-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// 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.
-
+use std::borrow::Cow;
+use std::cmp::min;
use std::ops::{Add, Sub};
-use Config;
+use crate::Config;
#[derive(Copy, Clone, Debug)]
-pub struct Indent {
+pub(crate) struct Indent {
// Width of the block indent, in characters. Must be a multiple of
// Config::tab_spaces.
- pub block_indent: usize,
+ pub(crate) block_indent: usize,
// Alignment in characters.
- pub alignment: usize,
+ pub(crate) alignment: usize,
}
+// INDENT_BUFFER.len() = 81
+const INDENT_BUFFER_LEN: usize = 80;
+const INDENT_BUFFER: &str =
+ "\n ";
+
impl Indent {
- pub fn new(block_indent: usize, alignment: usize) -> Indent {
+ pub(crate) fn new(block_indent: usize, alignment: usize) -> Indent {
Indent {
- block_indent: block_indent,
- alignment: alignment,
+ block_indent,
+ alignment,
}
}
- pub fn from_width(config: &Config, width: usize) -> Indent {
+ pub(crate) fn from_width(config: &Config, width: usize) -> Indent {
if config.hard_tabs() {
let tab_num = width / config.tab_spaces();
let alignment = width % config.tab_spaces();
}
}
- pub fn empty() -> Indent {
+ pub(crate) fn empty() -> Indent {
Indent::new(0, 0)
}
- pub fn block_only(&self) -> Indent {
+ pub(crate) fn block_only(&self) -> Indent {
Indent {
block_indent: self.block_indent,
alignment: 0,
}
}
- pub fn block_indent(mut self, config: &Config) -> Indent {
+ pub(crate) fn block_indent(mut self, config: &Config) -> Indent {
self.block_indent += config.tab_spaces();
self
}
- pub fn block_unindent(mut self, config: &Config) -> Indent {
+ pub(crate) fn block_unindent(mut self, config: &Config) -> Indent {
if self.block_indent < config.tab_spaces() {
Indent::new(self.block_indent, 0)
} else {
}
}
- pub fn width(&self) -> usize {
+ pub(crate) fn width(&self) -> usize {
self.block_indent + self.alignment
}
- pub fn to_string(&self, config: &Config) -> String {
+ pub(crate) fn to_string(&self, config: &Config) -> Cow<'static, str> {
+ self.to_string_inner(config, 1)
+ }
+
+ pub(crate) fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> {
+ self.to_string_inner(config, 0)
+ }
+
+ fn to_string_inner(&self, config: &Config, offset: usize) -> Cow<'static, str> {
let (num_tabs, num_spaces) = if config.hard_tabs() {
(self.block_indent / config.tab_spaces(), self.alignment)
} else {
(0, self.width())
};
let num_chars = num_tabs + num_spaces;
- let mut indent = String::with_capacity(num_chars);
- for _ in 0..num_tabs {
- indent.push('\t')
- }
- for _ in 0..num_spaces {
- indent.push(' ')
+ if num_tabs == 0 && num_chars + offset <= INDENT_BUFFER_LEN {
+ Cow::from(&INDENT_BUFFER[offset..=num_chars])
+ } else {
+ let mut indent = String::with_capacity(num_chars + if offset == 0 { 1 } else { 0 });
+ if offset == 0 {
+ indent.push('\n');
+ }
+ for _ in 0..num_tabs {
+ indent.push('\t')
+ }
+ for _ in 0..num_spaces {
+ indent.push(' ')
+ }
+ Cow::from(indent)
}
- indent
}
}
}
#[derive(Copy, Clone, Debug)]
-pub struct Shape {
- pub width: usize,
+pub(crate) struct Shape {
+ pub(crate) width: usize,
// The current indentation of code.
- pub indent: Indent,
+ pub(crate) indent: Indent,
// Indentation + any already emitted text on the first line of the current
// statement.
- pub offset: usize,
+ pub(crate) offset: usize,
}
impl Shape {
// |<------------>| max width
// |<---->| indent
// |<--->| width
- pub fn legacy(width: usize, indent: Indent) -> Shape {
+ pub(crate) fn legacy(width: usize, indent: Indent) -> Shape {
Shape {
- width: width,
- indent: indent,
+ width,
+ indent,
offset: indent.alignment,
}
}
- pub fn indented(indent: Indent, config: &Config) -> Shape {
+ pub(crate) fn indented(indent: Indent, config: &Config) -> Shape {
Shape {
- width: config.max_width().checked_sub(indent.width()).unwrap_or(0),
- indent: indent,
+ width: config.max_width().saturating_sub(indent.width()),
+ indent,
offset: indent.alignment,
}
}
- pub fn with_max_width(&self, config: &Config) -> Shape {
+ pub(crate) fn with_max_width(&self, config: &Config) -> Shape {
Shape {
- width: config
- .max_width()
- .checked_sub(self.indent.width())
- .unwrap_or(0),
+ width: config.max_width().saturating_sub(self.indent.width()),
..*self
}
}
- pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape {
- Shape {
- width: width,
- indent: indent,
- offset: offset,
- }
- }
-
- pub fn visual_indent(&self, extra_width: usize) -> Shape {
+ pub(crate) fn visual_indent(&self, extra_width: usize) -> Shape {
let alignment = self.offset + extra_width;
Shape {
width: self.width,
}
}
- pub fn block_indent(&self, extra_width: usize) -> Shape {
+ pub(crate) fn block_indent(&self, extra_width: usize) -> Shape {
if self.indent.alignment == 0 {
Shape {
width: self.width,
}
}
- pub fn block_left(&self, width: usize) -> Option<Shape> {
+ pub(crate) fn block_left(&self, width: usize) -> Option<Shape> {
self.block_indent(width).sub_width(width)
}
- pub fn add_offset(&self, extra_width: usize) -> Shape {
+ pub(crate) fn add_offset(&self, extra_width: usize) -> Shape {
Shape {
offset: self.offset + extra_width,
..*self
}
}
- pub fn block(&self) -> Shape {
+ pub(crate) fn block(&self) -> Shape {
Shape {
indent: self.indent.block_only(),
..*self
}
}
- pub fn sub_width(&self, width: usize) -> Option<Shape> {
+ pub(crate) fn saturating_sub_width(&self, width: usize) -> Shape {
+ self.sub_width(width).unwrap_or(Shape { width: 0, ..*self })
+ }
+
+ pub(crate) fn sub_width(&self, width: usize) -> Option<Shape> {
Some(Shape {
width: self.width.checked_sub(width)?,
..*self
})
}
- pub fn shrink_left(&self, width: usize) -> Option<Shape> {
+ pub(crate) fn shrink_left(&self, width: usize) -> Option<Shape> {
Some(Shape {
width: self.width.checked_sub(width)?,
indent: self.indent + width,
})
}
- pub fn offset_left(&self, width: usize) -> Option<Shape> {
+ pub(crate) fn offset_left(&self, width: usize) -> Option<Shape> {
self.add_offset(width).sub_width(width)
}
- pub fn used_width(&self) -> usize {
+ pub(crate) fn used_width(&self) -> usize {
self.indent.block_indent + self.offset
}
- pub fn rhs_overhead(&self, config: &Config) -> usize {
+ pub(crate) fn rhs_overhead(&self, config: &Config) -> usize {
config
.max_width()
- .checked_sub(self.used_width() + self.width)
- .unwrap_or(0)
+ .saturating_sub(self.used_width() + self.width)
+ }
+
+ pub(crate) fn comment(&self, config: &Config) -> Shape {
+ let width = min(
+ self.width,
+ config.comment_width().saturating_sub(self.indent.width()),
+ );
+ Shape { width, ..*self }
+ }
+
+ pub(crate) fn to_string_with_newline(&self, config: &Config) -> Cow<'static, str> {
+ let mut offset_indent = self.indent;
+ offset_indent.alignment = self.offset;
+ offset_indent.to_string_inner(config, 0)
}
}