java_string/
owned.rs

1use std::borrow::{Borrow, BorrowMut, Cow};
2use std::collections::{Bound, TryReserveError};
3use std::convert::Infallible;
4use std::fmt::{Debug, Display, Formatter, Write};
5use std::hash::{Hash, Hasher};
6use std::iter::FusedIterator;
7use std::ops::{
8    Add, AddAssign, Deref, DerefMut, Index, IndexMut, Range, RangeBounds, RangeFrom, RangeFull,
9    RangeInclusive, RangeTo, RangeToInclusive,
10};
11use std::rc::Rc;
12use std::str::FromStr;
13use std::sync::Arc;
14use std::{ptr, slice};
15
16use crate::validations::{
17    run_utf8_full_validation_from_semi, run_utf8_semi_validation, to_range_checked,
18};
19use crate::{Chars, FromUtf8Error, JavaCodePoint, JavaStr, Utf8Error};
20
21#[derive(Default, PartialEq, PartialOrd, Eq, Ord)]
22pub struct JavaString {
23    vec: Vec<u8>,
24}
25
26#[allow(clippy::multiple_inherent_impl)]
27impl JavaString {
28    #[inline]
29    #[must_use]
30    pub const fn new() -> JavaString {
31        JavaString { vec: Vec::new() }
32    }
33
34    #[inline]
35    #[must_use]
36    pub fn with_capacity(capacity: usize) -> JavaString {
37        JavaString {
38            vec: Vec::with_capacity(capacity),
39        }
40    }
41
42    /// Converts `vec` to a `JavaString` if it is fully-valid UTF-8, i.e. UTF-8
43    /// without surrogate code points. See [`String::from_utf8`].
44    #[inline]
45    pub fn from_full_utf8(vec: Vec<u8>) -> Result<JavaString, FromUtf8Error> {
46        match std::str::from_utf8(&vec) {
47            Ok(..) => Ok(JavaString { vec }),
48            Err(e) => Err(FromUtf8Error {
49                bytes: vec,
50                error: e.into(),
51            }),
52        }
53    }
54
55    /// Converts `vec` to a `JavaString` if it is semi-valid UTF-8, i.e. UTF-8
56    /// with surrogate code points.
57    ///
58    /// ```
59    /// # use java_string::{JavaCodePoint, JavaString};
60    ///
61    /// assert_eq!(
62    ///     JavaString::from_semi_utf8(b"Hello World!".to_vec()).unwrap(),
63    ///     "Hello World!"
64    /// );
65    /// assert_eq!(
66    ///     JavaString::from_semi_utf8(vec![0xf0, 0x9f, 0x92, 0x96]).unwrap(),
67    ///     "💖"
68    /// );
69    /// assert_eq!(
70    ///     JavaString::from_semi_utf8(vec![0xed, 0xa0, 0x80]).unwrap(),
71    ///     JavaString::from(JavaCodePoint::from_u32(0xd800).unwrap())
72    /// );
73    /// assert!(JavaString::from_semi_utf8(vec![0xed]).is_err());
74    /// ```
75    pub fn from_semi_utf8(vec: Vec<u8>) -> Result<JavaString, FromUtf8Error> {
76        match run_utf8_semi_validation(&vec) {
77            Ok(..) => Ok(JavaString { vec }),
78            Err(err) => Err(FromUtf8Error {
79                bytes: vec,
80                error: err,
81            }),
82        }
83    }
84
85    /// Converts `v` to a `Cow<JavaStr>`, replacing invalid semi-UTF-8 with the
86    /// replacement character �.
87    ///
88    /// ```
89    /// # use std::borrow::Cow;
90    /// # use java_string::{JavaStr, JavaString};
91    ///
92    /// let sparkle_heart = [0xf0, 0x9f, 0x92, 0x96];
93    /// let result = JavaString::from_semi_utf8_lossy(&sparkle_heart);
94    /// assert!(matches!(result, Cow::Borrowed(_)));
95    /// assert_eq!(result, JavaStr::from_str("💖"));
96    ///
97    /// let foobar_with_error = [b'f', b'o', b'o', 0xed, b'b', b'a', b'r'];
98    /// let result = JavaString::from_semi_utf8_lossy(&foobar_with_error);
99    /// assert!(matches!(result, Cow::Owned(_)));
100    /// assert_eq!(result, JavaStr::from_str("foo�bar"));
101    /// ```
102    #[must_use]
103    pub fn from_semi_utf8_lossy(v: &[u8]) -> Cow<'_, JavaStr> {
104        const REPLACEMENT: &str = "\u{FFFD}";
105
106        match run_utf8_semi_validation(v) {
107            Ok(()) => unsafe {
108                // SAFETY: validation succeeded
109                Cow::Borrowed(JavaStr::from_semi_utf8_unchecked(v))
110            },
111            Err(error) => {
112                let mut result = unsafe {
113                    // SAFETY: validation succeeded up to this index
114                    JavaString::from_semi_utf8_unchecked(
115                        v.get_unchecked(..error.valid_up_to).to_vec(),
116                    )
117                };
118                result.push_str(REPLACEMENT);
119                let mut index = error.valid_up_to + error.error_len.unwrap_or(1) as usize;
120                loop {
121                    match run_utf8_semi_validation(&v[index..]) {
122                        Ok(()) => {
123                            unsafe {
124                                // SAFETY: validation succeeded
125                                result.push_java_str(JavaStr::from_semi_utf8_unchecked(&v[index..]))
126                            };
127                            return Cow::Owned(result);
128                        }
129                        Err(error) => {
130                            unsafe {
131                                // SAFETY: validation succeeded up to this index
132                                result.push_java_str(JavaStr::from_semi_utf8_unchecked(
133                                    v.get_unchecked(index..index + error.valid_up_to),
134                                ))
135                            };
136                            result.push_str(REPLACEMENT);
137                            index += error.valid_up_to + error.error_len.unwrap_or(1) as usize;
138                        }
139                    }
140                }
141            }
142        }
143    }
144
145    /// # Safety
146    ///
147    /// The parameter must be in semi-valid UTF-8 format, that is, UTF-8 plus
148    /// surrogate code points.
149    #[inline]
150    #[must_use]
151    pub unsafe fn from_semi_utf8_unchecked(bytes: Vec<u8>) -> JavaString {
152        JavaString { vec: bytes }
153    }
154
155    /// See [`String::into_bytes`].
156    #[inline]
157    #[must_use]
158    pub fn into_bytes(self) -> Vec<u8> {
159        self.vec
160    }
161
162    /// See [`String::as_str`].
163    #[inline]
164    #[must_use]
165    pub fn as_java_str(&self) -> &JavaStr {
166        unsafe {
167            // SAFETY: this str has semi-valid UTF-8
168            JavaStr::from_semi_utf8_unchecked(&self.vec)
169        }
170    }
171
172    /// See [`String::as_mut_str`].
173    #[inline]
174    #[must_use]
175    pub fn as_mut_java_str(&mut self) -> &mut JavaStr {
176        unsafe {
177            // SAFETY: this str has semi-valid UTF-8
178            JavaStr::from_semi_utf8_unchecked_mut(&mut self.vec)
179        }
180    }
181
182    /// Tries to convert this `JavaString` to a `String`, returning an error if
183    /// it is not fully valid UTF-8, i.e. has no surrogate code points.
184    ///
185    /// ```
186    /// # use java_string::{JavaCodePoint, JavaString};
187    ///
188    /// assert_eq!(
189    ///     JavaString::from("Hello World!").into_string().unwrap(),
190    ///     "Hello World!"
191    /// );
192    /// assert_eq!(
193    ///     JavaString::from("abc\0ℝ💣").into_string().unwrap(),
194    ///     "abc\0ℝ💣"
195    /// );
196    ///
197    /// let string_with_error = JavaString::from("abc")
198    ///     + JavaString::from(JavaCodePoint::from_u32(0xd800).unwrap()).as_java_str();
199    /// assert!(string_with_error.into_string().is_err());
200    /// ```
201    pub fn into_string(self) -> Result<String, Utf8Error> {
202        run_utf8_full_validation_from_semi(self.as_bytes()).map(|()| unsafe {
203            // SAFETY: validation succeeded
204            self.into_string_unchecked()
205        })
206    }
207
208    /// # Safety
209    ///
210    /// This string must be fully valid UTF-8, i.e. have no surrogate code
211    /// points.
212    #[inline]
213    #[must_use]
214    pub unsafe fn into_string_unchecked(self) -> String {
215        // SAFETY: preconditions checked by caller
216        String::from_utf8_unchecked(self.vec)
217    }
218
219    /// See [`String::push_str`].
220    #[inline]
221    pub fn push_java_str(&mut self, string: &JavaStr) {
222        self.vec.extend_from_slice(string.as_bytes())
223    }
224
225    /// See [`String::push_str`].
226    #[inline]
227    pub fn push_str(&mut self, string: &str) {
228        self.vec.extend_from_slice(string.as_bytes())
229    }
230
231    /// See [`String::capacity`].
232    #[inline]
233    #[must_use]
234    pub fn capacity(&self) -> usize {
235        self.vec.capacity()
236    }
237
238    /// See [`String::reserve`].
239    #[inline]
240    pub fn reserve(&mut self, additional: usize) {
241        self.vec.reserve(additional)
242    }
243
244    /// See [`String::reserve_exact`].
245    #[inline]
246    pub fn reserve_exact(&mut self, additional: usize) {
247        self.vec.reserve_exact(additional)
248    }
249
250    /// See [`String::try_reserve`].
251    #[inline]
252    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
253        self.vec.try_reserve(additional)
254    }
255
256    /// See [`String::try_reserve_exact`].
257    #[inline]
258    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
259        self.vec.try_reserve_exact(additional)
260    }
261
262    /// See [`String::shrink_to_fit`].
263    #[inline]
264    pub fn shrink_to_fit(&mut self) {
265        self.vec.shrink_to_fit()
266    }
267
268    /// See [`String::shrink_to`].
269    #[inline]
270    pub fn shrink_to(&mut self, min_capacity: usize) {
271        self.vec.shrink_to(min_capacity)
272    }
273
274    /// See [`String::push`].
275    #[inline]
276    pub fn push(&mut self, ch: char) {
277        match ch.len_utf8() {
278            1 => self.vec.push(ch as u8),
279            _ => self
280                .vec
281                .extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
282        }
283    }
284
285    /// See [`String::push`].
286    #[inline]
287    pub fn push_java(&mut self, ch: JavaCodePoint) {
288        match ch.len_utf8() {
289            1 => self.vec.push(ch.as_u32() as u8),
290            _ => self.vec.extend_from_slice(ch.encode_semi_utf8(&mut [0; 4])),
291        }
292    }
293
294    /// See [`String::as_bytes`].
295    #[inline]
296    #[must_use]
297    pub fn as_bytes(&self) -> &[u8] {
298        &self.vec
299    }
300
301    /// See [`String::truncate`].
302    #[inline]
303    pub fn truncate(&mut self, new_len: usize) {
304        if new_len <= self.len() {
305            assert!(self.is_char_boundary(new_len));
306            self.vec.truncate(new_len)
307        }
308    }
309
310    /// See [`String::pop`].
311    ///
312    /// ```
313    /// # use java_string::JavaString;
314    ///
315    /// let mut str = JavaString::from("Hello World!");
316    /// assert_eq!(str.pop().unwrap(), '!');
317    /// assert_eq!(str, "Hello World");
318    ///
319    /// let mut str = JavaString::from("東京");
320    /// assert_eq!(str.pop().unwrap(), '京');
321    /// assert_eq!(str, "東");
322    ///
323    /// assert!(JavaString::new().pop().is_none());
324    /// ```
325    #[inline]
326    pub fn pop(&mut self) -> Option<JavaCodePoint> {
327        let ch = self.chars().next_back()?;
328        let newlen = self.len() - ch.len_utf8();
329        unsafe { self.vec.set_len(newlen) };
330        Some(ch)
331    }
332
333    /// See [`String::remove`].
334    ///
335    /// ```
336    /// # use java_string::JavaString;
337    ///
338    /// let mut str = JavaString::from("Hello World!");
339    /// assert_eq!(str.remove(5), ' ');
340    /// assert_eq!(str, "HelloWorld!");
341    ///
342    /// let mut str = JavaString::from("Hello 🦀 World!");
343    /// assert_eq!(str.remove(6), '🦀');
344    /// assert_eq!(str, "Hello  World!");
345    /// ```
346    /// ```should_panic
347    /// # use java_string::JavaString;
348    /// // Should panic
349    /// JavaString::new().remove(0);
350    /// ```
351    /// ```should_panic
352    /// # use java_string::JavaString;
353    /// // Should panic
354    /// JavaString::from("🦀").remove(1);
355    /// ```
356    #[inline]
357    pub fn remove(&mut self, idx: usize) -> JavaCodePoint {
358        let Some(ch) = self[idx..].chars().next() else {
359            panic!("cannot remove a char from the end of a string")
360        };
361
362        let next = idx + ch.len_utf8();
363        let len = self.len();
364        unsafe {
365            ptr::copy(
366                self.vec.as_ptr().add(next),
367                self.vec.as_mut_ptr().add(idx),
368                len - next,
369            );
370            self.vec.set_len(len - (next - idx))
371        };
372        ch
373    }
374
375    /// See [`String::retain`].
376    ///
377    /// ```
378    /// # use java_string::{JavaCodePoint, JavaString};
379    ///
380    /// let mut str = JavaString::from("Hello 🦀 World!");
381    /// str.retain(|ch| !ch.is_ascii_uppercase());
382    /// assert_eq!(str, "ello 🦀 orld!");
383    /// str.retain(JavaCodePoint::is_ascii);
384    /// assert_eq!(str, "ello  orld!");
385    /// ```
386    #[inline]
387    pub fn retain<F>(&mut self, mut f: F)
388    where
389        F: FnMut(JavaCodePoint) -> bool,
390    {
391        struct SetLenOnDrop<'a> {
392            s: &'a mut JavaString,
393            idx: usize,
394            del_bytes: usize,
395        }
396
397        impl Drop for SetLenOnDrop<'_> {
398            #[inline]
399            fn drop(&mut self) {
400                let new_len = self.idx - self.del_bytes;
401                debug_assert!(new_len <= self.s.len());
402                unsafe { self.s.vec.set_len(new_len) };
403            }
404        }
405
406        let len = self.len();
407        let mut guard = SetLenOnDrop {
408            s: self,
409            idx: 0,
410            del_bytes: 0,
411        };
412
413        while guard.idx < len {
414            // SAFETY: `guard.idx` is positive-or-zero and less that len so the
415            // `get_unchecked` is in bound. `self` is valid UTF-8 like string
416            // and the returned slice starts at a unicode code point so the
417            // `Chars` always return one character.
418            let ch = unsafe {
419                guard
420                    .s
421                    .get_unchecked(guard.idx..len)
422                    .chars()
423                    .next()
424                    .unwrap_unchecked()
425            };
426            let ch_len = ch.len_utf8();
427
428            if !f(ch) {
429                guard.del_bytes += ch_len;
430            } else if guard.del_bytes > 0 {
431                // SAFETY: `guard.idx` is in bound and `guard.del_bytes` represent the number of
432                // bytes that are erased from the string so the resulting `guard.idx -
433                // guard.del_bytes` always represent a valid unicode code point.
434                //
435                // `guard.del_bytes` >= `ch.len_utf8()`, so taking a slice with `ch.len_utf8()`
436                // len is safe.
437                ch.encode_semi_utf8(unsafe {
438                    slice::from_raw_parts_mut(
439                        guard.s.as_mut_ptr().add(guard.idx - guard.del_bytes),
440                        ch.len_utf8(),
441                    )
442                });
443            }
444
445            // Point idx to the next char
446            guard.idx += ch_len;
447        }
448
449        drop(guard);
450    }
451
452    /// See [`String::insert`].
453    ///
454    /// ```
455    /// # use java_string::JavaString;
456    /// let mut s = JavaString::from("foo");
457    /// s.insert(3, 'a');
458    /// s.insert(4, 'r');
459    /// s.insert(3, 'b');
460    /// assert_eq!(s, "foobar");
461    /// ```
462    #[inline]
463    pub fn insert(&mut self, idx: usize, ch: char) {
464        assert!(self.is_char_boundary(idx));
465        let mut bits = [0; 4];
466        let bits = ch.encode_utf8(&mut bits).as_bytes();
467
468        unsafe {
469            self.insert_bytes(idx, bits);
470        }
471    }
472
473    /// See [`String::insert`].
474    #[inline]
475    pub fn insert_java(&mut self, idx: usize, ch: JavaCodePoint) {
476        assert!(self.is_char_boundary(idx));
477        let mut bits = [0; 4];
478        let bits = ch.encode_semi_utf8(&mut bits);
479
480        unsafe {
481            self.insert_bytes(idx, bits);
482        }
483    }
484
485    #[inline]
486    unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
487        let len = self.len();
488        let amt = bytes.len();
489        self.vec.reserve(amt);
490
491        unsafe {
492            ptr::copy(
493                self.vec.as_ptr().add(idx),
494                self.vec.as_mut_ptr().add(idx + amt),
495                len - idx,
496            );
497            ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
498            self.vec.set_len(len + amt);
499        }
500    }
501
502    /// See [`String::insert_str`].
503    ///
504    /// ```
505    /// # use java_string::JavaString;
506    /// let mut s = JavaString::from("bar");
507    /// s.insert_str(0, "foo");
508    /// assert_eq!(s, "foobar");
509    /// ```
510    #[inline]
511    pub fn insert_str(&mut self, idx: usize, string: &str) {
512        assert!(self.is_char_boundary(idx));
513
514        unsafe {
515            self.insert_bytes(idx, string.as_bytes());
516        }
517    }
518
519    /// See [`String::insert_str`].
520    pub fn insert_java_str(&mut self, idx: usize, string: &JavaStr) {
521        assert!(self.is_char_boundary(idx));
522
523        unsafe {
524            self.insert_bytes(idx, string.as_bytes());
525        }
526    }
527
528    /// See [`String::as_mut_vec`].
529    ///
530    /// # Safety
531    ///
532    /// The returned `Vec` must not have invalid UTF-8 written to it, besides
533    /// surrogate pairs.
534    #[inline]
535    pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
536        &mut self.vec
537    }
538
539    /// See [`String::len`].
540    #[inline]
541    #[must_use]
542    pub fn len(&self) -> usize {
543        self.vec.len()
544    }
545
546    /// See [`String::is_empty`].
547    #[inline]
548    #[must_use]
549    pub fn is_empty(&self) -> bool {
550        self.len() == 0
551    }
552
553    /// See [`String::split_off`].
554    ///
555    /// ```
556    /// # use java_string::JavaString;
557    /// let mut hello = JavaString::from("Hello World!");
558    /// let world = hello.split_off(6);
559    /// assert_eq!(hello, "Hello ");
560    /// assert_eq!(world, "World!");
561    /// ```
562    /// ```should_panic
563    /// # use java_string::JavaString;
564    /// let mut s = JavaString::from("🦀");
565    /// // Should panic
566    /// let _ = s.split_off(1);
567    /// ```
568    #[inline]
569    #[must_use]
570    pub fn split_off(&mut self, at: usize) -> JavaString {
571        assert!(self.is_char_boundary(at));
572        let other = self.vec.split_off(at);
573        unsafe { JavaString::from_semi_utf8_unchecked(other) }
574    }
575
576    /// See [`String::clear`].
577    #[inline]
578    pub fn clear(&mut self) {
579        self.vec.clear();
580    }
581
582    /// See [`String::drain`].
583    ///
584    /// ```
585    /// # use java_string::JavaString;
586    ///
587    /// let mut s = JavaString::from("α is alpha, β is beta");
588    /// let beta_offset = s.find('β').unwrap_or(s.len());
589    ///
590    /// // Remove the range up until the β from the string
591    /// let t: JavaString = s.drain(..beta_offset).collect();
592    /// assert_eq!(t, "α is alpha, ");
593    /// assert_eq!(s, "β is beta");
594    ///
595    /// // A full range clears the string, like `clear()` does
596    /// s.drain(..);
597    /// assert_eq!(s, "");
598    /// ```
599    #[inline]
600    pub fn drain<R>(&mut self, range: R) -> Drain<'_>
601    where
602        R: RangeBounds<usize>,
603    {
604        // Memory safety: see String::drain
605        let Range { start, end } = to_range_checked(range, ..self.len());
606        assert!(self.is_char_boundary(start));
607        assert!(self.is_char_boundary(end));
608
609        // Take out two simultaneous borrows. The &mut String won't be accessed
610        // until iteration is over, in Drop.
611        let self_ptr = self as *mut _;
612        // SAFETY: `to_range_checked` and `is_char_boundary` do the appropriate bounds
613        // checks.
614        let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
615
616        Drain {
617            start,
618            end,
619            iter: chars_iter,
620            string: self_ptr,
621        }
622    }
623
624    /// See [`String::replace_range`].
625    ///
626    /// ```
627    /// # use java_string::JavaString;
628    ///
629    /// let mut s = JavaString::from("α is alpha, β is beta");
630    /// let beta_offset = s.find('β').unwrap_or(s.len());
631    ///
632    /// // Replace the range up until the β from the string
633    /// s.replace_range(..beta_offset, "Α is capital alpha; ");
634    /// assert_eq!(s, "Α is capital alpha; β is beta");
635    /// ```
636    /// ```should_panic
637    /// # use java_string::JavaString;
638    /// let mut s = JavaString::from("α is alpha, β is beta");
639    /// // Should panic
640    /// s.replace_range(..1, "Α is capital alpha; ");
641    /// ```
642    pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
643    where
644        R: RangeBounds<usize>,
645    {
646        self.replace_range_java(range, JavaStr::from_str(replace_with))
647    }
648
649    /// See [`String::replace_range`].
650    pub fn replace_range_java<R>(&mut self, range: R, replace_with: &JavaStr)
651    where
652        R: RangeBounds<usize>,
653    {
654        let start = range.start_bound();
655        match start {
656            Bound::Included(&n) => assert!(self.is_char_boundary(n)),
657            Bound::Excluded(&n) => assert!(self.is_char_boundary(n + 1)),
658            Bound::Unbounded => {}
659        };
660        let end = range.end_bound();
661        match end {
662            Bound::Included(&n) => assert!(self.is_char_boundary(n + 1)),
663            Bound::Excluded(&n) => assert!(self.is_char_boundary(n)),
664            Bound::Unbounded => {}
665        };
666
667        unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes());
668    }
669
670    /// See [`String::into_boxed_str`].
671    #[inline]
672    #[must_use]
673    pub fn into_boxed_str(self) -> Box<JavaStr> {
674        let slice = self.vec.into_boxed_slice();
675        unsafe { JavaStr::from_boxed_semi_utf8_unchecked(slice) }
676    }
677
678    /// See [`String::leak`].
679    #[inline]
680    pub fn leak<'a>(self) -> &'a mut JavaStr {
681        let slice = self.vec.leak();
682        unsafe { JavaStr::from_semi_utf8_unchecked_mut(slice) }
683    }
684}
685
686impl Add<&str> for JavaString {
687    type Output = JavaString;
688
689    #[inline]
690    fn add(mut self, rhs: &str) -> Self::Output {
691        self.push_str(rhs);
692        self
693    }
694}
695
696impl Add<&JavaStr> for JavaString {
697    type Output = JavaString;
698
699    #[inline]
700    fn add(mut self, rhs: &JavaStr) -> Self::Output {
701        self.push_java_str(rhs);
702        self
703    }
704}
705
706impl AddAssign<&str> for JavaString {
707    #[inline]
708    fn add_assign(&mut self, rhs: &str) {
709        self.push_str(rhs);
710    }
711}
712
713impl AddAssign<&JavaStr> for JavaString {
714    #[inline]
715    fn add_assign(&mut self, rhs: &JavaStr) {
716        self.push_java_str(rhs);
717    }
718}
719
720impl AsMut<JavaStr> for JavaString {
721    #[inline]
722    fn as_mut(&mut self) -> &mut JavaStr {
723        self.as_mut_java_str()
724    }
725}
726
727impl AsRef<[u8]> for JavaString {
728    #[inline]
729    fn as_ref(&self) -> &[u8] {
730        self.as_bytes()
731    }
732}
733
734impl AsRef<JavaStr> for JavaString {
735    #[inline]
736    fn as_ref(&self) -> &JavaStr {
737        self.as_java_str()
738    }
739}
740
741impl Borrow<JavaStr> for JavaString {
742    #[inline]
743    fn borrow(&self) -> &JavaStr {
744        self.as_java_str()
745    }
746}
747
748impl BorrowMut<JavaStr> for JavaString {
749    #[inline]
750    fn borrow_mut(&mut self) -> &mut JavaStr {
751        self.as_mut_java_str()
752    }
753}
754
755impl Clone for JavaString {
756    #[inline]
757    fn clone(&self) -> Self {
758        JavaString {
759            vec: self.vec.clone(),
760        }
761    }
762
763    #[inline]
764    fn clone_from(&mut self, source: &Self) {
765        self.vec.clone_from(&source.vec)
766    }
767}
768
769impl Debug for JavaString {
770    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
771        Debug::fmt(&**self, f)
772    }
773}
774
775impl Deref for JavaString {
776    type Target = JavaStr;
777
778    #[inline]
779    fn deref(&self) -> &Self::Target {
780        self.as_java_str()
781    }
782}
783
784impl DerefMut for JavaString {
785    #[inline]
786    fn deref_mut(&mut self) -> &mut Self::Target {
787        self.as_mut_java_str()
788    }
789}
790
791impl Display for JavaString {
792    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
793        Display::fmt(&**self, f)
794    }
795}
796
797impl Extend<char> for JavaString {
798    fn extend<T: IntoIterator<Item = char>>(&mut self, iter: T) {
799        let iterator = iter.into_iter();
800        let (lower_bound, _) = iterator.size_hint();
801        self.reserve(lower_bound);
802        iterator.for_each(move |c| self.push(c));
803    }
804}
805
806impl Extend<JavaCodePoint> for JavaString {
807    fn extend<T: IntoIterator<Item = JavaCodePoint>>(&mut self, iter: T) {
808        let iterator = iter.into_iter();
809        let (lower_bound, _) = iterator.size_hint();
810        self.reserve(lower_bound);
811        iterator.for_each(move |c| self.push_java(c));
812    }
813}
814
815impl Extend<String> for JavaString {
816    fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
817        iter.into_iter().for_each(move |s| self.push_str(&s));
818    }
819}
820
821impl Extend<JavaString> for JavaString {
822    fn extend<T: IntoIterator<Item = JavaString>>(&mut self, iter: T) {
823        iter.into_iter().for_each(move |s| self.push_java_str(&s));
824    }
825}
826
827impl<'a> Extend<&'a char> for JavaString {
828    fn extend<T: IntoIterator<Item = &'a char>>(&mut self, iter: T) {
829        self.extend(iter.into_iter().copied())
830    }
831}
832
833impl<'a> Extend<&'a JavaCodePoint> for JavaString {
834    fn extend<T: IntoIterator<Item = &'a JavaCodePoint>>(&mut self, iter: T) {
835        self.extend(iter.into_iter().copied())
836    }
837}
838
839impl<'a> Extend<&'a str> for JavaString {
840    fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
841        iter.into_iter().for_each(move |s| self.push_str(s));
842    }
843}
844
845impl<'a> Extend<&'a JavaStr> for JavaString {
846    fn extend<T: IntoIterator<Item = &'a JavaStr>>(&mut self, iter: T) {
847        iter.into_iter().for_each(move |s| self.push_java_str(s));
848    }
849}
850
851impl Extend<Box<str>> for JavaString {
852    fn extend<T: IntoIterator<Item = Box<str>>>(&mut self, iter: T) {
853        iter.into_iter().for_each(move |s| self.push_str(&s));
854    }
855}
856
857impl Extend<Box<JavaStr>> for JavaString {
858    fn extend<T: IntoIterator<Item = Box<JavaStr>>>(&mut self, iter: T) {
859        iter.into_iter().for_each(move |s| self.push_java_str(&s));
860    }
861}
862
863impl<'a> Extend<Cow<'a, str>> for JavaString {
864    fn extend<T: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: T) {
865        iter.into_iter().for_each(move |s| self.push_str(&s));
866    }
867}
868
869impl<'a> Extend<Cow<'a, JavaStr>> for JavaString {
870    fn extend<T: IntoIterator<Item = Cow<'a, JavaStr>>>(&mut self, iter: T) {
871        iter.into_iter().for_each(move |s| self.push_java_str(&s));
872    }
873}
874
875impl From<String> for JavaString {
876    #[inline]
877    fn from(value: String) -> Self {
878        unsafe {
879            // SAFETY: value is valid UTF-8
880            JavaString::from_semi_utf8_unchecked(value.into_bytes())
881        }
882    }
883}
884
885impl From<&String> for JavaString {
886    #[inline]
887    fn from(value: &String) -> Self {
888        Self::from(value.clone())
889    }
890}
891
892impl From<&JavaString> for JavaString {
893    #[inline]
894    fn from(value: &JavaString) -> Self {
895        value.clone()
896    }
897}
898
899impl From<&mut str> for JavaString {
900    #[inline]
901    fn from(value: &mut str) -> Self {
902        Self::from(&*value)
903    }
904}
905
906impl From<&str> for JavaString {
907    #[inline]
908    fn from(value: &str) -> Self {
909        Self::from(value.to_owned())
910    }
911}
912
913impl From<&mut JavaStr> for JavaString {
914    #[inline]
915    fn from(value: &mut JavaStr) -> Self {
916        Self::from(&*value)
917    }
918}
919
920impl From<&JavaStr> for JavaString {
921    #[inline]
922    fn from(value: &JavaStr) -> Self {
923        value.to_owned()
924    }
925}
926
927impl From<Box<str>> for JavaString {
928    #[inline]
929    fn from(value: Box<str>) -> Self {
930        Self::from(value.into_string())
931    }
932}
933
934impl From<Box<JavaStr>> for JavaString {
935    #[inline]
936    fn from(value: Box<JavaStr>) -> Self {
937        value.into_string()
938    }
939}
940
941impl<'a> From<Cow<'a, str>> for JavaString {
942    #[inline]
943    fn from(value: Cow<'a, str>) -> Self {
944        Self::from(value.into_owned())
945    }
946}
947
948impl<'a> From<Cow<'a, JavaStr>> for JavaString {
949    #[inline]
950    fn from(value: Cow<'a, JavaStr>) -> Self {
951        value.into_owned()
952    }
953}
954
955impl From<JavaString> for Arc<JavaStr> {
956    #[inline]
957    fn from(value: JavaString) -> Self {
958        Arc::from(&value[..])
959    }
960}
961
962impl From<JavaString> for Cow<'_, JavaStr> {
963    #[inline]
964    fn from(value: JavaString) -> Self {
965        Cow::Owned(value)
966    }
967}
968
969impl From<JavaString> for Rc<JavaStr> {
970    #[inline]
971    fn from(value: JavaString) -> Self {
972        Rc::from(&value[..])
973    }
974}
975
976impl From<JavaString> for Vec<u8> {
977    #[inline]
978    fn from(value: JavaString) -> Self {
979        value.into_bytes()
980    }
981}
982
983impl From<char> for JavaString {
984    #[inline]
985    fn from(value: char) -> Self {
986        Self::from(value.encode_utf8(&mut [0; 4]))
987    }
988}
989
990impl From<JavaCodePoint> for JavaString {
991    #[inline]
992    fn from(value: JavaCodePoint) -> Self {
993        unsafe {
994            // SAFETY: we're encoding into semi-valid UTF-8
995            JavaString::from_semi_utf8_unchecked(value.encode_semi_utf8(&mut [0; 4]).to_vec())
996        }
997    }
998}
999
1000impl FromIterator<char> for JavaString {
1001    #[inline]
1002    fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
1003        let mut buf = JavaString::new();
1004        buf.extend(iter);
1005        buf
1006    }
1007}
1008
1009impl<'a> FromIterator<&'a char> for JavaString {
1010    #[inline]
1011    fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
1012        let mut buf = JavaString::new();
1013        buf.extend(iter);
1014        buf
1015    }
1016}
1017
1018impl FromIterator<JavaCodePoint> for JavaString {
1019    #[inline]
1020    fn from_iter<T: IntoIterator<Item = JavaCodePoint>>(iter: T) -> Self {
1021        let mut buf = JavaString::new();
1022        buf.extend(iter);
1023        buf
1024    }
1025}
1026
1027impl<'a> FromIterator<&'a JavaCodePoint> for JavaString {
1028    #[inline]
1029    fn from_iter<T: IntoIterator<Item = &'a JavaCodePoint>>(iter: T) -> Self {
1030        let mut buf = JavaString::new();
1031        buf.extend(iter);
1032        buf
1033    }
1034}
1035
1036impl<'a> FromIterator<&'a str> for JavaString {
1037    #[inline]
1038    fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
1039        let mut buf = JavaString::new();
1040        buf.extend(iter);
1041        buf
1042    }
1043}
1044
1045impl FromIterator<String> for JavaString {
1046    fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
1047        let mut iterator = iter.into_iter();
1048
1049        match iterator.next() {
1050            None => JavaString::new(),
1051            Some(buf) => {
1052                let mut buf = JavaString::from(buf);
1053                buf.extend(iterator);
1054                buf
1055            }
1056        }
1057    }
1058}
1059
1060impl FromIterator<JavaString> for JavaString {
1061    fn from_iter<T: IntoIterator<Item = JavaString>>(iter: T) -> Self {
1062        let mut iterator = iter.into_iter();
1063
1064        match iterator.next() {
1065            None => JavaString::new(),
1066            Some(mut buf) => {
1067                buf.extend(iterator);
1068                buf
1069            }
1070        }
1071    }
1072}
1073
1074impl FromIterator<Box<str>> for JavaString {
1075    #[inline]
1076    fn from_iter<T: IntoIterator<Item = Box<str>>>(iter: T) -> Self {
1077        let mut buf = JavaString::new();
1078        buf.extend(iter);
1079        buf
1080    }
1081}
1082
1083impl FromIterator<Box<JavaStr>> for JavaString {
1084    #[inline]
1085    fn from_iter<T: IntoIterator<Item = Box<JavaStr>>>(iter: T) -> Self {
1086        let mut buf = JavaString::new();
1087        buf.extend(iter);
1088        buf
1089    }
1090}
1091
1092impl<'a> FromIterator<Cow<'a, str>> for JavaString {
1093    #[inline]
1094    fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self {
1095        let mut buf = JavaString::new();
1096        buf.extend(iter);
1097        buf
1098    }
1099}
1100
1101impl<'a> FromIterator<Cow<'a, JavaStr>> for JavaString {
1102    #[inline]
1103    fn from_iter<T: IntoIterator<Item = Cow<'a, JavaStr>>>(iter: T) -> Self {
1104        let mut buf = JavaString::new();
1105        buf.extend(iter);
1106        buf
1107    }
1108}
1109
1110impl FromStr for JavaString {
1111    type Err = Infallible;
1112
1113    #[inline]
1114    fn from_str(s: &str) -> Result<Self, Self::Err> {
1115        Ok(Self::from(s))
1116    }
1117}
1118
1119impl Hash for JavaString {
1120    #[inline]
1121    fn hash<H: Hasher>(&self, state: &mut H) {
1122        (**self).hash(state)
1123    }
1124}
1125
1126impl Index<Range<usize>> for JavaString {
1127    type Output = JavaStr;
1128
1129    #[inline]
1130    fn index(&self, index: Range<usize>) -> &Self::Output {
1131        &self[..][index]
1132    }
1133}
1134
1135impl Index<RangeFrom<usize>> for JavaString {
1136    type Output = JavaStr;
1137
1138    #[inline]
1139    fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
1140        &self[..][index]
1141    }
1142}
1143
1144impl Index<RangeFull> for JavaString {
1145    type Output = JavaStr;
1146
1147    #[inline]
1148    fn index(&self, _index: RangeFull) -> &Self::Output {
1149        self.as_java_str()
1150    }
1151}
1152
1153impl Index<RangeInclusive<usize>> for JavaString {
1154    type Output = JavaStr;
1155
1156    #[inline]
1157    fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
1158        &self[..][index]
1159    }
1160}
1161
1162impl Index<RangeTo<usize>> for JavaString {
1163    type Output = JavaStr;
1164
1165    #[inline]
1166    fn index(&self, index: RangeTo<usize>) -> &Self::Output {
1167        &self[..][index]
1168    }
1169}
1170
1171impl Index<RangeToInclusive<usize>> for JavaString {
1172    type Output = JavaStr;
1173
1174    #[inline]
1175    fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
1176        &self[..][index]
1177    }
1178}
1179
1180impl IndexMut<Range<usize>> for JavaString {
1181    #[inline]
1182    fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
1183        &mut self[..][index]
1184    }
1185}
1186
1187impl IndexMut<RangeFrom<usize>> for JavaString {
1188    #[inline]
1189    fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut Self::Output {
1190        &mut self[..][index]
1191    }
1192}
1193
1194impl IndexMut<RangeFull> for JavaString {
1195    #[inline]
1196    fn index_mut(&mut self, _index: RangeFull) -> &mut Self::Output {
1197        self.as_mut_java_str()
1198    }
1199}
1200
1201impl IndexMut<RangeInclusive<usize>> for JavaString {
1202    #[inline]
1203    fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output {
1204        &mut self[..][index]
1205    }
1206}
1207
1208impl IndexMut<RangeTo<usize>> for JavaString {
1209    #[inline]
1210    fn index_mut(&mut self, index: RangeTo<usize>) -> &mut Self::Output {
1211        &mut self[..][index]
1212    }
1213}
1214
1215impl IndexMut<RangeToInclusive<usize>> for JavaString {
1216    #[inline]
1217    fn index_mut(&mut self, index: RangeToInclusive<usize>) -> &mut Self::Output {
1218        &mut self[..][index]
1219    }
1220}
1221
1222impl PartialEq<str> for JavaString {
1223    #[inline]
1224    fn eq(&self, other: &str) -> bool {
1225        self[..] == other
1226    }
1227}
1228
1229impl PartialEq<JavaString> for str {
1230    #[inline]
1231    fn eq(&self, other: &JavaString) -> bool {
1232        self == other[..]
1233    }
1234}
1235
1236impl<'a> PartialEq<&'a str> for JavaString {
1237    #[inline]
1238    fn eq(&self, other: &&'a str) -> bool {
1239        self == *other
1240    }
1241}
1242
1243impl PartialEq<JavaString> for &str {
1244    #[inline]
1245    fn eq(&self, other: &JavaString) -> bool {
1246        *self == other
1247    }
1248}
1249
1250impl PartialEq<String> for JavaString {
1251    #[inline]
1252    fn eq(&self, other: &String) -> bool {
1253        &self[..] == other
1254    }
1255}
1256
1257impl PartialEq<JavaString> for String {
1258    #[inline]
1259    fn eq(&self, other: &JavaString) -> bool {
1260        self == &other[..]
1261    }
1262}
1263
1264impl PartialEq<JavaStr> for JavaString {
1265    #[inline]
1266    fn eq(&self, other: &JavaStr) -> bool {
1267        self[..] == other
1268    }
1269}
1270
1271impl<'a> PartialEq<&'a JavaStr> for JavaString {
1272    #[inline]
1273    fn eq(&self, other: &&'a JavaStr) -> bool {
1274        self == *other
1275    }
1276}
1277
1278impl<'a> PartialEq<Cow<'a, str>> for JavaString {
1279    #[inline]
1280    fn eq(&self, other: &Cow<'a, str>) -> bool {
1281        &self[..] == other
1282    }
1283}
1284
1285impl PartialEq<JavaString> for Cow<'_, str> {
1286    #[inline]
1287    fn eq(&self, other: &JavaString) -> bool {
1288        self == &other[..]
1289    }
1290}
1291
1292impl<'a> PartialEq<Cow<'a, JavaStr>> for JavaString {
1293    #[inline]
1294    fn eq(&self, other: &Cow<'a, JavaStr>) -> bool {
1295        &self[..] == other
1296    }
1297}
1298
1299impl PartialEq<JavaString> for Cow<'_, JavaStr> {
1300    #[inline]
1301    fn eq(&self, other: &JavaString) -> bool {
1302        self == &other[..]
1303    }
1304}
1305
1306impl Write for JavaString {
1307    #[inline]
1308    fn write_str(&mut self, s: &str) -> std::fmt::Result {
1309        self.push_str(s);
1310        Ok(())
1311    }
1312
1313    #[inline]
1314    fn write_char(&mut self, c: char) -> std::fmt::Result {
1315        self.push(c);
1316        Ok(())
1317    }
1318}
1319
1320pub struct Drain<'a> {
1321    string: *mut JavaString,
1322    start: usize,
1323    end: usize,
1324    iter: Chars<'a>,
1325}
1326
1327impl Debug for Drain<'_> {
1328    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1329        f.debug_tuple("Drain").field(&self.as_str()).finish()
1330    }
1331}
1332
1333unsafe impl Sync for Drain<'_> {}
1334unsafe impl Send for Drain<'_> {}
1335
1336impl Drop for Drain<'_> {
1337    #[inline]
1338    fn drop(&mut self) {
1339        unsafe {
1340            // Use Vec::drain. "Reaffirm" the bounds checks to avoid
1341            // panic code being inserted again.
1342            let self_vec = (*self.string).as_mut_vec();
1343            if self.start <= self.end && self.end <= self_vec.len() {
1344                self_vec.drain(self.start..self.end);
1345            }
1346        }
1347    }
1348}
1349
1350impl AsRef<JavaStr> for Drain<'_> {
1351    #[inline]
1352    fn as_ref(&self) -> &JavaStr {
1353        self.as_str()
1354    }
1355}
1356
1357impl AsRef<[u8]> for Drain<'_> {
1358    #[inline]
1359    fn as_ref(&self) -> &[u8] {
1360        self.as_str().as_bytes()
1361    }
1362}
1363
1364impl Drain<'_> {
1365    #[inline]
1366    #[must_use]
1367    pub fn as_str(&self) -> &JavaStr {
1368        self.iter.as_str()
1369    }
1370}
1371
1372impl Iterator for Drain<'_> {
1373    type Item = JavaCodePoint;
1374
1375    #[inline]
1376    fn next(&mut self) -> Option<JavaCodePoint> {
1377        self.iter.next()
1378    }
1379
1380    #[inline]
1381    fn size_hint(&self) -> (usize, Option<usize>) {
1382        self.iter.size_hint()
1383    }
1384
1385    #[inline]
1386    fn last(mut self) -> Option<JavaCodePoint> {
1387        self.next_back()
1388    }
1389}
1390
1391impl DoubleEndedIterator for Drain<'_> {
1392    #[inline]
1393    fn next_back(&mut self) -> Option<Self::Item> {
1394        self.iter.next_back()
1395    }
1396}
1397
1398impl FusedIterator for Drain<'_> {}