1 /** 2 * Copyright: Copyright (c) 2010-2011 Jacob Carlborg. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: Jan 26, 2010 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module orange.serialization.Serializable; 8 9 import orange.core.Attribute; 10 import orange.serialization.archives.Archive; 11 import orange.serialization.Events; 12 import orange.serialization.Serializer; 13 import orange.util.CTFE; 14 15 /** 16 * This interface represents a type that this is serializable. To implement this interface 17 * the user needs to implement two methods, one for serialization and one for 18 * deserialization. These methods are used to perform custom (de)serialization and will 19 * be called if available. It's up to these methods to call the serializer to perform 20 * the (de)serialization. If these methods are available the automatic (de)serialization 21 * process $(I will not) be performed. 22 * 23 * These methods can also be used without actually implementing this interface, i.e. they 24 * also work for structs. 25 * 26 * Examples: 27 * --- 28 * class Foo : Serializable 29 * { 30 * int a; 31 * 32 * void toData (Serializer serializer, Serializer.Data key) 33 * { 34 * serializer.serialize(a, "b"); 35 * } 36 * 37 * void fromData (Serializer serializer, Serializer.Data key) 38 * { 39 * a = serializer.deserialize!(int)("b"); 40 * } 41 * } 42 * --- 43 * 44 * See_Also: isSerializable 45 */ 46 interface Serializable 47 { 48 /** 49 * Called by the given serializer when performing custom serialization. 50 * 51 * Params: 52 * serializer = the serializer that performs the serialization 53 * key = the key of the receiver 54 */ 55 void toData (Serializer serializer, Serializer.Data key); 56 57 /** 58 * Called by the given serializer when performing custom deserialization. 59 * 60 * Params: 61 * serializer = the serializer that performs the deserialization 62 * key = the key of the receiver 63 */ 64 void fromData (Serializer serializer, Serializer.Data key); 65 } 66 67 /** 68 * This interface represents a type that this is serializable. To implement this interface 69 * Evaluates to $(D_KEYWORD true) if the given type is serializable. A type is considered 70 * serializable when it implements to two methods in the Serializable interface. 71 * Note that the type does not have to implement the actual interface, i.e. it also works 72 * for structs. 73 * 74 * Examples: 75 * --- 76 * struct Foo 77 * { 78 * int a; 79 * 80 * void toData (Serializer serializer, Serializer.Data key) 81 * { 82 * serializer.serialize(a, "b"); 83 * } 84 * 85 * void fromData (Serializer serializer, Serializer.Data key) 86 * { 87 * a = serializer.deserialize!(int)("b"); 88 * } 89 * } 90 * 91 * static assert(isSerializable!(Foo)); 92 * --- 93 * 94 * See_Also: Serializable 95 */ 96 template isSerializable (T) 97 { 98 enum isSerializable = is(T : Serializable) || ( 99 is(typeof(T.toData(Serializer.init, Serializer.Data.init))) && 100 is(typeof(T.fromData(Serializer.init, Serializer.Data.init)))); 101 } 102 103 /** 104 * This template is used to indicate that one or several fields should not be 105 * (de)serialized. If no fields or "this" is specified, it indicates that the whole 106 * class/struct should not be (de)serialized. 107 * 108 * This template is used as a mixin. 109 * 110 * Examples: 111 * --- 112 * class Foo 113 * { 114 * int a; 115 * int b; 116 * 117 * mixin NonSerialized!(b); // "b" will not be (de)serialized 118 * } 119 * 120 * struct Bar 121 * { 122 * int a; 123 * int b; 124 * 125 * mixin NonSerialized; // "Bar" will not be (de)serialized 126 * } 127 * --- 128 */ 129 template NonSerialized (Fields ...) 130 { 131 static if (Fields.length == 0) 132 static enum __nonSerialized = ["this"[]]; 133 134 else 135 static enum __nonSerialized = toArray!(Fields)(); 136 } 137 138 /// Indicates that the declaration this attribute is attached to should not be (de)serialized. 139 @attribute struct nonSerialized { } 140 141 struct NonSerializedField (string name) 142 { 143 enum field = name; 144 } 145 146 /* 147 * Converts a tuple of aliases to an array of strings containing the names of the given 148 * aliases. 149 * 150 * Examples: 151 * --- 152 * int a; 153 * int b; 154 * 155 * enum names = toArray!(a, b); 156 * 157 * static assert(names == ["a", "b"]); 158 * --- 159 * 160 * Returns: an array containing the names of the given aliases 161 */ 162 template toArray (Args ...) 163 { 164 static string[] toArray () 165 { 166 string[] args; 167 168 foreach (i, _ ; typeof(Args)) 169 args ~= Args[i].stringof; 170 171 return args; 172 } 173 } 174 175 package: 176 177 enum nonSerializedField = "__nonSerialized"; 178 enum serializedField = "__serialized"; 179 enum internalFields = [nonSerializedField[], onDeserializedField, onDeserializingField, onSerializedField, onSerializingField];