diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/de.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 7 | ||||
-rw-r--r-- | src/libyaml/emitter.rs | 11 | ||||
-rw-r--r-- | src/libyaml/error.rs | 26 | ||||
-rw-r--r-- | src/libyaml/parser.rs | 29 | ||||
-rw-r--r-- | src/mapping.rs | 120 | ||||
-rw-r--r-- | src/number.rs | 28 |
7 files changed, 153 insertions, 70 deletions
@@ -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() { @@ -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 |