Merge: Warn call on nullable receiver
[nit.git] / lib / serialization / caching.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Services for caching serialization engines
16 module caching
17
18 import serialization
19 private import engine_tools
20
21 # A `Serializer` with a `cache`
22 abstract class CachingSerializer
23 super Serializer
24
25 # Cache of known objects
26 var cache = new SerializerCache is lazy, writable
27
28 # Link the cache of `self` with `deserializer`
29 #
30 # This allows reference objects by id when they are known by the other side
31 # of the stream.
32 #
33 # Use `cache` if it is a `DuplexCache`, otherwise create a new one.
34 fun link(deserializer: CachingDeserializer)
35 do
36 var mem = self.cache
37 if not mem isa DuplexCache then mem = new DuplexCache
38
39 self.cache = mem
40 deserializer.cache = mem
41 end
42 end
43
44 # A `Deserializer` with a `cache`
45 abstract class CachingDeserializer
46 super Deserializer
47
48 # Cache of known objects
49 var cache = new DeserializerCache is lazy, writable
50 end
51
52 # Cache of sent objects
53 #
54 # Used by `Serializer` to avoid duplicating objects, by serializing them once,
55 # then using a reference.
56 class SerializerCache
57 # Map of already serialized objects to the reference id
58 private var sent: Map[Serializable, Int] = new StrictHashMap[Serializable, Int]
59
60 # Is `object` known?
61 fun has_object(object: Serializable): Bool do return sent.keys.has(object)
62
63 # Get the id for `object`
64 #
65 # Require: `has_object(object)`
66 fun id_for(object: Serializable): Int
67 do
68 assert sent.keys.has(object)
69 return sent[object]
70 end
71
72 # Get a new id for `object` and store it
73 #
74 # Require: `not has_object(object)`
75 fun new_id_for(object: Serializable): Int
76 do
77 var id = sent.length
78 sent[object] = id
79 return id
80 end
81 end
82
83 # Cache of received objects sorted by there reference id
84 #
85 # Used by `Deserializer` to find already deserialized objects by their reference.
86 class DeserializerCache
87 # Map of references to already deserialized objects.
88 private var received: Map[Int, Object] = new StrictHashMap[Int, Object]
89
90 # Is there an object associated to `id`?
91 fun has_id(id: Int): Bool do return received.keys.has(id)
92
93 # Get the object associated to `id`
94 fun object_for(id: Int): nullable Object do return received[id]
95
96 # Associate `object` to `id`
97 fun []=(id: Int, object: Object) do received[id] = object
98 end
99
100 # A shared cache for serialization and deserialization
101 class DuplexCache
102 super SerializerCache
103 super DeserializerCache
104
105 redef fun new_id_for(object)
106 do
107 var id = super
108 received[id] = object
109 return id
110 end
111
112 redef fun []=(id, object)
113 do
114 super
115 assert object isa Serializable
116 sent[object] = id
117 end
118 end