Add encoded_len method to Encode trait. (#125)

This allows packets to calculate their exact length up front.
This isn't currently tested or being used for anything, but that will come in later changes.
This commit is contained in:
Ryan Johnson 2022-10-19 01:52:02 -07:00 committed by GitHub
parent 9b8fbc5d82
commit 71d82c5330
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 326 additions and 53 deletions

View file

@ -40,7 +40,7 @@ sha2 = "0.10.6"
thiserror = "1.0.35"
url = { version = "2.2.2", features = ["serde"] }
uuid = { version = "1.1.2", features = ["serde"] }
valence_nbt = "0.2.0"
valence_nbt = "0.3.0"
vek = "0.15.8"
[dependencies.tokio]

View file

@ -78,7 +78,7 @@ impl Cli {
let len = VarInt(read.packet_buf().len() as i32);
len.encode(&mut len_buf.as_mut_slice())?;
write.write_all(&len_buf[..len.written_size()]).await?;
write.write_all(&len_buf[..len.encoded_len()]).await?;
write.write_all(read.packet_buf()).await?;
pkt

View file

@ -56,6 +56,10 @@ impl Encode for BlockState {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(self.0 as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(self.0 as i32).encoded_len()
}
}
impl Decode for BlockState {

View file

@ -58,6 +58,10 @@ impl Encode for BlockPos {
_ => bail!("out of range: {self:?}"),
}
}
fn encoded_len(&self) -> usize {
8
}
}
impl Decode for BlockPos {

View file

@ -27,6 +27,10 @@ impl Encode for OptionalInt {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(self.0 as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(self.0 as i32).encoded_len()
}
}
impl Decode for OptionalInt {
@ -54,6 +58,10 @@ impl Encode for EulerAngle {
self.yaw.encode(w)?;
self.roll.encode(w)
}
fn encoded_len(&self) -> usize {
self.pitch.encoded_len() + self.yaw.encoded_len() + self.roll.encoded_len()
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@ -70,6 +78,10 @@ impl Encode for Facing {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(*self as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(*self as i32).encoded_len()
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@ -105,6 +117,12 @@ impl Encode for VillagerData {
VarInt(self.profession as i32).encode(w)?;
VarInt(self.level).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(self.kind as i32).encoded_len()
+ VarInt(self.profession as i32).encoded_len()
+ VarInt(self.level).encoded_len()
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
@ -162,6 +180,10 @@ impl Encode for Pose {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(*self as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(*self as i32).encoded_len()
}
}
/// The main hand of a player.
@ -176,6 +198,10 @@ impl Encode for MainArm {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
(*self as u8).encode(w)
}
fn encoded_len(&self) -> usize {
1
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
@ -193,6 +219,10 @@ impl Encode for BoatKind {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(*self as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(*self as i32).encoded_len()
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
@ -215,6 +245,10 @@ impl Encode for CatKind {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(*self as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(*self as i32).encoded_len()
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
@ -229,6 +263,10 @@ impl Encode for FrogKind {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(*self as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(*self as i32).encoded_len()
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
@ -270,6 +308,10 @@ impl Encode for PaintingKind {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(*self as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(*self as i32).encoded_len()
}
}
// TODO
@ -282,4 +324,8 @@ impl Encode for Particle {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
VarInt(*self as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(*self as i32).encoded_len()
}
}

View file

@ -225,6 +225,10 @@ impl<S: Encode> Encode for Ident<S> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
self.string.encode(w)
}
fn encoded_len(&self) -> usize {
self.string.encoded_len()
}
}
impl<S> Decode for Ident<S>

View file

@ -12,6 +12,10 @@ impl Encode for ItemKind {
fn encode(&self, w: &mut impl std::io::Write) -> anyhow::Result<()> {
VarInt(self.to_raw() as i32).encode(w)
}
fn encoded_len(&self) -> usize {
VarInt(self.to_raw() as i32).encoded_len()
}
}
impl Decode for ItemKind {

View file

@ -41,9 +41,17 @@ mod var_long;
/// Types that can be written to the Minecraft protocol.
pub trait Encode {
/// This function must be pure. In other words, consecutive calls to
/// `encode` must write the exact same sequence of bytes.
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()>;
/// Returns the number of bytes that will be written when [`Self::encode`]
/// is called.
///
/// If [`Self::encode`] results in `Ok`, the exact number of bytes reported
/// by this function must be written to the writer argument.
///
/// If the result is `Err`, then the number of written bytes must be less
/// than or equal to the count returned by this function.
fn encoded_len(&self) -> usize;
}
/// Types that can be read from the Minecraft protocol.
@ -58,6 +66,10 @@ impl Encode for () {
fn encode(&self, _w: &mut impl Write) -> anyhow::Result<()> {
Ok(())
}
fn encoded_len(&self) -> usize {
0
}
}
impl Decode for () {
@ -71,6 +83,10 @@ impl<T: Encode, U: Encode> Encode for (T, U) {
self.0.encode(w)?;
self.1.encode(w)
}
fn encoded_len(&self) -> usize {
self.0.encoded_len() + self.1.encoded_len()
}
}
impl<T: Decode, U: Decode> Decode for (T, U) {
@ -83,6 +99,10 @@ impl<T: Encode> Encode for &T {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
(*self).encode(w)
}
fn encoded_len(&self) -> usize {
(*self).encoded_len()
}
}
impl Encode for bool {
@ -90,6 +110,10 @@ impl Encode for bool {
w.write_u8(*self as u8)?;
Ok(())
}
fn encoded_len(&self) -> usize {
1
}
}
impl Decode for bool {
@ -105,6 +129,10 @@ impl Encode for u8 {
w.write_u8(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
1
}
}
impl Decode for u8 {
@ -118,6 +146,10 @@ impl Encode for i8 {
w.write_i8(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
1
}
}
impl Decode for i8 {
@ -131,6 +163,10 @@ impl Encode for u16 {
w.write_u16::<BigEndian>(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
2
}
}
impl Decode for u16 {
@ -144,6 +180,10 @@ impl Encode for i16 {
w.write_i16::<BigEndian>(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
2
}
}
impl Decode for i16 {
@ -157,6 +197,10 @@ impl Encode for u32 {
w.write_u32::<BigEndian>(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
4
}
}
impl Decode for u32 {
@ -170,6 +214,10 @@ impl Encode for i32 {
w.write_i32::<BigEndian>(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
4
}
}
impl Decode for i32 {
@ -183,6 +231,10 @@ impl Encode for u64 {
w.write_u64::<BigEndian>(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
8
}
}
impl Decode for u64 {
@ -196,6 +248,10 @@ impl Encode for i64 {
w.write_i64::<BigEndian>(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
8
}
}
impl Decode for i64 {
@ -214,6 +270,10 @@ impl Encode for f32 {
w.write_f32::<BigEndian>(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
4
}
}
impl Decode for f32 {
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
@ -233,6 +293,10 @@ impl Encode for f64 {
w.write_f64::<BigEndian>(*self)?;
Ok(())
}
fn encoded_len(&self) -> usize {
8
}
}
impl Decode for f64 {
@ -253,6 +317,13 @@ impl<T: Encode> Encode for Option<T> {
None => false.encode(w),
}
}
fn encoded_len(&self) -> usize {
1 + match self {
Some(t) => t.encoded_len(),
None => 0,
}
}
}
impl<T: Decode> Decode for Option<T> {
@ -269,6 +340,10 @@ impl<T: Encode> Encode for Box<T> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
self.as_ref().encode(w)
}
fn encoded_len(&self) -> usize {
self.as_ref().encoded_len()
}
}
impl<T: Decode> Decode for Box<T> {
@ -281,6 +356,10 @@ impl Encode for Box<str> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_string_bounded(self, 0, 32767, w)
}
fn encoded_len(&self) -> usize {
self.as_ref().encoded_len()
}
}
impl Decode for Box<str> {
@ -326,6 +405,10 @@ where
self.0.encode(w)
}
fn encoded_len(&self) -> usize {
self.0.encoded_len()
}
}
impl<T, const MIN: i64, const MAX: i64> Decode for BoundedInt<T, MIN, MAX>
@ -349,12 +432,20 @@ impl Encode for str {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_string_bounded(self, 0, 32767, w)
}
fn encoded_len(&self) -> usize {
VarInt(self.len().try_into().unwrap_or(i32::MAX)).encoded_len() + self.len()
}
}
impl Encode for String {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
self.as_str().encode(w)
}
fn encoded_len(&self) -> usize {
self.as_str().encoded_len()
}
}
impl Decode for String {
@ -367,6 +458,10 @@ impl<'a> Encode for Cow<'a, str> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
self.as_ref().encode(w)
}
fn encoded_len(&self) -> usize {
self.as_ref().encoded_len()
}
}
impl Decode for Cow<'static, str> {
@ -398,6 +493,10 @@ impl<const MIN: usize, const MAX: usize> Encode for BoundedString<MIN, MAX> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_string_bounded(&self.0, MIN, MAX, w)
}
fn encoded_len(&self) -> usize {
self.0.encoded_len()
}
}
impl<const MIN: usize, const MAX: usize> Decode for BoundedString<MIN, MAX> {
@ -412,10 +511,25 @@ impl<const MIN: usize, const MAX: usize> From<String> for BoundedString<MIN, MAX
}
}
impl<T: Encode> Encode for Vec<T> {
impl<'a, T: Encode> Encode for &'a [T] {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_array_bounded(self, 0, usize::MAX, w)
}
fn encoded_len(&self) -> usize {
let elems_len: usize = self.iter().map(|a| a.encoded_len()).sum();
VarInt(self.len().try_into().unwrap_or(i32::MAX)).encoded_len() + elems_len
}
}
impl<T: Encode> Encode for Vec<T> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
self.as_slice().encode(w)
}
fn encoded_len(&self) -> usize {
self.as_slice().encoded_len()
}
}
impl<T: Decode> Decode for Vec<T> {
@ -428,6 +542,10 @@ impl<T: Encode> Encode for Box<[T]> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_array_bounded(self, 0, usize::MAX, w)
}
fn encoded_len(&self) -> usize {
self.as_ref().encoded_len()
}
}
impl<T: Decode> Decode for Box<[T]> {
@ -438,19 +556,31 @@ impl<T: Decode> Decode for Box<[T]> {
impl<T: Encode, const N: usize> Encode for [T; N] {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_array_bounded(self, N, N, w)
// for t in self {
// t.encode(w)?;
// }
//
// Ok(())
self.as_slice().encode(w)
// encode_array_bounded(self, N, N, w)
}
fn encoded_len(&self) -> usize {
self.iter().map(Encode::encoded_len).sum()
}
}
impl<T: Decode, const N: usize> Decode for [T; N] {
fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
ensure!(VarInt::decode(r)?.0 == N as i32);
let mut elems = ArrayVec::new();
for _ in 0..N {
elems.push(T::decode(r)?);
}
elems
.into_inner()
.map_err(|_| unreachable!("mismatched array size"))
elems.into_inner().map_err(|_| unreachable!())
}
}
@ -459,6 +589,10 @@ impl<T: Encode> Encode for Vec2<T> {
self.x.encode(w)?;
self.y.encode(w)
}
fn encoded_len(&self) -> usize {
self.x.encoded_len() + self.y.encoded_len()
}
}
impl<T: Encode> Encode for Vec3<T> {
@ -467,6 +601,10 @@ impl<T: Encode> Encode for Vec3<T> {
self.y.encode(w)?;
self.z.encode(w)
}
fn encoded_len(&self) -> usize {
self.x.encoded_len() + self.y.encoded_len() + self.z.encoded_len()
}
}
impl<T: Encode> Encode for Vec4<T> {
@ -476,6 +614,10 @@ impl<T: Encode> Encode for Vec4<T> {
self.z.encode(w)?;
self.w.encode(w)
}
fn encoded_len(&self) -> usize {
self.x.encoded_len() + self.y.encoded_len() + self.z.encoded_len() + self.w.encoded_len()
}
}
impl<T: Decode> Decode for Vec2<T> {
@ -506,12 +648,16 @@ impl<T: Decode> Decode for Vec4<T> {
/// If the array is not in bounds, an error is generated while
/// encoding or decoding.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Default, Hash, Debug)]
pub struct BoundedArray<T, const MIN: usize = 0, const MAX: usize = { usize::MAX }>(pub Vec<T>);
pub struct BoundedArray<T, const MIN: usize, const MAX: usize>(pub Vec<T>);
impl<T: Encode, const MIN: usize, const MAX: usize> Encode for BoundedArray<T, MIN, MAX> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_array_bounded(&self.0, MIN, MAX, w)
}
fn encoded_len(&self) -> usize {
self.0.as_slice().encoded_len()
}
}
impl<T: Decode, const MIN: usize, const MAX: usize> Decode for BoundedArray<T, MIN, MAX> {
@ -531,6 +677,10 @@ impl Encode for Uuid {
w.write_u128::<BigEndian>(self.as_u128())?;
Ok(())
}
fn encoded_len(&self) -> usize {
16
}
}
impl Decode for Uuid {
@ -543,6 +693,10 @@ impl Encode for Compound {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
Ok(nbt::to_binary_writer(w, self, "")?)
}
fn encoded_len(&self) -> usize {
self.binary_encoded_len("")
}
}
impl Decode for Compound {
@ -554,7 +708,11 @@ impl Decode for Compound {
impl Encode for BitVec<u64> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_array_bounded(self.as_raw_slice(), 0, usize::MAX, w)
self.as_raw_slice().encode(w)
}
fn encoded_len(&self) -> usize {
self.as_raw_slice().encoded_len()
}
}
@ -567,7 +725,11 @@ impl Decode for BitVec<u64> {
impl Encode for BitBox<u64> {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
encode_array_bounded(self.as_raw_slice(), 0, usize::MAX, w)
self.as_raw_slice().encode(w)
}
fn encoded_len(&self) -> usize {
self.as_raw_slice().encoded_len()
}
}
@ -593,7 +755,11 @@ impl Decode for RawBytes {
impl Encode for RawBytes {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
w.write_all(&self.0).map_err(|e| e.into())
Ok(w.write_all(&self.0)?)
}
fn encoded_len(&self) -> usize {
self.0.len()
}
}
@ -609,6 +775,10 @@ impl Encode for Option<EntityId> {
}
.encode(w)
}
fn encoded_len(&self) -> usize {
4
}
}
fn encode_array_bounded<T: Encode>(

View file

@ -20,6 +20,10 @@ impl Encode for ByteAngle {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
self.0.encode(w)
}
fn encoded_len(&self) -> usize {
self.0.encoded_len()
}
}
impl Decode for ByteAngle {

View file

@ -55,7 +55,7 @@ impl<W: AsyncWrite + Unpin> Encoder<W> {
z.read_to_end(&mut self.compress_buf)?;
let data_len_len = VarInt(data_len as i32).written_size();
let data_len_len = VarInt(data_len as i32).encoded_len();
let packet_len = data_len_len + self.compress_buf.len();
ensure!(packet_len <= MAX_PACKET_SIZE as usize, "bad packet length");
@ -67,7 +67,7 @@ impl<W: AsyncWrite + Unpin> Encoder<W> {
self.buf.extend_from_slice(&self.compress_buf);
self.compress_buf.clear();
} else {
let packet_len = VarInt(0).written_size() + data_len;
let packet_len = VarInt(0).encoded_len() + data_len;
ensure!(packet_len <= MAX_PACKET_SIZE as usize, "bad packet length");

View file

@ -15,7 +15,6 @@ use serde::{Deserialize, Serialize};
use uuid::Uuid;
use vek::Vec3;
// use {def_bitfield, def_enum, def_struct};
use crate::block_pos::BlockPos;
use crate::ident::Ident;
use crate::nbt::Compound;
@ -82,6 +81,13 @@ macro_rules! def_struct {
)*
Ok(())
}
fn encoded_len(&self) -> usize {
0
$(
+ self.$field.encoded_len()
)*
}
}
impl Decode for $name {
@ -152,6 +158,20 @@ macro_rules! def_enum {
_ => unreachable!("uninhabited enum?")
}
}
fn encoded_len(&self) -> usize {
match self {
$(
if_typ_is_empty_pat!($($typ)?, $name::$variant, $name::$variant(val)) => {
<$tag_ty>::encoded_len(&$lit.into()) +
if_typ_is_empty_expr!($($typ)?, 0, Encode::encoded_len(val))
}
)*
#[allow(unreachable_patterns)]
_ => unreachable!("uninhabited enum?")
}
}
}
impl Decode for $name {
@ -264,6 +284,10 @@ macro_rules! def_bitfield {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
self.0.encode(w)
}
fn encoded_len(&self) -> usize {
self.0.encoded_len()
}
}
impl Decode for $name {

View file

@ -366,12 +366,6 @@ pub mod play {
}
}
// #[derive(Clone, Debug, Serialize, Deserialize)]
// pub struct ChunkDataHeightmaps {
// #[serde(rename = "MOTION_BLOCKING", with = "crate::nbt::long_array")]
// pub motion_blocking: Vec<i64>,
// }
def_struct! {
ChunkDataBlockEntity {
packed_xz: i8,

View file

@ -26,6 +26,17 @@ impl Encode for Slot {
}
}
}
fn encoded_len(&self) -> usize {
match self {
None => 1,
Some(s) => {
1 + s.item.encoded_len()
+ 1
+ s.nbt.as_ref().map(|nbt| nbt.encoded_len()).unwrap_or(1)
}
}
}
}
impl Decode for Slot {

View file

@ -13,27 +13,12 @@ impl VarInt {
/// The maximum number of bytes a VarInt could occupy when read from and
/// written to the Minecraft protocol.
pub const MAX_SIZE: usize = 5;
/// The number of bytes this `VarInt` will occupy when written to the
/// Minecraft protocol.
pub const fn written_size(self) -> usize {
let val = self.0 as u32;
if val & 0b11110000_00000000_00000000_00000000 != 0 {
5
} else if val & 0b11111111_11100000_00000000_00000000 != 0 {
4
} else if val & 0b11111111_11111111_11000000_00000000 != 0 {
3
} else if val & 0b11111111_11111111_11111111_10000000 != 0 {
2
} else {
1
}
}
}
impl Encode for VarInt {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
// TODO: optimize this.
let mut val = self.0 as u32;
loop {
if val & 0b11111111111111111111111110000000 == 0 {
@ -44,6 +29,13 @@ impl Encode for VarInt {
val >>= 7;
}
}
fn encoded_len(&self) -> usize {
match self.0 {
0 => 1,
n => (31 - n.leading_zeros() as usize) / 7 + 1,
}
}
}
impl Decode for VarInt {
@ -85,7 +77,7 @@ mod tests {
use super::*;
#[test]
fn written_size_correct() {
fn encoded_len_correct() {
let mut rng = thread_rng();
let mut buf = Vec::new();
@ -96,7 +88,7 @@ mod tests {
{
buf.clear();
n.encode(&mut buf).unwrap();
assert_eq!(buf.len(), n.written_size());
assert_eq!(buf.len(), n.encoded_len());
}
}

View file

@ -17,6 +17,8 @@ impl VarLong {
impl Encode for VarLong {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
// TODO: optimize this.
let mut val = self.0 as u64;
loop {
if val & 0b1111111111111111111111111111111111111111111111111111111110000000 == 0 {
@ -27,6 +29,13 @@ impl Encode for VarLong {
val >>= 7;
}
}
fn encoded_len(&self) -> usize {
match self.0 {
0 => 1,
n => (63 - n.leading_zeros() as usize) / 7 + 1,
}
}
}
impl Decode for VarLong {

View file

@ -112,17 +112,21 @@ impl Text {
}
/// Writes this text object as plain text to the provided writer.
pub fn write_plain(&self, w: &mut impl fmt::Write) -> fmt::Result {
match &self.content {
TextContent::Text { text } => w.write_str(text.as_ref())?,
TextContent::Translate { translate } => w.write_str(translate.as_ref())?,
pub fn write_plain(&self, mut w: impl fmt::Write) -> fmt::Result {
fn write_plain_impl(this: &Text, w: &mut impl fmt::Write) -> fmt::Result {
match &this.content {
TextContent::Text { text } => w.write_str(text.as_ref())?,
TextContent::Translate { translate } => w.write_str(translate.as_ref())?,
}
for child in &this.extra {
write_plain_impl(child, w)?;
}
Ok(())
}
for child in &self.extra {
child.write_plain(w)?;
}
Ok(())
write_plain_impl(self, &mut w)
}
/// Returns `true` if the text contains no characters. Returns `false`
@ -443,8 +447,8 @@ impl<'a, 'b> From<&'a Text> for Cow<'b, str> {
}
impl fmt::Display for Text {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", String::from(self))
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.write_plain(f)
}
}
@ -452,6 +456,10 @@ impl Encode for Text {
fn encode(&self, w: &mut impl Write) -> anyhow::Result<()> {
BoundedString::<0, 262144>(serde_json::to_string(self)?).encode(w)
}
fn encoded_len(&self) -> usize {
todo!("remove Encode impl on text and come up with solution")
}
}
impl Decode for Text {
@ -467,7 +475,6 @@ impl Default for TextContent {
}
}
#[allow(missing_docs)]
impl Color {
pub const AQUA: Color = Color::new(85, 255, 255);
pub const BLACK: Color = Color::new(0, 0, 0);