stabby_abi/
str.rs

1//
2// Copyright (c) 2023 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12//   Pierre Avital, <pierre.avital@me.com>
13//
14
15//! Stable strs!
16
17use crate as stabby;
18
19use core::ops::{Deref, DerefMut};
20
21/// An ABI stable equivalent of `&'a str`
22#[stabby::stabby]
23#[derive(Clone, Copy, PartialEq, Eq, Hash)]
24pub struct Str<'a> {
25    pub(crate) inner: crate::slice::Slice<'a, u8>,
26}
27impl<'a> Str<'a> {
28    /// Wraps a standard `str` into its ABI-stable equivalent.
29    pub const fn new(s: &'a str) -> Self {
30        Self {
31            inner: crate::slice::Slice::new(s.as_bytes()),
32        }
33    }
34    /// Exposes `self` as a `&sr`.
35    pub const fn as_str(self) -> &'a str {
36        // Safety: the UTF8 predicate is validaetd by the type.
37        unsafe { core::str::from_utf8_unchecked(self.inner.as_slice()) }
38    }
39}
40impl<'a> From<&'a str> for Str<'a> {
41    fn from(value: &'a str) -> Self {
42        Self::new(value)
43    }
44}
45impl<'a> From<&'a mut str> for Str<'a> {
46    fn from(value: &'a mut str) -> Self {
47        Self::from(&*value)
48    }
49}
50impl<'a> From<Str<'a>> for &'a str {
51    fn from(value: Str<'a>) -> Self {
52        value.as_str()
53    }
54}
55impl AsRef<str> for Str<'_> {
56    fn as_ref(&self) -> &str {
57        self
58    }
59}
60impl Deref for Str<'_> {
61    type Target = str;
62    fn deref(&self) -> &Self::Target {
63        self.as_str()
64    }
65}
66impl core::fmt::Debug for Str<'_> {
67    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
68        self.deref().fmt(f)
69    }
70}
71impl core::fmt::Display for Str<'_> {
72    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73        self.deref().fmt(f)
74    }
75}
76impl core::cmp::PartialOrd for Str<'_> {
77    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
78        self.deref().partial_cmp(other.deref())
79    }
80}
81
82/// An ABI stable equivalent of `&'a mut T`
83#[stabby::stabby]
84pub struct StrMut<'a> {
85    pub(crate) inner: crate::slice::SliceMut<'a, u8>,
86}
87impl AsRef<str> for StrMut<'_> {
88    fn as_ref(&self) -> &str {
89        self
90    }
91}
92impl Deref for StrMut<'_> {
93    type Target = str;
94    fn deref(&self) -> &Self::Target {
95        // Safety: the UTF8 predicate is validaetd by the type.
96        unsafe { core::str::from_utf8_unchecked(&self.inner) }
97    }
98}
99impl DerefMut for StrMut<'_> {
100    fn deref_mut(&mut self) -> &mut Self::Target {
101        // Safety: the UTF8 predicate is validaetd by the type.
102        unsafe { core::str::from_utf8_unchecked_mut(&mut self.inner) }
103    }
104}
105impl<'a> From<&'a mut str> for StrMut<'a> {
106    fn from(value: &'a mut str) -> Self {
107        Self {
108            inner: unsafe { value.as_bytes_mut().into() },
109        }
110    }
111}
112impl<'a> From<StrMut<'a>> for Str<'a> {
113    fn from(value: StrMut<'a>) -> Self {
114        Self {
115            inner: value.inner.into(),
116        }
117    }
118}
119impl<'a> From<StrMut<'a>> for &'a mut str {
120    fn from(value: StrMut<'a>) -> Self {
121        // Safety: the UTF8 predicate is validaetd by the type.
122        unsafe { core::str::from_utf8_unchecked_mut(value.inner.into()) }
123    }
124}
125
126impl<'a> From<StrMut<'a>> for &'a str {
127    fn from(value: StrMut<'a>) -> Self {
128        // Safety: the UTF8 predicate is validaetd by the type.
129        unsafe { core::str::from_utf8_unchecked(value.inner.into()) }
130    }
131}
132
133#[cfg(feature = "serde")]
134mod serde_impl {
135    use super::*;
136    use serde::{de::Visitor, Deserialize, Serialize};
137    impl<'a> Serialize for Str<'a> {
138        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139        where
140            S: serde::Serializer,
141        {
142            serializer.serialize_str(self)
143        }
144    }
145    impl<'a> Serialize for StrMut<'a> {
146        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
147        where
148            S: serde::Serializer,
149        {
150            serializer.serialize_str(self)
151        }
152    }
153    impl<'a> Deserialize<'a> for Str<'a> {
154        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
155        where
156            D: serde::Deserializer<'a>,
157        {
158            deserializer.deserialize_str(StrVisitor(core::marker::PhantomData))
159        }
160    }
161    struct StrVisitor<'a>(core::marker::PhantomData<Str<'a>>);
162    impl<'a> Visitor<'a> for StrVisitor<'a> {
163        type Value = Str<'a>;
164        fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
165        where
166            E: serde::de::Error,
167        {
168            Ok(v.into())
169        }
170        fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
171            write!(formatter, "A borrowed_str")
172        }
173    }
174}