1use std::borrow::{Borrow, Cow};
2use std::convert::TryFrom;
3use std::fmt;
4use std::mem;
5use std::ops::Deref;
6
7#[repr(transparent)]
21#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct Line(str);
23
24impl Line {
25 #[must_use]
31 pub unsafe fn from_str_unchecked(val: &str) -> &Self {
32 mem::transmute(val)
33 }
34
35 #[must_use]
41 pub unsafe fn from_string_unchecked(val: String) -> Box<Self> {
42 let s: Box<str> = val.into_boxed_str();
43 mem::transmute(s)
44 }
45
46 #[must_use]
48 pub fn as_str(&self) -> &str {
49 &self.0
50 }
51
52 #[must_use]
54 pub fn into_string(self: Box<Self>) -> String {
55 let s: Box<str> = unsafe { mem::transmute(self) };
56 String::from(s)
57 }
58}
59
60impl fmt::Display for Line {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 write!(f, "{}", &self.0)
63 }
64}
65
66impl From<Box<Line>> for Cow<'_, Line> {
67 fn from(line: Box<Line>) -> Self {
68 Self::Owned(line)
69 }
70}
71impl<'a> From<&'a Line> for Cow<'a, Line> {
72 fn from(line: &'a Line) -> Self {
73 Self::Borrowed(line)
74 }
75}
76
77impl TryFrom<String> for Box<Line> {
78 type Error = &'static str;
79
80 fn try_from(val: String) -> Result<Self, Self::Error> {
81 if val.contains('\n') {
82 Err("string contains newlines")
83 } else {
84 Ok(unsafe { Line::from_string_unchecked(val) })
85 }
86 }
87}
88
89impl<'a> TryFrom<&'a str> for &'a Line {
90 type Error = &'static str;
91
92 fn try_from(val: &'a str) -> Result<Self, Self::Error> {
93 if val.contains('\n') {
94 Err("string contains newlines")
95 } else {
96 Ok(unsafe { Line::from_str_unchecked(val) })
97 }
98 }
99}
100
101impl Borrow<str> for Line {
102 fn borrow(&self) -> &str {
103 self.as_str()
104 }
105}
106
107impl Deref for Line {
108 type Target = str;
109
110 fn deref(&self) -> &Self::Target {
111 &self.0
112 }
113}
114
115impl ToOwned for Line {
116 type Owned = Box<Line>;
117
118 fn to_owned(&self) -> Self::Owned {
119 unsafe { Self::from_string_unchecked(self.0.to_owned()) }
120 }
121}
122
123impl Clone for Box<Line> {
124 fn clone(&self) -> Self {
125 (**self).to_owned()
126 }
127}