Internal representation = base64 string

This commit is contained in:
Vedant Roy 2021-05-18 13:54:26 -07:00 committed by Orion Henry
parent 41021f398f
commit 22af56b059
9 changed files with 19 additions and 21 deletions
automerge-backend/src
automerge-frontend
automerge-protocol/src
lib.rs
serde_impls

View file

@ -574,12 +574,7 @@ impl ValEncoder {
amp::ScalarValue::Null => self.len.append_value(VALUE_TYPE_NULL),
amp::ScalarValue::Boolean(true) => self.len.append_value(VALUE_TYPE_TRUE),
amp::ScalarValue::Boolean(false) => self.len.append_value(VALUE_TYPE_FALSE),
amp::ScalarValue::Bytes(bytes) => {
let len = bytes.len();
self.raw.extend(bytes);
self.len.append_value(len << 4 | VALUE_TYPE_BYTES)
}
amp::ScalarValue::Str(s) => {
amp::ScalarValue::Str(s) | amp::ScalarValue::Bytes(s) => {
let bytes = s.as_bytes();
let len = bytes.len();
self.raw.extend(bytes);

View file

@ -19,6 +19,7 @@ thiserror = "1.0.16"
im-rc = "15.0.0"
unicode-segmentation = "1.7.1"
arbitrary = { version = "1", features = ["derive"], optional = true }
base64 = "0.13.0"
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
getrandom = { version = "0.2.2", features=["js"] }

View file

@ -2,6 +2,7 @@ use std::{error::Error, fmt};
use automerge_protocol as amp;
use automerge_protocol::ObjectId;
use base64::DecodeError;
use thiserror::Error;
use crate::{value::Value, Path};
@ -80,6 +81,8 @@ pub enum InvalidPatch {
DiffEditWithHeadElemId,
#[error("Value diff containing cursor")]
ValueDiffContainedCursor,
#[error("Base64 decoding error: {0} for string: \"{1}\"")]
InvalidBase64(DecodeError, String),
}
#[derive(Error, Debug, PartialEq)]

View file

@ -2,6 +2,7 @@ use std::{collections::HashMap, convert::TryInto};
use amp::{MapDiff, ObjectId};
use automerge_protocol as amp;
use base64;
use crate::{error, Cursor, Path, PathElement, Primitive, Value};
@ -508,7 +509,10 @@ impl StateTreeValue {
match diff.diff {
amp::Diff::Value(v) => {
let value = match v {
amp::ScalarValue::Bytes(b) => Primitive::Bytes(b.clone()),
amp::ScalarValue::Bytes(b) => match base64::decode(b) {
Ok(bytes) => Primitive::Bytes(bytes),
Err(e) => return Err(error::InvalidPatch::InvalidBase64(e, b.clone())),
},
amp::ScalarValue::Str(s) => Primitive::Str(s.clone()),
amp::ScalarValue::Int(i) => Primitive::Int(*i),
amp::ScalarValue::Uint(u) => Primitive::Uint(*u),

View file

@ -1,6 +1,7 @@
use std::{cmp::Ordering, iter::Iterator};
use automerge_protocol as amp;
use base64;
use unicode_segmentation::UnicodeSegmentation;
use super::{
@ -676,7 +677,7 @@ where
_ => Cursors::new(),
};
let value = match primitive {
Primitive::Bytes(b) => amp::ScalarValue::Bytes(b.clone()),
Primitive::Bytes(b) => amp::ScalarValue::Bytes(base64::encode(b)),
Primitive::Str(s) => amp::ScalarValue::Str(s.clone()),
Primitive::Int(i) => amp::ScalarValue::Int(*i),
Primitive::Uint(u) => amp::ScalarValue::Uint(*u),

View file

@ -1,6 +1,7 @@
use std::{borrow::Borrow, collections::HashMap};
use automerge_protocol as amp;
use base64;
use serde::Serialize;
#[derive(Serialize, Clone, Debug, PartialEq)]
@ -66,7 +67,7 @@ impl From<Cursor> for Value {
impl From<&Primitive> for amp::ScalarValue {
fn from(p: &Primitive) -> Self {
match p {
Primitive::Bytes(b) => amp::ScalarValue::Bytes(b.clone()),
Primitive::Bytes(b) => amp::ScalarValue::Bytes(base64::encode(b)),
Primitive::Str(s) => amp::ScalarValue::Str(s.clone()),
Primitive::Int(i) => amp::ScalarValue::Int(*i),
Primitive::Uint(u) => amp::ScalarValue::Uint(*u),
@ -182,11 +183,7 @@ impl Value {
),
Primitive::Uint(n) => serde_json::Value::Number(serde_json::Number::from(*n)),
Primitive::Int(n) => serde_json::Value::Number(serde_json::Number::from(*n)),
Primitive::Bytes(b) => serde_json::Value::Array(
b.iter()
.map(|byte| serde_json::Value::Number(serde_json::Number::from(*byte)))
.collect(),
),
Primitive::Bytes(b) => serde_json::Value::String(base64::encode(b)),
Primitive::Str(s) => serde_json::Value::String(s.to_string()),
Primitive::Boolean(b) => serde_json::Value::Bool(*b),
Primitive::Counter(c) => serde_json::Value::Number(serde_json::Number::from(*c)),

View file

@ -107,7 +107,7 @@ fn test_set_bytes() {
hash: None,
deps: Vec::new(),
operations: vec![amp::Op {
action: amp::OpType::Set(amp::ScalarValue::Bytes(vec![1, 2, 3])),
action: amp::OpType::Set(amp::ScalarValue::Bytes("AQID".into())),
obj: "_root".try_into().unwrap(),
key: "bird".into(),
insert: false,

View file

@ -222,7 +222,7 @@ impl DataType {
#[derive(Serialize, PartialEq, Debug, Clone)]
#[serde(untagged)]
pub enum ScalarValue {
Bytes(Vec<u8>),
Bytes(String),
Str(String),
Int(i64),
Uint(u64),
@ -254,7 +254,7 @@ impl ScalarValue {
(DataType::Bytes, ScalarValue::Bytes(bytes)) => Ok(ScalarValue::Bytes(bytes.clone())),
(DataType::Bytes, v) => Err(error::InvalidScalarValue {
raw_value: self.clone(),
expected: "a vec of bytes".to_string(),
expected: "a base64 encoded string of bytes".to_string(),
unexpected: v.to_string(),
datatype,
}),

View file

@ -171,10 +171,7 @@ impl<'de> Deserialize<'de> for Op {
Some(ScalarValue::F32(n)) => Ok(OpType::Inc(n as i64)),
Some(ScalarValue::Counter(n)) => Ok(OpType::Inc(n)),
Some(ScalarValue::Timestamp(n)) => Ok(OpType::Inc(n)),
Some(ScalarValue::Bytes(b)) => {
Err(Error::invalid_value(Unexpected::Bytes(&b), &"a number"))
}
Some(ScalarValue::Str(s)) => {
Some(ScalarValue::Str(s) | ScalarValue::Bytes(s)) => {
Err(Error::invalid_value(Unexpected::Str(&s), &"a number"))
}
Some(ScalarValue::Boolean(b)) => {