compose_library/foundations/
str.rs1use crate::Iter;
2use compose_library::diag::bail;
3use compose_library::repr::Repr;
4use compose_library::vm::Vm;
5use compose_library::{IterValue, StringIterator, Value};
6use compose_macros::func;
7use compose_macros::{cast, scope, ty};
8use ecow::EcoString;
9use std::fmt;
10use std::ops::Add;
11
12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13#[ty(scope, cast, name = "String")]
14pub struct Str(pub EcoString);
15
16impl Add for &Str {
17 type Output = Str;
18
19 fn add(self, rhs: Self) -> Self::Output {
20 let mut l = self.0.clone();
21 l.push_str(&rhs.0);
22 Str(l)
23 }
24}
25
26#[scope]
27impl Str {
28 #[func]
29 pub fn chars(self, vm: &mut dyn Vm) -> IterValue {
30 IterValue::new(Iter::String(StringIterator::new(self.0)), vm)
31 }
32
33 #[func]
34 pub fn len(&self) -> usize {
35 self.0.len()
36 }
37
38 #[func]
39 pub fn is_empty(&self) -> bool {
40 self.0.is_empty()
41 }
42}
43
44impl Repr for Str {
45 fn repr(&self, _vm: &dyn Vm) -> EcoString {
46 self.0.clone()
47 }
48}
49
50impl fmt::Display for Str {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 write!(f, "{}", self.0)
53 }
54}
55
56impl From<EcoString> for Str {
57 fn from(s: EcoString) -> Self {
58 Str(s)
59 }
60}
61
62impl From<String> for Str {
63 fn from(value: String) -> Self {
64 Str(value.into())
65 }
66}
67
68impl From<&str> for Str {
69 fn from(s: &str) -> Self {
70 Str(s.into())
71 }
72}
73
74impl From<Str> for String {
75 fn from(s: Str) -> Self {
76 s.0.into()
77 }
78}
79
80impl From<Str> for EcoString {
81 fn from(s: Str) -> Self {
82 s.0
83 }
84}
85
86cast! {
87 &str,
88 self => Value::Str(self.into()),
89}
90
91cast! {
92 EcoString,
93 self => Value::Str(self.into()),
94 v: Str => v.into()
95}
96
97cast! {
98 char,
99 self => Value::Str(EcoString::from(self).into()),
100 v: Str => {
101 let mut chars = v.0.chars();
102 match (chars.next(), chars.next()) {
103 (Some(_), Some(_)) => bail!("cannot convert a string with more than one character to char: {}", v.0),
104 (Some(c), None) => c,
105 (None, _) => bail!("cannot convert empty string to char"),
106 }
107 }
108}