Skip to content

Commit a753713

Browse files
committed
Add powersync_extract with blob support
1 parent f06dd35 commit a753713

File tree

10 files changed

+394
-106
lines changed

10 files changed

+394
-106
lines changed

crates/core/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ features = []
3535

3636

3737
[features]
38-
default = ["getrandom", "loadable_extension"]
38+
default = ["getrandom"]
3939

4040
loadable_extension = ["sqlite_nostd/loadable_extension"]
4141
static = ["sqlite_nostd/static"]

crates/core/src/bson/de.rs

+36-32
Original file line numberDiff line numberDiff line change
@@ -40,44 +40,51 @@ impl<'de> Deserializer<'de> {
4040
/// document without actually inspecting the structure of that document.
4141
pub const SPECIAL_CASE_EMBEDDED_DOCUMENT: &'static str = "\0SpecialCaseEmbedDoc";
4242

43-
pub fn outside_of_document(parser: Parser<'de>) -> Self {
43+
fn outside_of_document(parser: Parser<'de>) -> Self {
4444
Self {
4545
parser,
4646
position: DeserializerPosition::OutsideOfDocument,
4747
}
4848
}
4949

50-
/// Prepares to read a value without actually reading it, returning the [ElementType] of the
51-
/// upcoming key-value pair.
52-
fn prepare_to_read_value(&mut self) -> Result<ElementType, BsonError> {
50+
pub fn from_bytes(bytes: &'de [u8]) -> Self {
51+
let parser = Parser::new(bytes);
52+
Self::outside_of_document(parser)
53+
}
54+
55+
fn prepare_to_read(&mut self, allow_key: bool) -> Result<KeyOrValue<'de>, BsonError> {
5356
match self.position.clone() {
5457
DeserializerPosition::OutsideOfDocument => {
5558
// The next value we're reading is a document
5659
self.position = DeserializerPosition::BeforeValue {
5760
pending_type: ElementType::Document,
5861
};
59-
Ok(ElementType::Document)
62+
Ok(KeyOrValue::PendingValue(ElementType::Document))
63+
}
64+
DeserializerPosition::BeforeValue { pending_type } => {
65+
Ok(KeyOrValue::PendingValue(pending_type))
6066
}
61-
DeserializerPosition::BeforeValue { pending_type } => Ok(pending_type),
6267
DeserializerPosition::BeforeTypeOrAtEndOfDocument { .. } => {
6368
Err(self.parser.error(ErrorKind::InvalidStateExpectedType))
6469
}
65-
DeserializerPosition::BeforeName { .. } => {
66-
Err(self.parser.error(ErrorKind::InvalidStateExpectedName))
67-
}
68-
}
69-
}
70-
71-
/// If the deserializer is in a suitable position, read the upcoming key.
72-
fn read_entry_key(&mut self) -> Result<Option<&'de str>, BsonError> {
73-
match self.position.clone() {
7470
DeserializerPosition::BeforeName { pending_type } => {
71+
if !allow_key {
72+
return Err(self.parser.error(ErrorKind::InvalidStateExpectedName));
73+
}
74+
7575
self.position = DeserializerPosition::BeforeValue {
7676
pending_type: pending_type,
7777
};
78-
Ok(Some(self.parser.read_cstr()?))
78+
Ok(KeyOrValue::Key(self.parser.read_cstr()?))
7979
}
80-
_ => Ok(None),
80+
}
81+
}
82+
83+
fn prepare_to_read_value(&mut self) -> Result<ElementType, BsonError> {
84+
let result = self.prepare_to_read(false)?;
85+
match result {
86+
KeyOrValue::Key(_) => unreachable!(),
87+
KeyOrValue::PendingValue(element_type) => Ok(element_type),
8188
}
8289
}
8390

@@ -113,7 +120,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
113120
where
114121
V: Visitor<'de>,
115122
{
116-
let element_type = self.prepare_to_read_value()?;
123+
let element_type = match self.prepare_to_read(true)? {
124+
KeyOrValue::Key(name) => return visitor.visit_borrowed_str(name),
125+
KeyOrValue::PendingValue(element_type) => element_type,
126+
};
117127

118128
match element_type {
119129
ElementType::Double => visitor.visit_f64(self.parser.read_double()?),
@@ -133,24 +143,13 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
133143
ElementType::ObjectId => todo!(),
134144
ElementType::Boolean => visitor.visit_bool(self.parser.read_bool()?),
135145
ElementType::DatetimeUtc => todo!(),
136-
ElementType::Null | ElementType::Undefined => visitor.visit_none(),
146+
ElementType::Null | ElementType::Undefined => visitor.visit_unit(),
137147
ElementType::Int32 => visitor.visit_i32(self.parser.read_int32()?),
138148
ElementType::Int64 => visitor.visit_i64(self.parser.read_int64()?),
139149
ElementType::Timestamp => todo!(),
140150
}
141151
}
142152

143-
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
144-
where
145-
V: Visitor<'de>,
146-
{
147-
let Some(key) = self.read_entry_key()? else {
148-
return Err(self.parser.error(ErrorKind::InvalidStateExpectedName));
149-
};
150-
151-
visitor.visit_borrowed_str(key)
152-
}
153-
154153
fn deserialize_enum<V>(
155154
self,
156155
name: &'static str,
@@ -200,7 +199,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
200199
forward_to_deserialize_any! {
201200
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
202201
bytes byte_buf unit unit_struct newtype_struct seq tuple
203-
tuple_struct map struct ignored_any
202+
tuple_struct map struct ignored_any identifier
204203
}
205204
}
206205

@@ -239,7 +238,7 @@ impl<'de> SeqAccess<'de> for Deserializer<'de> {
239238

240239
// Skip name
241240
debug_assert_matches!(self.position, DeserializerPosition::BeforeName { .. });
242-
self.read_entry_key()?;
241+
self.prepare_to_read(true)?;
243242

244243
// And deserialize value!
245244
Ok(Some(seed.deserialize(self)?))
@@ -303,3 +302,8 @@ impl<'a, 'de> VariantAccess<'de> for &'a mut Deserializer<'de> {
303302
de::Deserializer::deserialize_map(self, visitor)
304303
}
305304
}
305+
306+
enum KeyOrValue<'de> {
307+
Key(&'de str),
308+
PendingValue(ElementType),
309+
}

crates/core/src/bson/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ mod writer;
1111

1212
/// Deserializes BSON [bytes] into a structure [T].
1313
pub fn from_bytes<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, BsonError> {
14-
let parser = Parser::new(bytes);
15-
let mut deserializer = Deserializer::outside_of_document(parser);
14+
let mut deserializer = Deserializer::from_bytes(bytes);
1615

1716
T::deserialize(&mut deserializer)
1817
}

0 commit comments

Comments
 (0)