lib/makit/storage.rb



# frozen_string_literal: true


# This module provides classes for the Makit gem.

module Makit
  # This class provide methods for serializing and deserializing objects.

  #

  class Storage
    # declare a private class variable, connection_string

    attr_accessor :directory #= nil

    attr_accessor :protoc_json_serializer # = Makit::Serializer::new()

    attr_accessor :protoc_binary_serializer # = Makit::Serializer::new()


    def initialize(directory)
      @directory = directory
      @protoc_json_serializer = Makit::Serializer::new(Makit::Proto3Formats::JSON)
      @protoc_binary_serializer = Makit::Serializer::new(Makit::Proto3Formats::BINARY)
    end

    def save(object, key)
      #puts "=" * 80

      #puts "Saving object to storage"

      # puts "=" * 80

      raise "directory is nil" if @directory.nil?
      raise "Object is nil" if object.nil?
      raise "Key is nil" if key.nil?

      # get the fully qualfied type name of the object

      type_name = object.class.to_s
      #puts "Type name: #{type_name}"


      type_rel_dir = type_name.downcase.gsub("::", "/")
      #puts "Type relative directory: #{type_rel_dir}"


      # extract the file extension from the key

      file_extension = File.extname(key)
      #puts "File extension: #{file_extension}"


      serializer = nil
      if file_extension == ".json"
        serializer = @protoc_json_serializer
      elsif file_extension == ".pb"
        serializer = @protoc_binary_serializer
      else
        raise "Unknown file extension: #{file_extension}"
      end
      bytes = serializer.serialize(object)
      #puts "Serialized object size: #{bytes.size} bytes"


      rel_filename = File.join(type_rel_dir, "#{key}")
      #puts "Relative filename: #{rel_filename}"


      filename = File.join(@directory, rel_filename)
      #puts "Saving object to file: #{filename}"


      # make sure the file directory has been created

      FileUtils.mkdir_p(File.dirname(filename)) unless File.directory?(File.dirname(filename))
      # write the bytes to the file

      File.open(filename, "wb") do |file|
        file.write(bytes)
      end

      #puts "=" * 80

    end

    def load(type, key)
      raise "directory is nil" if @directory.nil?
      raise "Key is nil" if key.nil?

      # get the fully qualfied type name of the object

      type_name = type.to_s # object.class.to_s

      #puts "Type name: #{type_name}"


      type_rel_dir = type_name.downcase.gsub("::", "/")
      #puts "Type relative directory: #{type_rel_dir}"


      # extract the file extension from the key

      file_extension = File.extname(key)
      #puts "File extension: #{file_extension}"


      rel_filename = File.join(type_rel_dir, "#{key}")
      #puts "Relative filename: #{rel_filename}"


      filename = File.join(@directory, rel_filename)
      #puts "Loading object from file: #{filename}"


      # make sure the file exists

      raise "File does not exist: #{filename}" unless File.exist?(filename)

      # read the bytes from the file

      bytes = File.read(filename, mode: "rb")
      #puts "Read object from file: #{filename}"


      # extract the file extension from the key

      file_extension = File.extname(key)
      #puts "File extension: #{file_extension}"


      serializer = nil
      if file_extension == ".json"
        serializer = @protoc_json_serializer
      elsif file_extension == ".pb"
        serializer = @protoc_binary_serializer
      else
        raise "Unknown file extension: #{file_extension}"
      end

      # deserialize the object

      object = serializer.deserialize(type, bytes)
      #puts "Deserialized object size: #{bytes.size} bytes"


      # if the object type inherits from Google::Protobuf::AbstractMessage,

      # then serialize to protobuf json format

      #if object.is_a? Google::Protobuf::MessageExts

      #  puts "Serializing to protobuf json format"

      #  serialized_object = object.to_json

      #  pretty_json = JSON.pretty_generate(JSON.parse(serialized_object))

      #  puts pretty_json

      #else

      #  puts "Serializing to Marshal format"

      #  serialized_object = Marshal.dump(object)

      #end

      # serialize the object

      #serialized_object = Marshal.dump(object)


      # save the object to the storage

      # ...

      #puts "=" * 80


      object
    end
  end # class Storage

end # module Makit