Refactor Decoder from trait to struct to make it Sized.

This commit is contained in:
Henri Sivonen
2016-01-20 13:03:35 +02:00
parent d4c7d2649c
commit 72f2bbf8fa
4 changed files with 152 additions and 59 deletions
+7 -8
View File
@@ -11,14 +11,15 @@ use Decoder;
use DecoderResult;
use handles::*;
use data::*;
use variant::*;
pub struct Big5Decoder {
lead: u8,
}
impl Big5Decoder {
pub fn new() -> Big5Decoder {
Big5Decoder { lead: 0 }
pub fn new() -> Decoder {
Decoder::new(VariantDecoder::Big5(Big5Decoder { lead: 0 }))
}
fn plus_one_if_lead(&self, byte_length: usize) -> usize {
@@ -29,14 +30,12 @@ impl Big5Decoder {
1
}
}
}
impl Decoder for Big5Decoder {
fn reset(&mut self) {
pub fn reset(&mut self) {
self.lead = 0u8;
}
fn max_utf16_buffer_length(&self, byte_length: usize) -> usize {
pub fn max_utf16_buffer_length(&self, byte_length: usize) -> usize {
// If there is a lead but the next byte isn't a valid trail, an
// error is generated for the lead (+1). Then another iteration checks
// space, which needs +1 to account for the possibility of astral
@@ -44,7 +43,7 @@ impl Decoder for Big5Decoder {
self.plus_one_if_lead(byte_length) + 1
}
fn max_utf8_buffer_length(&self, byte_length: usize) -> usize {
pub fn max_utf8_buffer_length(&self, byte_length: usize) -> usize {
// No need to account for REPLACEMENT CHARACTERS.
// Cases:
// ASCII: 1 to 1
@@ -64,7 +63,7 @@ impl Decoder for Big5Decoder {
(len * 2)
}
fn max_utf8_buffer_length_with_replacement(&self, byte_length: usize) -> usize {
pub fn max_utf8_buffer_length_with_replacement(&self, byte_length: usize) -> usize {
// If there is a lead but the next byte isn't a valid trail, an
// error is generated for the lead (+(1*3)). Then another iteration
// checks space, which needs +3 to account for the possibility of astral
+68 -46
View File
@@ -13,8 +13,11 @@ mod macros;
mod handles;
mod big5;
mod data;
mod variant;
pub mod ffi;
use variant::*;
static TEST: Encoding = Encoding {
name: "foo",
dom_name: "Foo",
@@ -189,9 +192,19 @@ pub enum DecoderResult {
/// `src` may not have been completely consumed. In that case, the caller must
/// pass the unconsumed contents of `src` to `decode_*` again upon the next
/// call.
pub trait Decoder {
pub struct Decoder {
variant: VariantDecoder,
}
impl Decoder {
fn new(decoder: VariantDecoder) -> Decoder {
Decoder { variant: decoder }
}
/// Make the decoder ready to process a new stream.
fn reset(&mut self);
pub fn reset(&mut self) {
self.variant.reset();
}
/// Query the worst-case UTF-16 output size (with or without replacement).
///
@@ -204,7 +217,9 @@ pub trait Decoder {
/// `_with_replacement` case.
///
/// Available via the C wrapper.
fn max_utf16_buffer_length(&self, byte_length: usize) -> usize;
pub fn max_utf16_buffer_length(&self, byte_length: usize) -> usize {
self.variant.max_utf16_buffer_length(byte_length)
}
/// Query the worst-case UTF-8 output size _without replacement_.
///
@@ -217,7 +232,9 @@ pub trait Decoder {
/// Use `max_utf8_buffer_length_with_replacement` for that case.
///
/// Available via the C wrapper.
fn max_utf8_buffer_length(&self, byte_length: usize) -> usize;
pub fn max_utf8_buffer_length(&self, byte_length: usize) -> usize {
self.variant.max_utf8_buffer_length(byte_length)
}
/// Query the worst-case UTF-8 output size _with replacement_.
///
@@ -228,7 +245,9 @@ pub trait Decoder {
/// sequence.
///
/// Available via the C wrapper.
fn max_utf8_buffer_length_with_replacement(&self, byte_length: usize) -> usize;
pub fn max_utf8_buffer_length_with_replacement(&self, byte_length: usize) -> usize {
self.variant.max_utf8_buffer_length_with_replacement(byte_length)
}
/// Incrementally decode a byte stream into UTF-16.
///
@@ -236,11 +255,13 @@ pub trait Decoder {
/// methods collectively.
///
/// Available via the C wrapper.
fn decode_to_utf16(&mut self,
src: &[u8],
dst: &mut [u16],
last: bool)
-> (DecoderResult, usize, usize);
pub fn decode_to_utf16(&mut self,
src: &[u8],
dst: &mut [u16],
last: bool)
-> (DecoderResult, usize, usize) {
self.variant.decode_to_utf16(src, dst, last)
}
/// Incrementally decode a byte stream into UTF-8.
///
@@ -248,11 +269,13 @@ pub trait Decoder {
/// methods collectively.
///
/// Available via the C wrapper.
fn decode_to_utf8(&mut self,
src: &[u8],
dst: &mut [u8],
last: bool)
-> (DecoderResult, usize, usize);
pub fn decode_to_utf8(&mut self,
src: &[u8],
dst: &mut [u8],
last: bool)
-> (DecoderResult, usize, usize) {
self.variant.decode_to_utf8(src, dst, last)
}
/// Incrementally decode a byte stream into UTF-8 with type system signaling
/// of UTF-8 validity.
@@ -265,11 +288,11 @@ pub trait Decoder {
/// methods collectively.
///
/// Available to Rust only.
fn decode_to_str(&mut self,
src: &[u8],
dst: &mut str,
last: bool)
-> (DecoderResult, usize, usize) {
pub fn decode_to_str(&mut self,
src: &[u8],
dst: &mut str,
last: bool)
-> (DecoderResult, usize, usize) {
let bytes: &mut [u8] = unsafe { std::mem::transmute(dst) };
let (result, read, written) = self.decode_to_utf8(src, bytes, last);
let len = bytes.len();
@@ -296,11 +319,11 @@ pub trait Decoder {
/// methods collectively.
///
/// Available to Rust only.
fn decode_to_string(&mut self,
src: &[u8],
dst: &mut String,
last: bool)
-> (DecoderResult, usize) {
pub fn decode_to_string(&mut self,
src: &[u8],
dst: &mut String,
last: bool)
-> (DecoderResult, usize) {
unsafe {
let vec = dst.as_mut_vec();
let old_len = vec.len();
@@ -319,11 +342,11 @@ pub trait Decoder {
/// methods collectively.
///
/// Available via the C wrapper.
fn decode_to_utf16_with_replacement(&mut self,
src: &[u8],
dst: &mut [u16],
last: bool)
-> (WithReplacementResult, usize, usize, bool) {
pub fn decode_to_utf16_with_replacement(&mut self,
src: &[u8],
dst: &mut [u16],
last: bool)
-> (WithReplacementResult, usize, usize, bool) {
let mut had_errors = false;
let mut total_read = 0usize;
let mut total_written = 0usize;
@@ -364,11 +387,11 @@ pub trait Decoder {
/// methods collectively.
///
/// Available via the C wrapper.
fn decode_to_utf8_with_replacement(&mut self,
src: &[u8],
dst: &mut [u8],
last: bool)
-> (WithReplacementResult, usize, usize, bool) {
pub fn decode_to_utf8_with_replacement(&mut self,
src: &[u8],
dst: &mut [u8],
last: bool)
-> (WithReplacementResult, usize, usize, bool) {
let mut had_errors = false;
let mut total_read = 0usize;
let mut total_written = 0usize;
@@ -420,11 +443,11 @@ pub trait Decoder {
/// methods collectively.
///
/// Available to Rust only.
fn decode_to_str_with_replacement(&mut self,
src: &[u8],
dst: &mut str,
last: bool)
-> (WithReplacementResult, usize, usize, bool) {
pub fn decode_to_str_with_replacement(&mut self,
src: &[u8],
dst: &mut str,
last: bool)
-> (WithReplacementResult, usize, usize, bool) {
let bytes: &mut [u8] = unsafe { std::mem::transmute(dst) };
let (result, read, written, replaced) = self.decode_to_utf8_with_replacement(src,
bytes,
@@ -455,11 +478,11 @@ pub trait Decoder {
/// methods collectively.
///
/// Available to Rust only.
fn decode_to_string_with_replacement(&mut self,
src: &[u8],
dst: &mut String,
last: bool)
-> (WithReplacementResult, usize, bool) {
pub fn decode_to_string_with_replacement(&mut self,
src: &[u8],
dst: &mut String,
last: bool)
-> (WithReplacementResult, usize, bool) {
unsafe {
let vec = dst.as_mut_vec();
let old_len = vec.len();
@@ -471,7 +494,6 @@ pub trait Decoder {
(result, read, replaced)
}
}
}
/// Result of a (potentially partial) encode operation.
+5 -5
View File
@@ -20,11 +20,11 @@ macro_rules! decoder_function {
$name:ident,
$code_unit:ty,
$dest_struct:ident) => (
fn $name(&mut $slf,
src: &[u8],
dst: &mut [$code_unit],
last: bool)
-> (DecoderResult, usize, usize) {
pub fn $name(&mut $slf,
src: &[u8],
dst: &mut [$code_unit],
last: bool)
-> (DecoderResult, usize, usize) {
let mut source = ByteSource::new(src);
let mut $dest = $dest_struct::new(dst);
loop {
+72
View File
@@ -0,0 +1,72 @@
// Copyright 2015-2016 Mozilla Foundation. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module provides enums that wrap the various decoders and encoders.
//! The purpose is to make `Decoder` and `Encoder` `Sized` by writing the
//! dispatch explicitly for a finite set of specialized decoders and encoders.
//! Unfortunately, this means the compiler doesn't generate the dispatch code
//! and it has to be written here instead.
//!
//! The purpose of making `Decoder` and `Encoder` `Sized` is to allow stack
//! allocation in Rust code, including the convenience methods on `Encoding`.
use big5::*;
use super::*;
pub enum VariantDecoder {
Big5(Big5Decoder),
}
impl VariantDecoder {
pub fn reset(&mut self) {
match self {
&mut VariantDecoder::Big5(ref mut d) => {
d.reset();
}
}
}
pub fn max_utf16_buffer_length(&self, byte_length: usize) -> usize {
match self {
&VariantDecoder::Big5(ref d) => d.max_utf16_buffer_length(byte_length),
}
}
pub fn max_utf8_buffer_length(&self, byte_length: usize) -> usize {
match self {
&VariantDecoder::Big5(ref d) => d.max_utf8_buffer_length(byte_length),
}
}
pub fn max_utf8_buffer_length_with_replacement(&self, byte_length: usize) -> usize {
match self {
&VariantDecoder::Big5(ref d) => d.max_utf8_buffer_length_with_replacement(byte_length),
}
}
pub fn decode_to_utf16(&mut self,
src: &[u8],
dst: &mut [u16],
last: bool)
-> (DecoderResult, usize, usize) {
match self {
&mut VariantDecoder::Big5(ref mut d) => d.decode_to_utf16(src, dst, last),
}
}
pub fn decode_to_utf8(&mut self,
src: &[u8],
dst: &mut [u8],
last: bool)
-> (DecoderResult, usize, usize) {
match self {
&mut VariantDecoder::Big5(ref mut d) => d.decode_to_utf8(src, dst, last),
}
}
}