aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/de.rs2
-rw-r--r--src/lib.rs7
-rw-r--r--src/libyaml/emitter.rs11
-rw-r--r--src/libyaml/error.rs26
-rw-r--r--src/libyaml/parser.rs29
-rw-r--r--src/mapping.rs120
-rw-r--r--src/number.rs28
7 files changed, 153 insertions, 70 deletions
diff --git a/src/de.rs b/src/de.rs
index 43f4678..566f5f0 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -1079,7 +1079,7 @@ pub(crate) fn parse_f64(scalar: &str) -> Option<f64> {
return Some(f64::NEG_INFINITY);
}
if let ".nan" | ".NaN" | ".NAN" = scalar {
- return Some(f64::NAN);
+ return Some(f64::NAN.copysign(1.0));
}
if let Ok(float) = unpositive.parse::<f64>() {
if float.is_finite() {
diff --git a/src/lib.rs b/src/lib.rs
index d5256d4..7afcf93 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -115,8 +115,8 @@
//! }
//! ```
-#![doc(html_root_url = "https://docs.rs/serde_yaml/0.9.25")]
-#![deny(missing_docs)]
+#![doc(html_root_url = "https://docs.rs/serde_yaml/0.9.31")]
+#![deny(missing_docs, unsafe_op_in_unsafe_fn)]
// Suppressed clippy_pedantic lints
#![allow(
// buggy
@@ -134,11 +134,10 @@
clippy::match_same_arms,
clippy::module_name_repetitions,
clippy::needless_pass_by_value,
- clippy::option_if_let_else,
clippy::redundant_else,
clippy::single_match_else,
// code is acceptable
- clippy::blocks_in_if_conditions,
+ clippy::blocks_in_conditions,
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_precision_loss,
diff --git a/src/libyaml/emitter.rs b/src/libyaml/emitter.rs
index a0ce25f..686f06e 100644
--- a/src/libyaml/emitter.rs
+++ b/src/libyaml/emitter.rs
@@ -197,13 +197,14 @@ impl<'a> Emitter<'a> {
unsafe fn write_handler(data: *mut c_void, buffer: *mut u8, size: u64) -> i32 {
let data = data.cast::<EmitterPinned>();
- match io::Write::write_all(
- &mut *(*data).write,
- slice::from_raw_parts(buffer, size as usize),
- ) {
+ match io::Write::write_all(unsafe { &mut *(*data).write }, unsafe {
+ slice::from_raw_parts(buffer, size as usize)
+ }) {
Ok(()) => 1,
Err(err) => {
- (*data).write_error = Some(err);
+ unsafe {
+ (*data).write_error = Some(err);
+ }
0
}
}
diff --git a/src/libyaml/error.rs b/src/libyaml/error.rs
index 603557d..8397f6e 100644
--- a/src/libyaml/error.rs
+++ b/src/libyaml/error.rs
@@ -18,41 +18,41 @@ pub(crate) struct Error {
impl Error {
pub unsafe fn parse_error(parser: *const sys::yaml_parser_t) -> Self {
Error {
- kind: (*parser).error,
- problem: match NonNull::new((*parser).problem as *mut _) {
- Some(problem) => CStr::from_ptr(problem),
+ kind: unsafe { (*parser).error },
+ problem: match NonNull::new(unsafe { (*parser).problem as *mut _ }) {
+ Some(problem) => unsafe { CStr::from_ptr(problem) },
None => CStr::from_bytes_with_nul(b"libyaml parser failed but there is no error\0"),
},
- problem_offset: (*parser).problem_offset,
+ problem_offset: unsafe { (*parser).problem_offset },
problem_mark: Mark {
- sys: (*parser).problem_mark,
+ sys: unsafe { (*parser).problem_mark },
},
- context: match NonNull::new((*parser).context as *mut _) {
- Some(context) => Some(CStr::from_ptr(context)),
+ context: match NonNull::new(unsafe { (*parser).context as *mut _ }) {
+ Some(context) => Some(unsafe { CStr::from_ptr(context) }),
None => None,
},
context_mark: Mark {
- sys: (*parser).context_mark,
+ sys: unsafe { (*parser).context_mark },
},
}
}
pub unsafe fn emit_error(emitter: *const sys::yaml_emitter_t) -> Self {
Error {
- kind: (*emitter).error,
- problem: match NonNull::new((*emitter).problem as *mut _) {
- Some(problem) => CStr::from_ptr(problem),
+ kind: unsafe { (*emitter).error },
+ problem: match NonNull::new(unsafe { (*emitter).problem as *mut _ }) {
+ Some(problem) => unsafe { CStr::from_ptr(problem) },
None => {
CStr::from_bytes_with_nul(b"libyaml emitter failed but there is no error\0")
}
},
problem_offset: 0,
problem_mark: Mark {
- sys: MaybeUninit::<sys::yaml_mark_t>::zeroed().assume_init(),
+ sys: unsafe { MaybeUninit::<sys::yaml_mark_t>::zeroed().assume_init() },
},
context: None,
context_mark: Mark {
- sys: MaybeUninit::<sys::yaml_mark_t>::zeroed().assume_init(),
+ sys: unsafe { MaybeUninit::<sys::yaml_mark_t>::zeroed().assume_init() },
},
}
}
diff --git a/src/libyaml/parser.rs b/src/libyaml/parser.rs
index ae8f375..3492edd 100644
--- a/src/libyaml/parser.rs
+++ b/src/libyaml/parser.rs
@@ -110,15 +110,16 @@ unsafe fn convert_event<'input>(
sys::YAML_STREAM_END_EVENT => Event::StreamEnd,
sys::YAML_DOCUMENT_START_EVENT => Event::DocumentStart,
sys::YAML_DOCUMENT_END_EVENT => Event::DocumentEnd,
- sys::YAML_ALIAS_EVENT => Event::Alias(optional_anchor(sys.data.alias.anchor).unwrap()),
+ sys::YAML_ALIAS_EVENT => {
+ Event::Alias(unsafe { optional_anchor(sys.data.alias.anchor) }.unwrap())
+ }
sys::YAML_SCALAR_EVENT => Event::Scalar(Scalar {
- anchor: optional_anchor(sys.data.scalar.anchor),
- tag: optional_tag(sys.data.scalar.tag),
- value: Box::from(slice::from_raw_parts(
- sys.data.scalar.value,
- sys.data.scalar.length as usize,
- )),
- style: match sys.data.scalar.style {
+ anchor: unsafe { optional_anchor(sys.data.scalar.anchor) },
+ tag: unsafe { optional_tag(sys.data.scalar.tag) },
+ value: Box::from(unsafe {
+ slice::from_raw_parts(sys.data.scalar.value, sys.data.scalar.length as usize)
+ }),
+ style: match unsafe { sys.data.scalar.style } {
sys::YAML_PLAIN_SCALAR_STYLE => ScalarStyle::Plain,
sys::YAML_SINGLE_QUOTED_SCALAR_STYLE => ScalarStyle::SingleQuoted,
sys::YAML_DOUBLE_QUOTED_SCALAR_STYLE => ScalarStyle::DoubleQuoted,
@@ -133,13 +134,13 @@ unsafe fn convert_event<'input>(
},
}),
sys::YAML_SEQUENCE_START_EVENT => Event::SequenceStart(SequenceStart {
- anchor: optional_anchor(sys.data.sequence_start.anchor),
- tag: optional_tag(sys.data.sequence_start.tag),
+ anchor: unsafe { optional_anchor(sys.data.sequence_start.anchor) },
+ tag: unsafe { optional_tag(sys.data.sequence_start.tag) },
}),
sys::YAML_SEQUENCE_END_EVENT => Event::SequenceEnd,
sys::YAML_MAPPING_START_EVENT => Event::MappingStart(MappingStart {
- anchor: optional_anchor(sys.data.mapping_start.anchor),
- tag: optional_tag(sys.data.mapping_start.tag),
+ anchor: unsafe { optional_anchor(sys.data.mapping_start.anchor) },
+ tag: unsafe { optional_tag(sys.data.mapping_start.tag) },
}),
sys::YAML_MAPPING_END_EVENT => Event::MappingEnd,
sys::YAML_NO_EVENT => unreachable!(),
@@ -149,13 +150,13 @@ unsafe fn convert_event<'input>(
unsafe fn optional_anchor(anchor: *const u8) -> Option<Anchor> {
let ptr = NonNull::new(anchor as *mut i8)?;
- let cstr = CStr::from_ptr(ptr);
+ let cstr = unsafe { CStr::from_ptr(ptr) };
Some(Anchor(Box::from(cstr.to_bytes())))
}
unsafe fn optional_tag(tag: *const u8) -> Option<Tag> {
let ptr = NonNull::new(tag as *mut i8)?;
- let cstr = CStr::from_ptr(ptr);
+ let cstr = unsafe { CStr::from_ptr(ptr) };
Some(Tag(Box::from(cstr.to_bytes())))
}
diff --git a/src/mapping.rs b/src/mapping.rs
index fe8d509..b1341a6 100644
--- a/src/mapping.rs
+++ b/src/mapping.rs
@@ -87,15 +87,65 @@ impl Mapping {
}
/// Removes and returns the value corresponding to the key from the map.
+ ///
+ /// This is equivalent to [`.swap_remove(index)`][Self::swap_remove],
+ /// replacing this entry’s position with the last element. If you need to
+ /// preserve the relative order of the keys in the map, use
+ /// [`.shift_remove(key)`][Self::shift_remove] instead.
#[inline]
pub fn remove<I: Index>(&mut self, index: I) -> Option<Value> {
- index.remove_from(self)
+ self.swap_remove(index)
}
/// Remove and return the key-value pair.
+ ///
+ /// This is equivalent to [`.swap_remove_entry(index)`][Self::swap_remove_entry],
+ /// replacing this entry’s position with the last element. If you need to
+ /// preserve the relative order of the keys in the map, use
+ /// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead.
#[inline]
pub fn remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> {
- index.remove_entry_from(self)
+ self.swap_remove_entry(index)
+ }
+
+ /// Removes and returns the value corresponding to the key from the map.
+ ///
+ /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
+ /// last element of the map and popping it off. This perturbs the position
+ /// of what used to be the last element!
+ #[inline]
+ pub fn swap_remove<I: Index>(&mut self, index: I) -> Option<Value> {
+ index.swap_remove_from(self)
+ }
+
+ /// Remove and return the key-value pair.
+ ///
+ /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
+ /// last element of the map and popping it off. This perturbs the position
+ /// of what used to be the last element!
+ #[inline]
+ pub fn swap_remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> {
+ index.swap_remove_entry_from(self)
+ }
+
+ /// Removes and returns the value corresponding to the key from the map.
+ ///
+ /// Like [`Vec::remove`], the entry is removed by shifting all of the
+ /// elements that follow it, preserving their relative order. This perturbs
+ /// the index of all of those elements!
+ #[inline]
+ pub fn shift_remove<I: Index>(&mut self, index: I) -> Option<Value> {
+ index.shift_remove_from(self)
+ }
+
+ /// Remove and return the key-value pair.
+ ///
+ /// Like [`Vec::remove`], the entry is removed by shifting all of the
+ /// elements that follow it, preserving their relative order. This perturbs
+ /// the index of all of those elements!
+ #[inline]
+ pub fn shift_remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> {
+ index.shift_remove_entry_from(self)
}
/// Scan through each key-value pair in the map and keep those where the
@@ -203,10 +253,16 @@ pub trait Index: private::Sealed {
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value>;
#[doc(hidden)]
- fn remove_from(&self, v: &mut Mapping) -> Option<Value>;
+ fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value>;
+
+ #[doc(hidden)]
+ fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>;
+
+ #[doc(hidden)]
+ fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value>;
#[doc(hidden)]
- fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>;
+ fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>;
}
struct HashLikeValue<'a>(&'a str);
@@ -239,11 +295,17 @@ impl Index for Value {
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> {
v.map.get_mut(self)
}
- fn remove_from(&self, v: &mut Mapping) -> Option<Value> {
- v.map.remove(self)
+ fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> {
+ v.map.swap_remove(self)
}
- fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
- v.map.remove_entry(self)
+ fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
+ v.map.swap_remove_entry(self)
+ }
+ fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> {
+ v.map.shift_remove(self)
+ }
+ fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
+ v.map.shift_remove_entry(self)
}
}
@@ -257,11 +319,17 @@ impl Index for str {
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> {
v.map.get_mut(&HashLikeValue(self))
}
- fn remove_from(&self, v: &mut Mapping) -> Option<Value> {
- v.map.remove(&HashLikeValue(self))
+ fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> {
+ v.map.swap_remove(&HashLikeValue(self))
+ }
+ fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
+ v.map.swap_remove_entry(&HashLikeValue(self))
+ }
+ fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> {
+ v.map.shift_remove(&HashLikeValue(self))
}
- fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
- v.map.remove_entry(&HashLikeValue(self))
+ fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
+ v.map.shift_remove_entry(&HashLikeValue(self))
}
}
@@ -275,11 +343,17 @@ impl Index for String {
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> {
self.as_str().index_into_mut(v)
}
- fn remove_from(&self, v: &mut Mapping) -> Option<Value> {
- self.as_str().remove_from(v)
+ fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> {
+ self.as_str().swap_remove_from(v)
}
- fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
- self.as_str().remove_entry_from(v)
+ fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
+ self.as_str().swap_remove_entry_from(v)
+ }
+ fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> {
+ self.as_str().shift_remove_from(v)
+ }
+ fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
+ self.as_str().shift_remove_entry_from(v)
}
}
@@ -296,11 +370,17 @@ where
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> {
(**self).index_into_mut(v)
}
- fn remove_from(&self, v: &mut Mapping) -> Option<Value> {
- (**self).remove_from(v)
+ fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> {
+ (**self).swap_remove_from(v)
+ }
+ fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
+ (**self).swap_remove_entry_from(v)
+ }
+ fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> {
+ (**self).shift_remove_from(v)
}
- fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
- (**self).remove_entry_from(v)
+ fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
+ (**self).shift_remove_entry_from(v)
}
}
diff --git a/src/number.rs b/src/number.rs
index 3b0293b..5ebe395 100644
--- a/src/number.rs
+++ b/src/number.rs
@@ -517,22 +517,24 @@ macro_rules! from_unsigned {
};
}
-macro_rules! from_float {
- ($($float_ty:ident)*) => {
- $(
- impl From<$float_ty> for Number {
- #[inline]
- fn from(f: $float_ty) -> Self {
- Number { n: N::Float(f as f64) }
- }
- }
- )*
+from_signed!(i8 i16 i32 i64 isize);
+from_unsigned!(u8 u16 u32 u64 usize);
+
+impl From<f32> for Number {
+ fn from(f: f32) -> Self {
+ Number::from(f as f64)
}
}
-from_signed!(i8 i16 i32 i64 isize);
-from_unsigned!(u8 u16 u32 u64 usize);
-from_float!(f32 f64);
+impl From<f64> for Number {
+ fn from(mut f: f64) -> Self {
+ if f.is_nan() {
+ // Destroy NaN sign, signaling, and payload. YAML only has one NaN.
+ f = f64::NAN.copysign(1.0);
+ }
+ Number { n: N::Float(f) }
+ }
+}
// This is fine, because we don't _really_ implement hash for floats
// all other hash functions should work as expected