Skip to content

Commit

Permalink
Replace unstable chars usage
Browse files Browse the repository at this point in the history
Use private char iterator as done in kkawakam/rustyline#38 while waiting
for stabilisation of the chars method per rust-lang/rust#27802
This removes the need for `#[feature(io)]` letting skim compile on rust
stable.
  • Loading branch information
brookst committed Jan 19, 2017
1 parent 8f20286 commit a5f4f9d
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 2 deletions.
106 changes: 106 additions & 0 deletions src/char_iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//! An iterator over the `char`s of a reader.
//!
//! A copy of the unstable code from the stdlib's std::io::Read::chars.

use std::error;
use std::fmt;
use std::io;
use std::io::Read;
use std::str;

pub fn chars<R: Read>(read: R) -> Chars<R> where R: Sized {
Chars { inner: read }
}

// https://tools.ietf.org/html/rfc3629
static UTF8_CHAR_WIDTH: [u8; 256] = [
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
];

/// Given a first byte, determine how many bytes are in this UTF-8 character
#[inline]
fn utf8_char_width(b: u8) -> usize {
return UTF8_CHAR_WIDTH[b as usize] as usize;
}

pub struct Chars<R> {
inner: R,
}

#[derive(Debug)]
pub enum CharsError {
NotUtf8,
Other(io::Error),
}

impl<R: Read> Iterator for Chars<R> {
type Item = Result<char, CharsError>;

fn next(&mut self) -> Option<Result<char, CharsError>> {
let mut buf = [0];
let first_byte = match self.inner.read(&mut buf) {
Ok(0) => return None,
Ok(..) => buf[0],
Err(e) => return Some(Err(CharsError::Other(e))),
};
let width = utf8_char_width(first_byte);
if width == 1 { return Some(Ok(first_byte as char)) }
if width == 0 { return Some(Err(CharsError::NotUtf8)) }
let mut buf = [first_byte, 0, 0, 0];
{
let mut start = 1;
while start < width {
match self.inner.read(&mut buf[start..width]) {
Ok(0) => return Some(Err(CharsError::NotUtf8)),
Ok(n) => start += n,
Err(e) => return Some(Err(CharsError::Other(e))),
}
}
}
Some(match str::from_utf8(&buf[..width]).ok() {
Some(s) => Ok(s.chars().next().unwrap()),
None => Err(CharsError::NotUtf8),
})
}
}

impl error::Error for CharsError {
fn description(&self) -> &str {
match *self {
CharsError::NotUtf8 => "invalid utf8 encoding",
CharsError::Other(ref e) => error::Error::description(e),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
CharsError::NotUtf8 => None,
CharsError::Other(ref e) => e.cause(),
}
}
}

impl fmt::Display for CharsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CharsError::NotUtf8 => {
"byte stream did not contain valid utf8".fmt(f)
}
CharsError::Other(ref e) => e.fmt(f),
}
}
}
3 changes: 2 additions & 1 deletion src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::fs::File;
use std::collections::HashMap;
use std::collections::VecDeque;
use std::time::Duration;
use char_iter;

use event::{Event, EventArg, parse_action};

Expand Down Expand Up @@ -102,7 +103,7 @@ impl KeyBoard {
pub fn new(f: File) -> Self {
let (tx, rx) = channel();
thread::spawn(move || {
for ch in f.chars() {
for ch in char_iter::chars(f) {
if ch.is_ok() {
let _ = tx.send(ch.unwrap());
}
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![feature(io)]
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
extern crate libc;
Expand All @@ -19,6 +18,7 @@ mod curses;
mod query;
mod ansi;
mod sender;
mod char_iter;

use std::thread;
use std::time::Duration;
Expand Down

0 comments on commit a5f4f9d

Please sign in to comment.