X-Git-Url: http://nitlanguage.org diff --git a/lib/serialization/serialization.nit b/lib/serialization/serialization.nit index e3ca6b3..f94445e 100644 --- a/lib/serialization/serialization.nit +++ b/lib/serialization/serialization.nit @@ -46,6 +46,7 @@ module serialization is new_annotation auto_serializable new_annotation serialize new_annotation noserialize + new_annotation serialize_as end # Abstract serialization service to be sub-classed by specialized services. @@ -87,26 +88,44 @@ end # Abstract deserialization service # -# After initialization of one of its sub-classes, call `deserialize` +# The main service is `deserialize`. abstract class Deserializer - # Main method of this class, returns a Nit object - fun deserialize: nullable Object is abstract + # 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` can be used as last resort if the deserialized object + # desn't have any metadata declaring the dynamic type. + # + # 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 - # Internal method to be implemented by sub-classes - fun deserialize_attribute(name: String): nullable Object is abstract + # Was the attribute queried by the last call to `deserialize_attribute` missing? + var deserialize_attribute_missing = false - # Internal method called by objects in creation, - # to be implemented by sub-classes + # 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` # - # Returns the deserialized object on success, aborts on error. + # 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: String): nullable Object do + if class_name == "Error" then return new Error.from_deserializer(self) return deserialize_class_intern(class_name) end @@ -137,10 +156,12 @@ abstract class Deserializer var errors = new Array[Error] end -# Deserialization got wrong attribute names +# Error on invalid dynamic type for a deserialized attribute class AttributeTypeError super Error + autoinit receiver, attribute_name, attribute, expected_type + # Parent object of the problematic attribute var receiver: Object @@ -153,8 +174,7 @@ class AttributeTypeError # Name of the type expected for `attribute` var expected_type: String - redef fun to_s - do + redef var message is lazy do var attribute = attribute var found_type = if attribute != null then attribute.class_name else "null" @@ -191,7 +211,7 @@ interface Serializable # 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) do end + init from_deserializer(deserializer: Deserializer) is nosuper do end end redef interface Object @@ -219,8 +239,8 @@ redef class Bool super DirectSerializable end redef class Char super DirectSerializable end redef class Int super DirectSerializable end redef class Float super DirectSerializable end -redef class NativeString super DirectSerializable end -redef class String 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 @@ -257,3 +277,25 @@ redef class Ref[E] 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