You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
4.7 KiB
196 lines
4.7 KiB
//! Data structures for the in-memory map.
|
|
use super::*;
|
|
use std::{
|
|
collections::HashMap,
|
|
borrow::Cow,
|
|
error,
|
|
fmt,
|
|
};
|
|
use generational_arena::{
|
|
Arena, Index,
|
|
};
|
|
use bitflags::bitflags;
|
|
use cryptohelpers::{
|
|
rsa::{
|
|
RsaPublicKey, RsaPrivateKey,
|
|
Signature,
|
|
},
|
|
aes::{self, AesKey,},
|
|
sha256::Sha256Hash,
|
|
};
|
|
use tokio::io::{
|
|
AsyncRead, AsyncWrite,
|
|
};
|
|
|
|
/// An absolute (nested) index
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
pub struct AbsoluteIndex(Vec<Index>);
|
|
|
|
/// Possible value types of the data map
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub enum Data
|
|
{
|
|
Byte(u8),
|
|
Char(char),
|
|
Bool(bool),
|
|
|
|
/// Signed integer
|
|
SI(i64),
|
|
/// Unsigned integer
|
|
UI(u64),
|
|
/// Floating-point integer
|
|
FI(f64),
|
|
|
|
/// A UTF-8 text string
|
|
Text(String),
|
|
/// A binary blob
|
|
Binary(Vec<u8>),
|
|
|
|
/// A reference index to an item within the same `Datamap` as this one.
|
|
RelativeRef(Index),
|
|
/// A reference to an item N deep within nested `Map` elements.
|
|
///
|
|
/// The first `Index` specifies the `Map` data item at the root `Datamap` that contains the next, et cetera. The pointed to value is the last index.
|
|
AbsoluteRef(AbsoluteIndex),
|
|
|
|
/// A list of atoms
|
|
List(Vec<Atom>),
|
|
/// Another datamap
|
|
Map(Datamap),
|
|
|
|
/// An AES key
|
|
AesKey(AesKey),
|
|
/// An RSA keypair
|
|
RsaKeypair(RsaPrivateKey, RsaPublicKey),
|
|
/// An RSA private key
|
|
RsaPrivate(RsaPrivateKey),
|
|
/// An RSA public key
|
|
RsaPublic(RsaPublicKey),
|
|
|
|
/// A SHA256 hash
|
|
Hash(Sha256Hash),
|
|
|
|
/// A unique ID
|
|
Uuid(uuid::Uuid),
|
|
|
|
/// An RSA signature
|
|
Signature(Signature),
|
|
|
|
/// Nothing
|
|
Null,
|
|
}
|
|
|
|
/// An entry that may or may not be encrypted
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub enum MaybeEncrypted
|
|
{
|
|
/// This is an encrypted serialized `Data`.
|
|
Encrypted(Vec<u8>),
|
|
/// An unencrypted `Data`
|
|
Unencrypted(Data),
|
|
}
|
|
|
|
submod!(encryption; "impl for `MaybeEncrypted`. \
|
|
Other `Data` encryption helpers");
|
|
|
|
bitflags! {
|
|
/// And additional metadata for values
|
|
#[derive(Serialize, Deserialize)]
|
|
struct Tags: u16
|
|
{
|
|
/// Default
|
|
const NONE = 0;
|
|
/// This value should be cloned on write unless specified elsewhere.
|
|
const COW = 1<<0;
|
|
/// This should not show up in searches.
|
|
const HIDDEN = 1<<1;
|
|
/// Versioning is enabled for this value.
|
|
///
|
|
/// When it is deleted, it should instead be moved away into a sperate entry.
|
|
const VERSIONED = 1<<2;
|
|
}
|
|
}
|
|
|
|
/// Information about a map entry.
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub struct Info
|
|
{
|
|
alt_name: Option<(String, String)>,
|
|
|
|
created: u64,
|
|
modified: u64,
|
|
|
|
tags: Tags,
|
|
|
|
/// Events to be emitted to `State` when this element does something.
|
|
///
|
|
/// Can be used for monitoring or logging and such.
|
|
hooks: event::Hooks,
|
|
|
|
owner: Option<Vec<user::EntityID>>, //starts as the user that created (i.e. same as `created_by`), or `None` if ownership is disabled
|
|
signed: Option<Vec<Signature>>,
|
|
|
|
perms: user::Permissions,
|
|
|
|
created_by: user::UserID,
|
|
log: Vec<event::InBandEvent>,
|
|
}
|
|
|
|
/// The root data containing map
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct Datamap
|
|
{
|
|
data: Arena<Atom>,
|
|
ident: HashMap<Identifier, Index>,
|
|
}
|
|
|
|
impl PartialEq for Datamap
|
|
{
|
|
fn eq(&self, other: &Self) -> bool
|
|
{
|
|
self.ident == other.ident && {
|
|
for (v1, v2) in self.ident.iter().map(|(_, v)| (self.data.get(*v), other.data.get(*v)))
|
|
{
|
|
if v1 != v2 {
|
|
return false;
|
|
}
|
|
}
|
|
true
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A value in a datamap, contains the information about the value and the value itself.
|
|
///
|
|
/// May also contain previous versions of this atom.
|
|
///
|
|
/// # Note
|
|
/// `Atom` boxes most of itself. It's not needed to box `Atom` itself.
|
|
// Box these first two together, since they are hueg.
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub struct Atom(Box<(MaybeEncrypted, Info)>, Vec<Atom>);
|
|
|
|
/// An identifier for an item in a `Datamap`, or an item nested within many `Datamap`s.
|
|
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
|
pub struct Identifier(String);
|
|
|
|
#[cfg(test)]
|
|
mod tests
|
|
{
|
|
#[test]
|
|
fn data_me_sync()
|
|
{
|
|
let data = super::Data::SI(-120);
|
|
let aes = super::aes::AesKey::generate().unwrap();
|
|
|
|
println!("Data: {:?}", data);
|
|
let enc = super::MaybeEncrypted::new_encrypted(data.clone(), &aes).expect("Couldn't encrypt");
|
|
println!("M/Enc: {:?}", enc);
|
|
let dec = enc.clone().into_unencrypted(Some(&aes)).expect("Couldn't decrypt");
|
|
println!("M/Dec: {:?}", dec);
|
|
let out = dec.into_data(Some(&aes)).unwrap();
|
|
|
|
assert_eq!(data, out);
|
|
}
|
|
}
|