Skip to main content

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