This module declares the serialize
annotation to mark Nit classes as serializable.
For an introduction to this service, refer to the documentation of the serialization
group.
This documentation provides more technical information on interesting entitie of this module.
Interesting entities for end users of serializable classes:
Serializable
with either
Serializer::serializable
and Serializable::serialize
.Deserializer::deserialize
.
The object type must the be checked with an assert
or otherwise.Interesting entities to create custom serializable classes:
Serializable
to declare a class as serializable and to customize
the serialization and deserialization behavior.Serializable::core_serialize_to
to customize the serialization
of the receiver class.Deserializer::deserialize_class
to customize the deserialization
of a specific class by name.Interesting entities for serialization format:
Serializer
and Deserializer
with custom serices.Serializer
, serialize
and serialize_reference
must be redefined.Deserializer
; deserialize
, deserialize_attribute and
notify_of_creation` must be redefined.serialization :: AttributeError
Deserialization error related to an attribute ofreceiver
serialization :: AttributeMissingError
Missing attribute at deserializationserialization :: AttributeTypeError
Invalid dynamic type for a deserialized attributeserialization :: DirectSerializable
Instances of this class are not delayed and instead serialized immediatelySerializer::serialize
serialization :: serialization_core $ Couple
Two objects in a simple structure.serialization :: serialization_core $ Map
Maps are associative collections:key
-> item
.
serialization :: serialization_core $ MinHeap
A min-heap implemented over an arrayserialization :: serialization_core $ ProxyQueue
Factorize common proxy implementationserialization :: serialization_core $ Ref
A collection that contains only one item.serialization :: serialization_core $ SimpleCollection
Items can be added to these collections.serialization :: serialization_core $ Text
High-level abstraction for all text representationsserialization $ AttributeError
Deserialization error related to an attribute ofreceiver
serialization $ AttributeMissingError
Missing attribute at deserializationserialization $ AttributeTypeError
Invalid dynamic type for a deserialized attributeserialization :: serialization_core $ Couple
Two objects in a simple structure.serialization $ DirectSerializable
Instances of this class are not delayed and instead serialized immediatelyserialization :: serialization_core $ Map
Maps are associative collections:key
-> item
.
serialization :: serialization_core $ MinHeap
A min-heap implemented over an arrayserialization :: serialization_core $ ProxyQueue
Factorize common proxy implementationserialization :: serialization_core $ Ref
A collection that contains only one item.Serializer::serialize
serialization :: serialization_core $ SimpleCollection
Items can be added to these collections.serialization :: serialization_core $ Text
High-level abstraction for all text representationscore :: union_find
union–find algorithm using an efficient disjoint-set data structurenitc :: actors_generation_phase
Generate a support module for each module that contain a class annotated withis actor
nitc :: actors_injection_phase
Injects model for the classes annotated with "is actor" sonitc :: api_metrics
nitc :: astbuilder
Instantiation and transformation of semantic nodes in the AST of expressions and statementsbucketed_game :: bucketed_game
Game framework with an emphasis on efficient event coordinationcflags
and ldflags
to specify
accept_scroll_and_zoom
gamnit :: camera_control_android
Two fingers camera manipulation, pinch to zoom and slide to scrollgamnit :: camera_control_linux
Mouse wheel and middle mouse button to control cameranitc :: commands_ini
serialization :: custom_serialization
Example of an ad hoc serializer that is tailored to transform business specific objects into customized representation.nitc :: detect_variance_constraints
Collect metrics about detected variances constraints on formal types.extra_java_files
to compile extra java files
FileServer
action, which is a standard and minimal file server
HttpRequest
class and services to create it
app::http_request
main service AsyncHttpRequest
nitc :: i18n_phase
Basic support of internationalization through the generation of id-to-string tablesSerializable::inspect
to show more useful information
nitc :: light_only
Compiler support for the light FFI only, detects unsupported usage of callbacksnitc
.
nitc :: modelbuilder
more_collections :: more_collections
Highly specific, but useful, collections-related classes.mpi :: mpi_simple
app.nit
on Android using a custom Java entry point
nitcc_runtime :: nitcc_runtime
Runtime library required by parsers and lexers generated by nitccnitc :: nitmetrics
A program that collects various metrics on nit programs and librariesnitc :: nitrestful
Tool generating boilerplate code linking RESTful actions to Nit methodsnlp :: nlp_server
threaded
annotation
restful
annotation documented at lib/nitcorn/restful.nit
nitc :: separate_erasure_compiler
Separate compilation of a Nit program with generic type erasurenitc :: serialization_code_gen_phase
Phase generating methods (code) to serialize Nit objectsnitc :: serialization_model_phase
Phase generating methods (model-only) to serialize Nit objectsdeserialize_json
and JsonDeserializer
msgpack :: serialization_write
Serialize full Nit objects to MessagePack formatserialize_to_json
and JsonSerializer
root
to execute
EulerCamera
and App::frame_core_draw
to get a stereoscopic view
clone
method of the astbuilder tool
gamnit :: texture_atlas_parser
Tool to parse XML texture atlas and generated Nit code to access subtexturesnitc :: toolcontext
Common command-line tool infrastructure than handle options and error messagesnitc :: uml_module
Services for generation of a UML package diagram based on aModel
# Abstract services to serialize Nit objects to different formats
#
# This module declares the `serialize` annotation to mark Nit classes as serializable.
# For an introduction to this service, refer to the documentation of the `serialization` group.
# This documentation provides more technical information on interesting entitie of this module.
#
# Interesting entities for end users of serializable classes:
#
# * Serialize an instance subclass of `Serializable` with either
# `Serializer::serializable` and `Serializable::serialize`.
# * Deserialize an object using `Deserializer::deserialize`.
# The object type must the be checked with an `assert` or otherwise.
#
# Interesting entities to create custom serializable classes:
#
# * Subclass `Serializable` to declare a class as serializable and to customize
# the serialization and deserialization behavior.
# * Redefine `Serializable::core_serialize_to` to customize the serialization
# of the receiver class.
# * Redefine `Deserializer::deserialize_class` to customize the deserialization
# of a specific class by name.
#
# Interesting entities for serialization format:
#
# * Subclass `Serializer` and `Deserializer` with custom serices.
# * In `Serializer`, `serialize` and `serialize_reference` must be redefined.
# * In `Deserializer`; `deserialize`, `deserialize_attribute and
# `notify_of_creation` must be redefined.
module serialization_core is
new_annotation auto_serializable
new_annotation serialize
new_annotation noserialize
new_annotation serialize_as
end
intrude import core::queue
import meta
# Abstract serialization service to be sub-classed by specialized services.
interface Serializer
# Entry point method of this service, serialize the `object`
#
# This method, and refinements, should handle `null` and probably
# use double dispatch to customize the bahavior per serializable objects.
fun serialize(object: nullable Serializable) is abstract
# The object currently serialized by `serialized`
#
# Can be used by a custom serializer to add domain-specific serialization behavior.
protected fun current_object: nullable Object is abstract
# Serialize an object, with full serialization or a simple reference
protected fun serialize_reference(object: Serializable) is abstract
# Serialize an attribute to compose a serializable object
#
# This method should be called from `Serializable::core_serialize_to`.
fun serialize_attribute(name: String, value: nullable Object)
do
if not try_to_serialize(value) then
assert value != null # null would have been serialized
warn("argument {name} of type {value.class_name} is not serializable.")
end
end
# Serialize `value` is possible, i.e. it is `Serializable` or `null`
fun try_to_serialize(value: nullable Object): Bool
do
if value isa Serializable then
value.serialize_to_or_delay(self)
else if value == null then
serialize value
else return false
return true
end
# The method is called when a standard `value` is serialized
#
# The default behavior is to call `value.core_serialize_to(self)` but it
# can be redefined by a custom serializer to add domain-specific serialization behavior.
fun serialize_core(value: Serializable)
do
value.core_serialize_to(self)
end
# Warn of problems and potential errors (such as if an attribute
# is not serializable)
fun warn(msg: String) do print "Serialization warning: {msg}"
end
# Abstract deserialization service
#
# The main service is `deserialize`.
abstract class Deserializer
# Deserialize and return an object, storing errors in the attribute `errors`
#
# If a `static_type` is given, only subtypes of the `static_type` are accepted.
#
# This method behavior varies according to the implementation engines.
fun deserialize(static_type: nullable String): nullable Object is abstract
# Deserialize the attribute with `name` from the object open for deserialization
#
# The `static_type` restricts what kind of object can be deserialized.
#
# Return the deserialized value or null on error, and set
# `deserialize_attribute_missing` to whether the attribute was missing.
#
# Internal method to be implemented by the engines.
fun deserialize_attribute(name: String, static_type: nullable String): nullable Object is abstract
# Was the attribute queried by the last call to `deserialize_attribute` missing?
var deserialize_attribute_missing = false
# Register a newly allocated object (even if not completely built)
#
# Internal method called by objects in creation, to be implemented by the engines.
fun notify_of_creation(new_object: Object) is abstract
# Deserialize the next available object as an instance of `class_name`
#
# Return the deserialized object on success and
# record in `errors` if `class_name` is unknown.
#
# This method should be redefined for each custom subclass of `Serializable`.
# All refinement should look for a precise `class_name` and call super
# on unsupported classes.
protected fun deserialize_class(class_name: Text): nullable Object do
if class_name == "Error" then return new Error.from_deserializer(self)
return deserialize_class_intern(class_name)
end
# Generated service to deserialize the next available object as an instance of `class_name`
#
# Refinements to this method will be generated by the serialization phase.
# To avoid conflicts, there should not be any other refinements to this method.
# You can instead use `deserialize_class`.
protected fun deserialize_class_intern(class_name: Text): nullable Object do
errors.add new Error("Deserialization Error: Doesn't know how to deserialize class \"{class_name}\"")
return null
end
# Should `self` keep trying to deserialize an object after an error?
#
# This behavior takes effect after each attribute deserialization with
# errors such as a missing attribute or the value is of the wrong type.
# If `keep_going`, the attribute will be skipped but the engine will
# deserialize the next attribute.
# If `not keep_going`, the engine stops deserializing right away.
#
# When at `true`, this may cause the accumulation of a lot of entries in `errors`.
#
# Default at `true`.
var keep_going: nullable Bool = null is writable
# Errors encountered in the last call to `deserialize`
var errors = new Array[Error]
end
# Deserialization error related to an attribute of `receiver`
abstract class AttributeError
super Error
# Parent object of the problematic attribute
var receiver: Object
# Name of the problematic attribute in `receiver`
var attribute_name: String
end
# Invalid dynamic type for a deserialized attribute
class AttributeTypeError
super AttributeError
autoinit receiver, attribute_name, attribute, expected_type
# Deserialized object that isn't of the `expected_type`
var attribute: nullable Object
# Name of the type expected for `attribute`
var expected_type: String
redef var message is lazy do
var attribute = attribute
var found_type = if attribute != null then attribute.class_name else "null"
return "Deserialization Error: {
}Wrong type on `{receiver.class_name}::{attribute_name}` expected `{expected_type}`, got `{found_type}`"
end
end
# Missing attribute at deserialization
class AttributeMissingError
super AttributeError
autoinit receiver, attribute_name
redef var message is lazy do
return "Deserialization Error: Missing attribute `{receiver.class_name}::{attribute_name}`"
end
end
# Instances of this class can be passed to `Serializer::serialize`
interface Serializable
# Serialize `self` to `serializer`
#
# This is a shortcut to `Serializer::serialize`.
fun serialize_to(serializer: Serializer) do serializer.serialize(self)
# Actual serialization of `self` to `serializer`
#
# This writes the full data of `self` to `serializer`.
#
# This method can be redefined in sub classes and refinements.
# It should use `Serializer::serialize_attribute` to to register real or
# logical attributes.
#
# Any refinement should have its equivalent refinement of
# `Deserializer::deserialize_class` to support this custom deserialization.
fun core_serialize_to(serializer: Serializer) do end
# Accept references or force direct serialization (using `serialize_to`)
#
# The subclass change the default behavior, which will accept references,
# to force to always serialize copies of `self`.
private fun serialize_to_or_delay(v: Serializer) do v.serialize_reference(self)
# Create an instance of this class from the `deserializer`
#
# This constructor is refined by subclasses to correctly build their instances.
init from_deserializer(deserializer: Deserializer) is nosuper do end
end
# Instances of this class are not delayed and instead serialized immediately
# This applies mainly to `universal` types
interface DirectSerializable
super Serializable
redef fun serialize_to_or_delay(v) do serialize_to(v)
end
redef class Bool super DirectSerializable end
redef class Char super DirectSerializable end
redef class Byte super DirectSerializable end
redef class Int super DirectSerializable end
redef class Float super DirectSerializable end
redef class CString super DirectSerializable end
redef class Text super DirectSerializable end
redef class SimpleCollection[E] super Serializable end
redef class Map[K, V] super Serializable end
redef class Couple[F, S]
super Serializable
redef init from_deserializer(v)
do
v.notify_of_creation self
var first = v.deserialize_attribute("first")
var second = v.deserialize_attribute("second")
init(first, second)
end
redef fun core_serialize_to(v)
do
v.serialize_attribute("first", first)
v.serialize_attribute("second", second)
end
end
redef class Ref[E]
super Serializable
redef init from_deserializer(v)
do
v.notify_of_creation self
var item = v.deserialize_attribute("item")
init item
end
redef fun core_serialize_to(v)
do
v.serialize_attribute("item", first)
end
end
redef class Error
super Serializable
redef init from_deserializer(v)
do
v.notify_of_creation self
var message = v.deserialize_attribute("message")
if not message isa String then message = ""
init message
var cause = v.deserialize_attribute("cause")
if cause isa nullable Error then self.cause = cause
end
redef fun core_serialize_to(v)
do
v.serialize_attribute("message", message)
v.serialize_attribute("cause", cause)
end
end
# ---
# core::queue classes
redef abstract class ProxyQueue[E]
redef init from_deserializer(v)
do
v.notify_of_creation self
var seq = v.deserialize_attribute("seq", (new GetName[Sequence[E]]).to_s)
if not seq isa Sequence[E] then seq = new Array[E]
if v.deserialize_attribute_missing then
v.errors.add new AttributeMissingError(self, "seq")
end
init seq
end
redef fun core_serialize_to(v) do v.serialize_attribute("seq", seq)
end
redef class RandQueue[E]
redef init from_deserializer(v)
do
v.notify_of_creation self
var seq = v.deserialize_attribute("seq", (new GetName[SimpleCollection[E]]).to_s)
if not seq isa SimpleCollection[E] then seq = new Array[E]
if v.deserialize_attribute_missing then
v.errors.add new AttributeMissingError(self, "seq")
end
init seq
end
redef fun core_serialize_to(v) do v.serialize_attribute("seq", seq)
end
redef class MinHeap[E]
redef init from_deserializer(v)
do
v.notify_of_creation self
var items = v.deserialize_attribute("items", (new GetName[SimpleCollection[E]]).to_s)
if not items isa Array[E] then items = new Array[E]
if v.deserialize_attribute_missing then
v.errors.add new AttributeMissingError(self, "items")
end
var comparator = v.deserialize_attribute("comparator", "Comparator")
if not comparator isa Comparator then comparator = default_comparator
if v.deserialize_attribute_missing then
v.errors.add new AttributeMissingError(self, "comparator")
end
init comparator
self.items.add_all items
end
redef fun core_serialize_to(v)
do
v.serialize_attribute("items", items)
v.serialize_attribute("comparator", comparator)
end
end
lib/serialization/serialization_core.nit:17,1--390,3