1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Copyright 2023 The Cordata Authors, except as waived below
// 
// Licensed under the CC0 Universal 1.0 License (the "CC0 License"), or the Apache License, Version
// 2.0 (the "Apache License"), at the licensee's discretion. You may obtain a copy of the CC0
// License at
// 
//     https://creativecommons.org/publicdomain/zero/1.0/legalcode
//
// You may obtain a copy of the Apache License at
//
//     https://www.apache.org/licenses/LICENSE-2.0    
//
// Unless required by applicable law or agreed to in writing, this software is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// Licenses for the specific language governing permissions and limitations under the Licenses.

use std::collections::BTreeMap;
use std::default::Default;

// UUIDs are way bigger than we need, and we do care about the size of
// this struct. If there were 10^9 nodes collaborating on the same
// document, 10 bytes give a ~10^-8  chance of a collision. With
// "only" 10^6 nodes collaborating, you get ~10^-13. And at that point,
// you'd need >10 megabytes to even store the vector clock.
// I'll take those odds.
#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ThreadId([u8; 10]);
// TODO: tricky question is whether we should try to avoid (simple) construction of specific
// NodeIds. Not allowing it could protect people from shooting themselves in the foot, but 
// we have to be very careful with the rest of the API to ensure that this is never necessary.

// How large do the ints in our version vectors need to be? The allegedly longest novel in the
// world is In Search of Lost Time, at ~10M characters. So you'd need to do the work of 400
// Prousts, all on the same computer, to overflow a u32. #[derive(Debug, Eq, PartialEq,
// PartialOrd)] struct VersionVector<N, V>(BTreeMap<N, V>);

// Thus, for now, a (compact) VersionVector is 14 bytes * node count. My guess is that a typical
// document will have less than, I dunno, order 1k editor nodes? Even if individual sessions get
// their own nodes, which is usually avoidable using browser / desktop local storage. So the
// version vector will be roughly 20KiB. I'm okay with this, as long as there's only a single
// version vector. And I think we can enforce this at the node level.
struct VersionVector<T, V>(BTreeMap<T, V>);

pub struct State<Operation, OperationId, ThreadId, LocalClock> {
    thread_id: ThreadId,
    version: VersionVector<ThreadId, LocalClock>,
    operations: BTreeMap<OperationId, Operation>,
}


// things we'll need from the user:
//  - a way to get an OperationId from an Operation

impl<Operation, OperationId, ThreadId, LocalClock> State<Operation, OperationId, ThreadId, LocalClock> {
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
    }
}