New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vectors and buffers #202

wants to merge 10 commits into
base: master

Start on buffers. Port buffer-hash, remove sha1_ctx API.

  • Loading branch information...
birkenfeld committed Jun 5, 2017
commit c7f81453a47ae8ebfd9d7e45bb8909b73e87d886
Copy path View file
@@ -682,10 +682,13 @@ extern "C" {
pub static Qsequencep: Lisp_Object;
pub fn Fcons(car: Lisp_Object, cdr: Lisp_Object) -> Lisp_Object;
pub fn Fcurrent_buffer() -> Lisp_Object;
pub fn Fget_buffer(buffer_or_name: Lisp_Object) -> Lisp_Object;
pub fn make_float(float_value: libc::c_double) -> Lisp_Object;
pub fn make_string(s: *const libc::c_char, length: libc::ptrdiff_t) -> Lisp_Object;
pub fn make_unibyte_string(s: *const libc::c_char, length: libc::ptrdiff_t) -> Lisp_Object;
pub fn make_uninit_string(length: EmacsInt) -> Lisp_Object;
pub fn make_uninit_multibyte_string(nchars: EmacsInt, nbytes: EmacsInt) -> Lisp_Object;
pub fn string_to_multibyte(string: Lisp_Object) -> Lisp_Object;
@@ -706,6 +709,7 @@ extern "C" {
// number of arguments.
// TODO: define a Rust version of this that uses Rust strings.
pub fn error(m: *const u8, ...) -> !;
pub fn nsberror(spec: Lisp_Object) -> !;
pub fn emacs_abort() -> !;
Copy path View file
@@ -0,0 +1,200 @@
//! Functions operating on buffers.
use libc::{c_void, c_int, c_uchar, ptrdiff_t, off_t, time_t, timespec};
use lisp::{LispObject, ExternalPtr};
use vectors::Lisp_Vectorlike_Header;
use remacs_sys::EmacsInt;
pub const BEG_BYTE: ptrdiff_t = 1;
/// Represents an Emacs buffer. For documentation see struct buffer in
/// buffer.h.
pub struct Lisp_Buffer {
header: Lisp_Vectorlike_Header,
name: LispObject,
filename: LispObject,
directory: LispObject,
backed_up: LispObject,
save_length: LispObject,
auto_save_file_name: LispObject,
read_only: LispObject,
mark: LispObject,
local_var_alist: LispObject,
major_mode: LispObject,
mode_name: LispObject,
mode_line_format: LispObject,
header_line_format: LispObject,
keymap: LispObject,
abbrev_table: LispObject,
syntax_table: LispObject,
category_table: LispObject,
case_fold_search: LispObject,
tab_width: LispObject,
fill_column: LispObject,
left_margin: LispObject,
auto_fill_function: LispObject,
downcase_table: LispObject,
upcase_table: LispObject,
case_canon_table: LispObject,
case_eqv_table: LispObject,
truncate_lines: LispObject,
word_wrap: LispObject,
ctl_arrow: LispObject,
bidi_display_reordering: LispObject,
bidi_paragraph_direction: LispObject,
selective_display: LispObject,
selective_display_ellipses: LispObject,
minor_modes: LispObject,
overwrite_mode: LispObject,
abbrev_mode: LispObject,
display_table: LispObject,
mark_active: LispObject,
enable_multibyte_characters: LispObject,
buffer_file_coding_system: LispObject,
file_format: LispObject,
auto_save_file_format: LispObject,
cache_long_scans: LispObject,
width_table: LispObject,
pt_marker: LispObject,
begv_marker: LispObject,
zv_marker: LispObject,
point_before_scroll: LispObject,
file_truename: LispObject,
invisibility_spec: LispObject,
last_selected_window: LispObject,
display_count: LispObject,
left_margin_cols: LispObject,
right_margin_cols: LispObject,
left_fringe_width: LispObject,
right_fringe_width: LispObject,
fringes_outside_margins: LispObject,
scroll_bar_width: LispObject,
scroll_bar_height: LispObject,
vertical_scroll_bar_type: LispObject,
horizontal_scroll_bar_type: LispObject,
indicate_empty_lines: LispObject,
indicate_buffer_boundaries: LispObject,
fringe_indicator_alist: LispObject,
fringe_cursor_alist: LispObject,
display_time: LispObject,
scroll_up_aggressively: LispObject,
scroll_down_aggressively: LispObject,
cursor_type: LispObject,
extra_line_spacing: LispObject,
cursor_in_non_selected_windows: LispObject,
own_text: Lisp_Buffer_Text,
text: *mut Lisp_Buffer_Text,
next: *mut Lisp_Buffer,
pt: ptrdiff_t,
pt_byte: ptrdiff_t,
begv: ptrdiff_t,
begv_byte: ptrdiff_t,
zv: ptrdiff_t,
zv_byte: ptrdiff_t,
base_buffer: *mut Lisp_Buffer,
indirections: c_int,
window_count: c_int,
local_flags: [c_uchar; 50],
modtime: timespec,
modtime_size: off_t,
auto_save_modified: EmacsInt,
display_error_modiff: EmacsInt,
auto_save_failure_time: time_t,
last_window_start: ptrdiff_t,
newline_cache: *mut c_void,
width_run_cache: *mut c_void,
bidi_paragraph_cache: *mut c_void,
// XXX in C, bitfield with two bools
flags: u8,
overlays_before: *mut c_void,
overlays_after: *mut c_void,
overlay_center: ptrdiff_t,
undo_list: LispObject,
/// Represents text contents of an Emacs buffer. For documentation see
/// struct buffer_text in buffer.h.
pub struct Lisp_Buffer_Text {
beg: *mut c_uchar,
gpt: ptrdiff_t,
z: ptrdiff_t,
gpt_byte: ptrdiff_t,
z_byte: ptrdiff_t,
gap_size: ptrdiff_t,
modiff: EmacsInt,
chars_modiff: EmacsInt,
save_modiff: EmacsInt,
overlay_modiff: EmacsInt,
compact: EmacsInt,
beg_unchanged: ptrdiff_t,
end_unchanged: ptrdiff_t,
unchanged_modified: EmacsInt,
overlay_unchanged_modified: EmacsInt,
// until we define struct interval
intervals: *mut c_void,
// until we define struct Lisp_Marker
markers: *mut c_void,
// XXX: in Emacs, a bitfield of 2 booleans
flags: u8,
pub type LispBufferRef = ExternalPtr<Lisp_Buffer>;
impl LispBufferRef {
pub fn beg_addr(&self) -> *mut c_uchar {
unsafe { (*self.text).beg }
pub fn beg_byte(&self) -> ptrdiff_t {
pub fn gpt_byte(&self) -> ptrdiff_t {
unsafe { (*self.text).gpt_byte }
pub fn gap_end_addr(&self) -> *mut c_uchar {
unsafe {
.offset((*self.text).gpt_byte + (*self.text).gap_size - BEG_BYTE)
pub fn z_addr(&self) -> *mut c_uchar {
unsafe {
.offset((*self.text).gap_size + (*self.text).z_byte - BEG_BYTE)
pub fn z_byte(&self) -> ptrdiff_t {
unsafe { (*self.text).z_byte }
Copy path View file
@@ -1,12 +1,14 @@
extern crate libc;
pub mod sha1_ctx;
use sha1;
use sha2::{Sha224, Digest, Sha256, Sha384, Sha512};
use std::{ptr, slice};
use libc::{c_char, c_void, size_t};
use lisp::LispObject;
use remacs_sys::{nsberror, Fcurrent_buffer, Fget_buffer, EmacsInt, make_uninit_string};
use remacs_macros::lisp_fn;
pub unsafe extern "C" fn sha1_buffer(buffer: *const c_char,
len: size_t,
@@ -67,3 +69,41 @@ pub unsafe extern "C" fn sha512_buffer(buffer: *const c_char,
sha2_hash_buffer(Sha512::new(), buffer, len, resblock);
/// Return a hash of the contents of BUFFER-OR-NAME.
/// This hash is performed on the raw internal format of the buffer,
/// disregarding any coding systems.
/// If nil, use the current buffer.
/// (fn &optional BUFFER_OR_NAME)
#[lisp_fn(min = "0")]
fn buffer_hash(buffer_or_name: LispObject) -> LispObject {
let buffer = LispObject::from_raw(if buffer_or_name.is_nil() {
unsafe { Fcurrent_buffer() }
} else {
unsafe { Fget_buffer(buffer_or_name.to_raw()) }
if buffer.is_nil() {
unsafe { nsberror(buffer_or_name.to_raw()) };
let b = buffer.as_vectorlike().unwrap().as_buffer().unwrap();
let mut ctx = sha1::Sha1::new();
ctx.update(unsafe {
slice::from_raw_parts(b.beg_addr(), (b.gpt_byte() - b.beg_byte()) as usize)
if b.gpt_byte() < b.z_byte() {
ctx.update(unsafe {
(b.z_addr() as usize - b.gap_end_addr() as usize))
let formatted = ctx.digest().to_string();
let digest = LispObject::from_raw(unsafe { make_uninit_string(formatted.len() as EmacsInt) });
Copy path View file

This file was deleted.

Oops, something went wrong.
Copy path View file
@@ -34,6 +34,7 @@ mod base64;
mod crypto;
mod str2sig;
mod multibyte;
mod buffers;
use remacs_sys::Lisp_Subr;
@@ -83,14 +84,11 @@ pub use vectors::Fsort;
pub use lists::merge;
// Cryptographic functions used in the C codebase.
pub use crypto::sha256_buffer;
pub use crypto::sha1_buffer;
pub use crypto::sha224_buffer;
pub use crypto::sha256_buffer;
pub use crypto::sha384_buffer;
pub use crypto::sha512_buffer;
pub use crypto::sha224_buffer;
pub use crypto::sha1_ctx::sha1_ctx_new;
pub use crypto::sha1_ctx::sha1_process_bytes;
pub use crypto::sha1_ctx::sha1_finish_ctx;
// Used in process.c
pub use str2sig::str2sig;
@@ -177,6 +175,7 @@ pub extern "C" fn rust_init_syms() {
Copy path View file
@@ -86,6 +86,16 @@ impl LispStringRef {
pub fn sdata_ptr(&mut self) -> *mut c_char { as *mut c_char
pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts( as *const u8, self.len_bytes() as usize) }
pub fn as_mut_slice(&self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut( as *mut u8, self.len_bytes() as usize) }
fn string_overflow() -> ! {
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.