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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use {
rust_icu_common as common, rust_icu_sys as sys, rust_icu_sys::versioned_function,
rust_icu_sys::*, std::cmp::Eq, std::convert::TryFrom, std::os::raw,
};
#[derive(Debug)]
pub struct Text {
rep: *mut UText,
}
impl PartialEq for Text {
fn eq(&self, other: &Self) -> bool {
let ret = unsafe { versioned_function!(utext_equals)(self.rep, other.rep) };
match ret {
0 => false,
1 => true,
_ => panic!("value is not convertible to bool in Text::eq: {}", ret),
}
}
}
impl Eq for Text {}
impl TryFrom<String> for Text {
type Error = common::Error;
fn try_from(s: String) -> Result<Self, Self::Error> {
let len: i64 = s.len() as i64;
let bytes = s.as_ptr() as *const raw::c_char;
unsafe { Self::from_raw_bytes(bytes, len) }
}
}
impl TryFrom<&str> for Text {
type Error = common::Error;
fn try_from(s: &str) -> Result<Self, Self::Error> {
let len = s.len() as i64;
let bytes = s.as_ptr() as *const raw::c_char;
unsafe { Self::from_raw_bytes(bytes, len) }
}
}
impl Text {
unsafe fn from_raw_bytes(buffer: *const raw::c_char, len: i64) -> Result<Self, common::Error> {
let mut status = common::Error::OK_CODE;
let rep = versioned_function!(utext_openUTF8)(0 as *mut UText, buffer, len, &mut status);
common::Error::ok_or_warning(status)?;
Ok(Text { rep })
}
pub fn try_clone(&self, deep: bool, readonly: bool) -> Result<Self, common::Error> {
let mut status = common::Error::OK_CODE;
let rep = unsafe {
assert!(common::Error::is_ok(status));
versioned_function!(utext_clone)(
0 as *mut UText,
self.rep,
deep as sys::UBool,
readonly as sys::UBool,
&mut status,
)
};
common::Error::ok_or_warning(status)?;
Ok(Text { rep })
}
}
impl Drop for Text {
fn drop(&mut self) {
unsafe {
versioned_function!(utext_close)(self.rep);
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn partial_eq() {
let foo = Text::try_from("foo".to_string()).expect("conversion from string succeeds.");
let bar = Text::try_from("foo").expect("conversion from literal succeeds");
let baz = Text::try_from("baz").expect("conversion from literal succeeds");
assert_eq!(1i8, unsafe {
versioned_function!(utext_equals)(foo.rep, foo.rep)
});
assert_eq!(1i8, unsafe {
versioned_function!(utext_equals)(bar.rep, bar.rep)
});
assert_ne!(1i8, unsafe {
versioned_function!(utext_equals)(foo.rep, bar.rep)
});
assert_ne!(foo, bar);
assert_ne!(foo, baz);
assert_ne!(bar, baz);
assert_eq!(
foo,
foo.try_clone(true, true).expect("clone is a success"),
"a clone should be the same as its source"
);
}
}