1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! String trait implementations.

use crate::{
    FromValue, OwnedMut, OwnedRef, RawOwnedMut, RawOwnedRef, Shared, ToValue, UnsafeFromValue,
    Value, VmError,
};

value_types!(crate::STRING_TYPE, String => String, &String, &mut String, &str, &mut str);

impl FromValue for String {
    fn from_value(value: Value) -> Result<Self, VmError> {
        match value {
            Value::String(string) => Ok(string.borrow_ref()?.clone()),
            Value::StaticString(string) => Ok((**string).clone()),
            actual => Err(VmError::expected::<String>(actual.type_info()?)),
        }
    }
}

impl ToValue for Box<str> {
    fn to_value(self) -> Result<Value, VmError> {
        Ok(Value::String(Shared::new(self.to_string())))
    }
}

impl FromValue for Box<str> {
    fn from_value(value: Value) -> Result<Self, VmError> {
        let string = value.into_string()?;
        let string = string.borrow_ref()?.clone();
        Ok(string.into_boxed_str())
    }
}

impl UnsafeFromValue for &str {
    type Output = *const str;
    type Guard = Option<RawOwnedRef>;

    unsafe fn unsafe_from_value(value: Value) -> Result<(Self::Output, Self::Guard), VmError> {
        Ok(match value {
            Value::String(string) => {
                let string = string.owned_ref()?;
                let (s, guard) = OwnedRef::into_raw(string);
                ((*s).as_str(), Some(guard))
            }
            Value::StaticString(string) => (string.as_ref().as_str(), None),
            actual => return Err(VmError::expected::<String>(actual.type_info()?)),
        })
    }

    unsafe fn to_arg(output: Self::Output) -> Self {
        &*output
    }
}

impl UnsafeFromValue for &mut str {
    type Output = *mut str;
    type Guard = Option<RawOwnedMut>;

    unsafe fn unsafe_from_value(value: Value) -> Result<(Self::Output, Self::Guard), VmError> {
        Ok(match value {
            Value::String(string) => {
                let string = string.owned_mut()?;
                let (s, guard) = OwnedMut::into_raw(string);
                ((*s).as_mut_str(), Some(guard))
            }
            actual => {
                return Err(VmError::expected::<String>(actual.type_info()?));
            }
        })
    }

    unsafe fn to_arg(output: Self::Output) -> Self {
        &mut *output
    }
}

impl UnsafeFromValue for &String {
    type Output = *const String;
    type Guard = Option<RawOwnedRef>;

    unsafe fn unsafe_from_value(value: Value) -> Result<(Self::Output, Self::Guard), VmError> {
        Ok(match value {
            Value::String(string) => {
                let string = string.owned_ref()?;
                let (s, guard) = OwnedRef::into_raw(string);
                (s, Some(guard))
            }
            Value::StaticString(string) => (&**string, None),
            actual => {
                return Err(VmError::expected::<String>(actual.type_info()?));
            }
        })
    }

    unsafe fn to_arg(output: Self::Output) -> Self {
        &*output
    }
}

impl UnsafeFromValue for &mut String {
    type Output = *mut String;
    type Guard = RawOwnedMut;

    unsafe fn unsafe_from_value(value: Value) -> Result<(Self::Output, Self::Guard), VmError> {
        Ok(match value {
            Value::String(string) => {
                let string = string.owned_mut()?;
                let (s, guard) = OwnedMut::into_raw(string);
                (s, guard)
            }
            actual => {
                return Err(VmError::expected::<String>(actual.type_info()?));
            }
        })
    }

    unsafe fn to_arg(output: Self::Output) -> Self {
        &mut *output
    }
}