1use libc::{c_char, size_t};
2use std::ffi::CStr;
3use std::marker::PhantomData;
4use std::ops::Deref;
5use std::{fmt, mem, ptr};
6
7use super::JsonnetVm;
8use jsonnet_sys;
9
10pub struct JsonnetString<'a> {
16 vm: &'a JsonnetVm,
17 data: *mut c_char,
18}
19
20impl<'a> JsonnetString<'a> {
21 pub fn new(vm: &'a JsonnetVm, v: &str) -> Self {
27 JsonnetString::from_bytes(vm, v.as_bytes())
28 }
29
30 pub fn from_bytes(vm: &'a JsonnetVm, v: &[u8]) -> Self {
38 unsafe {
39 let p = jsonnet_sys::jsonnet_realloc(vm.as_ptr(), ptr::null(), v.len() + 1);
40 ptr::copy_nonoverlapping(v.as_ptr(), p as *mut u8, v.len());
41 *(p.offset(v.len() as isize)) = 0; Self::from_ptr(vm, p)
43 }
44 }
45
46 pub unsafe fn from_ptr(vm: &'a JsonnetVm, p: *mut c_char) -> Self {
55 JsonnetString { vm: vm, data: p }
56 }
57
58 fn realloc(&mut self, size: size_t) {
59 unsafe {
60 self.data = jsonnet_sys::jsonnet_realloc(self.vm.as_ptr(), self.data, size);
61 }
62 }
63
64 pub fn as_str(&self) -> &'a str {
66 self.as_cstr().to_str().unwrap()
67 }
68
69 pub fn as_cstr(&self) -> &'a CStr {
71 unsafe { CStr::from_ptr(self.data) }
72 }
73
74 pub fn as_ptr(&self) -> *const c_char {
78 self.data
79 }
80
81 pub fn into_raw(self) -> *mut c_char {
88 let result = self.data;
89 mem::forget(self);
90 result
91 }
92}
93
94impl<'a> Deref for JsonnetString<'a> {
95 type Target = str;
96 fn deref(&self) -> &str {
97 self.as_str()
98 }
99}
100
101impl<'a> fmt::Debug for JsonnetString<'a> {
102 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103 fmt::Debug::fmt(self.as_str(), f)
104 }
105}
106
107impl<'a> fmt::Display for JsonnetString<'a> {
108 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109 fmt::Display::fmt(self.as_str(), f)
110 }
111}
112
113impl<'a> Drop for JsonnetString<'a> {
114 fn drop(&mut self) {
115 self.realloc(0);
116 }
117}
118
119impl<'a> PartialEq for JsonnetString<'a> {
120 fn eq<'b>(&self, other: &JsonnetString<'b>) -> bool {
121 self.as_str() == other.as_str()
122 }
123}
124
125impl<'a> Eq for JsonnetString<'a> {}
126
127#[test]
128fn simple() {
129 let vm = JsonnetVm::new();
130 let s = JsonnetString::new(&vm, "1234");
131 assert_eq!(s.as_str(), "1234");
132 assert_eq!(s.as_cstr().to_bytes_with_nul(), b"1234\0");
133}
134
135#[derive(Debug)]
137pub struct JsonnetStringIter<'a, 'b: 'a> {
138 cursor: *const c_char,
139 marker: PhantomData<&'a JsonnetString<'b>>,
140}
141
142impl<'a, 'b> JsonnetStringIter<'a, 'b> {
143 pub unsafe fn new(inner: &'a JsonnetString<'b>) -> Self {
146 let cursor = inner.as_ptr();
147 JsonnetStringIter {
148 cursor: cursor,
149 marker: PhantomData,
150 }
151 }
152
153 fn end(&self) -> bool {
154 let c = unsafe { *self.cursor };
155 c == 0
156 }
157
158 unsafe fn take_next(&mut self) -> &'a CStr {
160 let ret = CStr::from_ptr(self.cursor);
161 let len = ret.to_bytes_with_nul().len();
162 self.cursor = self.cursor.offset(len as isize);
163 ret
164 }
165}
166
167impl<'a, 'b> Iterator for JsonnetStringIter<'a, 'b> {
168 type Item = &'a str;
169 fn next(&mut self) -> Option<Self::Item> {
170 if self.end() {
171 None
172 } else {
173 let v = unsafe { self.take_next() };
174 Some(v.to_str().unwrap())
175 }
176 }
177}