<commit_before>export fold;
export fold_crate, fold_mod, fold_fn;
export default_seq_fold;
export default_seq_fold_crate;
export default_seq_fold_item;
export default_seq_fold_mod;
export default_seq_fold_nmod;
export default_seq_fold_fn;
export default_seq_fold_const;
export default_seq_fold_enum;
export default_seq_fold_res;
export default_seq_fold_iface;
export default_seq_fold_impl;
export default_seq_fold_type;
export default_par_fold;
export default_par_fold_mod;
export default_any_fold;
export default_any_fold_mod;

enum fold<T> = t<T>;

type fold_crate<T> = fn~(fold: fold<T>, doc: doc::cratedoc) -> doc::cratedoc;
type fold_item<T> = fn~(fold: fold<T>, doc: doc::itemdoc) -> doc::itemdoc;
type fold_mod<T> = fn~(fold: fold<T>, doc: doc::moddoc) -> doc::moddoc;
type fold_nmod<T> = fn~(fold: fold<T>, doc: doc::nmoddoc) -> doc::nmoddoc;
type fold_fn<T> = fn~(fold: fold<T>, doc: doc::fndoc) -> doc::fndoc;
type fold_const<T> = fn~(fold: fold<T>, doc: doc::constdoc) -> doc::constdoc;
type fold_enum<T> = fn~(fold: fold<T>, doc: doc::enumdoc) -> doc::enumdoc;
type fold_res<T> = fn~(fold: fold<T>, doc: doc::resdoc) -> doc::resdoc;
type fold_iface<T> = fn~(fold: fold<T>, doc: doc::ifacedoc) -> doc::ifacedoc;
type fold_impl<T> = fn~(fold: fold<T>, doc: doc::impldoc) -> doc::impldoc;
type fold_type<T> = fn~(fold: fold<T>, doc: doc::tydoc) -> doc::tydoc;

type t<T> = {
    ctxt: T,
    fold_crate: fold_crate<T>,
    fold_item: fold_item<T>,
    fold_mod: fold_mod<T>,
    fold_nmod: fold_nmod<T>,
    fold_fn: fold_fn<T>,
    fold_const: fold_const<T>,
    fold_enum: fold_enum<T>,
    fold_res: fold_res<T>,
    fold_iface: fold_iface<T>,
    fold_impl: fold_impl<T>,
    fold_type: fold_type<T>
};

// This exists because fn types don't infer correctly as record
// initializers, but they do as function arguments
fn mk_fold<T:copy>(
    ctxt: T,
    fold_crate: fold_crate<T>,
    fold_item: fold_item<T>,
    fold_mod: fold_mod<T>,
    fold_nmod: fold_nmod<T>,
    fold_fn: fold_fn<T>,
    fold_const: fold_const<T>,
    fold_enum: fold_enum<T>,
    fold_res: fold_res<T>,
    fold_iface: fold_iface<T>,
    fold_impl: fold_impl<T>,
    fold_type: fold_type<T>
) -> fold<T> {
    fold({
        ctxt: ctxt,
        fold_crate: fold_crate,
        fold_item: fold_item,
        fold_mod: fold_mod,
        fold_nmod: fold_nmod,
        fold_fn: fold_fn,
        fold_const: fold_const,
        fold_enum: fold_enum,
        fold_res: fold_res,
        fold_iface: fold_iface,
        fold_impl: fold_impl,
        fold_type: fold_type
    })
}

fn default_any_fold<T:send>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_any_fold_mod(f, d)},
        {|f, d| default_seq_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_seq_fold<T:copy>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_seq_fold_mod(f, d)},
        {|f, d| default_seq_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_par_fold<T:send>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_par_fold_mod(f, d)},
        {|f, d| default_seq_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_seq_fold_crate<T>(
    fold: fold<T>,
    doc: doc::cratedoc
) -> doc::cratedoc {
    {
        topmod: fold.fold_mod(fold, doc.topmod)
    }
}

fn default_seq_fold_item<T>(
    _fold: fold<T>,
    doc: doc::itemdoc
) -> doc::itemdoc {
    doc
}

fn default_any_fold_mod<T:send>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::anymap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_seq_fold_mod<T>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::seqmap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_par_fold_mod<T:send>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::parmap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_seq_fold_nmod<T>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: vec::map(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn fold_itemtag<T>(fold: fold<T>, doc: doc::itemtag) -> doc::itemtag {
    alt doc {
      doc::modtag(moddoc) {
        doc::modtag(fold.fold_mod(fold, moddoc))
      }
      doc::nmodtag(nmoddoc) {
        doc::nmodtag(fold.fold_nmod(fold, nmoddoc))
      }
      doc::fntag(fndoc) {
        doc::fntag(fold.fold_fn(fold, fndoc))
      }
      doc::consttag(constdoc) {
        doc::consttag(fold.fold_const(fold, constdoc))
      }
      doc::enumtag(enumdoc) {
        doc::enumtag(fold.fold_enum(fold, enumdoc))
      }
      doc::restag(resdoc) {
        doc::restag(fold.fold_res(fold, resdoc))
      }
      doc::ifacetag(ifacedoc) {
        doc::ifacetag(fold.fold_iface(fold, ifacedoc))
      }
      doc::impltag(impldoc) {
        doc::impltag(fold.fold_impl(fold, impldoc))
      }
      doc::tytag(tydoc) {
        doc::tytag(fold.fold_type(fold, tydoc))
      }
    }
}

fn default_seq_fold_fn<T>(
    fold: fold<T>,
    doc: doc::fndoc
) -> doc::fndoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_const<T>(
    fold: fold<T>,
    doc: doc::constdoc
) -> doc::constdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_enum<T>(
    fold: fold<T>,
    doc: doc::enumdoc
) -> doc::enumdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_res<T>(
    fold: fold<T>,
    doc: doc::resdoc
) -> doc::resdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_iface<T>(
    fold: fold<T>,
    doc: doc::ifacedoc
) -> doc::ifacedoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_impl<T>(
    fold: fold<T>,
    doc: doc::impldoc
) -> doc::impldoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_type<T>(
    fold: fold<T>,
    doc: doc::tydoc
) -> doc::tydoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

#[test]
fn default_fold_should_produce_same_doc() {
    let source = "mod a { fn b() { } mod c { fn d() { } } }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_fold_should_produce_same_consts() {
    let source = "const a: int = 0;";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_fold_should_produce_same_enums() {
    let source = "enum a { b }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_parallel_fold_should_produce_same_doc() {
    let source = "mod a { fn b() { } mod c { fn d() { } } }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_par_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}
<commit_msg>rustdoc: Add parallel folds for native mods<commit_after>export fold;
export fold_crate, fold_mod, fold_fn;
export default_seq_fold;
export default_seq_fold_crate;
export default_seq_fold_item;
export default_seq_fold_mod;
export default_seq_fold_nmod;
export default_seq_fold_fn;
export default_seq_fold_const;
export default_seq_fold_enum;
export default_seq_fold_res;
export default_seq_fold_iface;
export default_seq_fold_impl;
export default_seq_fold_type;
export default_par_fold;
export default_par_fold_mod;
export default_par_fold_nmod;
export default_any_fold;
export default_any_fold_mod;
export default_any_fold_nmod;

enum fold<T> = t<T>;

type fold_crate<T> = fn~(fold: fold<T>, doc: doc::cratedoc) -> doc::cratedoc;
type fold_item<T> = fn~(fold: fold<T>, doc: doc::itemdoc) -> doc::itemdoc;
type fold_mod<T> = fn~(fold: fold<T>, doc: doc::moddoc) -> doc::moddoc;
type fold_nmod<T> = fn~(fold: fold<T>, doc: doc::nmoddoc) -> doc::nmoddoc;
type fold_fn<T> = fn~(fold: fold<T>, doc: doc::fndoc) -> doc::fndoc;
type fold_const<T> = fn~(fold: fold<T>, doc: doc::constdoc) -> doc::constdoc;
type fold_enum<T> = fn~(fold: fold<T>, doc: doc::enumdoc) -> doc::enumdoc;
type fold_res<T> = fn~(fold: fold<T>, doc: doc::resdoc) -> doc::resdoc;
type fold_iface<T> = fn~(fold: fold<T>, doc: doc::ifacedoc) -> doc::ifacedoc;
type fold_impl<T> = fn~(fold: fold<T>, doc: doc::impldoc) -> doc::impldoc;
type fold_type<T> = fn~(fold: fold<T>, doc: doc::tydoc) -> doc::tydoc;

type t<T> = {
    ctxt: T,
    fold_crate: fold_crate<T>,
    fold_item: fold_item<T>,
    fold_mod: fold_mod<T>,
    fold_nmod: fold_nmod<T>,
    fold_fn: fold_fn<T>,
    fold_const: fold_const<T>,
    fold_enum: fold_enum<T>,
    fold_res: fold_res<T>,
    fold_iface: fold_iface<T>,
    fold_impl: fold_impl<T>,
    fold_type: fold_type<T>
};

// This exists because fn types don't infer correctly as record
// initializers, but they do as function arguments
fn mk_fold<T:copy>(
    ctxt: T,
    fold_crate: fold_crate<T>,
    fold_item: fold_item<T>,
    fold_mod: fold_mod<T>,
    fold_nmod: fold_nmod<T>,
    fold_fn: fold_fn<T>,
    fold_const: fold_const<T>,
    fold_enum: fold_enum<T>,
    fold_res: fold_res<T>,
    fold_iface: fold_iface<T>,
    fold_impl: fold_impl<T>,
    fold_type: fold_type<T>
) -> fold<T> {
    fold({
        ctxt: ctxt,
        fold_crate: fold_crate,
        fold_item: fold_item,
        fold_mod: fold_mod,
        fold_nmod: fold_nmod,
        fold_fn: fold_fn,
        fold_const: fold_const,
        fold_enum: fold_enum,
        fold_res: fold_res,
        fold_iface: fold_iface,
        fold_impl: fold_impl,
        fold_type: fold_type
    })
}

fn default_any_fold<T:send>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_any_fold_mod(f, d)},
        {|f, d| default_any_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_seq_fold<T:copy>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_seq_fold_mod(f, d)},
        {|f, d| default_seq_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_par_fold<T:send>(ctxt: T) -> fold<T> {
    mk_fold(
        ctxt,
        {|f, d| default_seq_fold_crate(f, d)},
        {|f, d| default_seq_fold_item(f, d)},
        {|f, d| default_par_fold_mod(f, d)},
        {|f, d| default_par_fold_nmod(f, d)},
        {|f, d| default_seq_fold_fn(f, d)},
        {|f, d| default_seq_fold_const(f, d)},
        {|f, d| default_seq_fold_enum(f, d)},
        {|f, d| default_seq_fold_res(f, d)},
        {|f, d| default_seq_fold_iface(f, d)},
        {|f, d| default_seq_fold_impl(f, d)},
        {|f, d| default_seq_fold_type(f, d)}
    )
}

fn default_seq_fold_crate<T>(
    fold: fold<T>,
    doc: doc::cratedoc
) -> doc::cratedoc {
    {
        topmod: fold.fold_mod(fold, doc.topmod)
    }
}

fn default_seq_fold_item<T>(
    _fold: fold<T>,
    doc: doc::itemdoc
) -> doc::itemdoc {
    doc
}

fn default_any_fold_mod<T:send>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::anymap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_seq_fold_mod<T>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::seqmap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_par_fold_mod<T:send>(
    fold: fold<T>,
    doc: doc::moddoc
) -> doc::moddoc {
    {
        item: fold.fold_item(fold, doc.item),
        items: util::parmap(doc.items) {|itemtag|
            fold_itemtag(fold, itemtag)
        }
        with doc
    }
}

fn default_any_fold_nmod<T:send>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::anymap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn default_seq_fold_nmod<T>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::seqmap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn default_par_fold_nmod<T:send>(
    fold: fold<T>,
    doc: doc::nmoddoc
) -> doc::nmoddoc {
    {
        item: fold.fold_item(fold, doc.item),
        fns: util::parmap(doc.fns) {|fndoc|
            fold.fold_fn(fold, fndoc)
        }
        with doc
    }
}

fn fold_itemtag<T>(fold: fold<T>, doc: doc::itemtag) -> doc::itemtag {
    alt doc {
      doc::modtag(moddoc) {
        doc::modtag(fold.fold_mod(fold, moddoc))
      }
      doc::nmodtag(nmoddoc) {
        doc::nmodtag(fold.fold_nmod(fold, nmoddoc))
      }
      doc::fntag(fndoc) {
        doc::fntag(fold.fold_fn(fold, fndoc))
      }
      doc::consttag(constdoc) {
        doc::consttag(fold.fold_const(fold, constdoc))
      }
      doc::enumtag(enumdoc) {
        doc::enumtag(fold.fold_enum(fold, enumdoc))
      }
      doc::restag(resdoc) {
        doc::restag(fold.fold_res(fold, resdoc))
      }
      doc::ifacetag(ifacedoc) {
        doc::ifacetag(fold.fold_iface(fold, ifacedoc))
      }
      doc::impltag(impldoc) {
        doc::impltag(fold.fold_impl(fold, impldoc))
      }
      doc::tytag(tydoc) {
        doc::tytag(fold.fold_type(fold, tydoc))
      }
    }
}

fn default_seq_fold_fn<T>(
    fold: fold<T>,
    doc: doc::fndoc
) -> doc::fndoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_const<T>(
    fold: fold<T>,
    doc: doc::constdoc
) -> doc::constdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_enum<T>(
    fold: fold<T>,
    doc: doc::enumdoc
) -> doc::enumdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_res<T>(
    fold: fold<T>,
    doc: doc::resdoc
) -> doc::resdoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_iface<T>(
    fold: fold<T>,
    doc: doc::ifacedoc
) -> doc::ifacedoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_impl<T>(
    fold: fold<T>,
    doc: doc::impldoc
) -> doc::impldoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

fn default_seq_fold_type<T>(
    fold: fold<T>,
    doc: doc::tydoc
) -> doc::tydoc {
    {
        item: fold.fold_item(fold, doc.item)
        with doc
    }
}

#[test]
fn default_fold_should_produce_same_doc() {
    let source = "mod a { fn b() { } mod c { fn d() { } } }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_fold_should_produce_same_consts() {
    let source = "const a: int = 0;";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_fold_should_produce_same_enums() {
    let source = "enum a { b }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_seq_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}

#[test]
fn default_parallel_fold_should_produce_same_doc() {
    let source = "mod a { fn b() { } mod c { fn d() { } } }";
    let ast = parse::from_str(source);
    let doc = extract::extract(ast, "");
    let fld = default_par_fold(());
    let folded = fld.fold_crate(fld, doc);
    assert doc == folded;
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

use error::{Error, Result};

use std::borrow::Cow;

/// Escape some special characters that would cause trouble
pub fn escape_string<'a>(s: &'a str) -> Cow<'a, str> {
    if s.contains('\n') {
        let res = s.replace('\n', r"\n");
        Cow::Owned(res)
    } else {
        Cow::Borrowed(s)
    }
}

/// Find the next string, delimited by quotes `"` (which are not returned),
/// and not stopping at escape quotes `\"`
pub fn find_string(bytes: &[u8]) -> Result<String> {
    let mut begin = None;
    let mut i = 0;
    while i < bytes.len() {
        match bytes[i] {
            b'"' => if begin.is_some() {
                if bytes[i-1] != b'\\' {
                    break
                }
            } else {
                if i + 1 >= bytes.len() {
                    return Err(Error::new(""));
                }
                begin = Some(i + 1);
            },
            _ => (),
        }
        i += 1;
    }
    let begin = if let Some(begin) = begin {
        begin
    } else {
        return Err(Error::new(""));
    };
    Ok(String::from_utf8(bytes[begin..i].to_vec()).unwrap())
}

#[test]
fn find_string_1() {
    let s = r#"
"Test"
"#;
    let expected = "Test";
    assert_eq!(&find_string(s.as_bytes()).unwrap(), expected);
}

#[test]
fn find_string_2() {
    let s = r#"
"A \"test\"..."
"#;
    let expected = r#"A \"test\"..."#;
    assert_eq!(&find_string(s.as_bytes()).unwrap(), expected);
}

#[test]
fn escape_string_1() {
    let s = r#"foo
bar"#;
    let expected = "foo\\nbar";
    assert_eq!(&escape_string(s), expected);
}
<commit_msg>Escape '\' followed by a newline<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

use error::{Error, Result};

use std::borrow::Cow;

use regex::Regex;

/// Escape some special characters that would cause trouble
///
/// The newline character
/// '\' followed by a newline
pub fn escape_string<'a>(s: &'a str) -> Cow<'a, str> {
    lazy_static! {
        static ref REGEX:Regex = Regex::new(r#"\\\n\s*"#).unwrap();
    }

    if s.contains('\n') || REGEX.is_match(s) {
        let mut res = REGEX.replace_all(s, "");
        res = res.replace('\n', r"\n");
        Cow::Owned(res)
    } else {
        Cow::Borrowed(s)
    }
}

/// Find the next string, delimited by quotes `"` (which are not returned),
/// and not stopping at escape quotes `\"`
pub fn find_string(bytes: &[u8]) -> Result<String> {
    let mut begin = None;
    let mut i = 0;
    while i < bytes.len() {
        match bytes[i] {
            b'"' => if begin.is_some() {
                if bytes[i-1] != b'\\' {
                    break
                }
            } else {
                if i + 1 >= bytes.len() {
                    return Err(Error::new(""));
                }
                begin = Some(i + 1);
            },
            _ => (),
        }
        i += 1;
    }
    let begin = if let Some(begin) = begin {
        begin
    } else {
        return Err(Error::new(""));
    };
    Ok(String::from_utf8(bytes[begin..i].to_vec()).unwrap())
}

#[test]
fn find_string_1() {
    let s = r#"
"Test"
"#;
    let expected = "Test";
    assert_eq!(&find_string(s.as_bytes()).unwrap(), expected);
}

#[test]
fn find_string_2() {
    let s = r#"
"A \"test\"..."
"#;
    let expected = r#"A \"test\"..."#;
    assert_eq!(&find_string(s.as_bytes()).unwrap(), expected);
}

#[test]
fn escape_string_1() {
    let s = r#"foo
bar"#;
    let expected = "foo\\nbar";
    assert_eq!(&escape_string(s), expected);
}

#[test]
fn escape_string_2() {
    let s = "foo\
             bar";
    let expected = "foobar";
    assert_eq!(&escape_string(s), expected);
}

#[test]
fn escape_string_3() {
    let s = r#"foo\
             bar"#;
    let expected = "foobar";
    assert_eq!(&escape_string(s), expected);
}

#[test]
fn escape_string_4() {
    let s = r#"foo\
             bar
baz"#;
    let expected = "foobar\\nbaz";
    assert_eq!(&escape_string(s), expected);
}
<|endoftext|>


<commit_before>use std::ops::{Index, IndexMut};
use std::iter::{Iterator, repeat};

use graph::{Edge, Graph};

pub struct AdjacencyMatrix {
    rows: Vec<Vec<u32>>,
}

impl AdjacencyMatrix {
    fn new(size: usize) -> AdjacencyMatrix {
        let row = vec![0; size];
        let rows = repeat(row).take(size).collect();

        AdjacencyMatrix { rows: rows }
    }

    pub fn from_graph(g: &Graph) -> AdjacencyMatrix {
        let mut matrix = AdjacencyMatrix::new(g.vertex_count);

        for &Edge { x, y } in &g.edges {
            matrix[x][y] = 1;
            if !g.directed {
                matrix[y][x] = 1;
            }
        }

        matrix
    }

    pub fn size(&self) -> usize {
        self.rows.len()
    }
}

// For convenience, enable writing matrix[x] instead of matrix.rows[x].

impl Index<usize> for AdjacencyMatrix {
    type Output = Vec<u32>;

    fn index<'a>(&'a self, _index: usize) -> &'a Vec<u32> {
        &self.rows[_index]
    }
}

impl IndexMut<usize> for AdjacencyMatrix {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Vec<u32> {
        &mut self.rows[_index]
    }
}

// Breadth-first search.

struct BreadthFirstSearch<'a> {
    matrix: &'a AdjacencyMatrix,
    visited: Vec<bool>,
    queue: Vec<usize>,
    y: usize,
}

impl AdjacencyMatrix {
    pub fn breadth_first_search(&self, start: usize) -> BreadthFirstSearch {
        let mut visited = vec!(false; self.size());
        visited[start] = true;

        BreadthFirstSearch {
            matrix: self,
            visited: visited,
            queue: vec![start],
            y: 0
        }
    }
}

impl<'a> Iterator for BreadthFirstSearch<'a> {
    type Item = Edge;

    fn next(&mut self) -> Option<Edge> {
        while !self.queue.is_empty() {
            let x = self.queue[0];

            for y in self.y..self.matrix.size() {
                if self.visited[y] || self.matrix[x][y] == 0 {
                    continue;
                }
                self.visited[y] = true;
                self.queue.push(y);
                self.y = y + 1;
                return Some(Edge { x: x, y: y });
            }

            // Process the next element in the queue.
            self.queue.remove(0);
            self.y = 0;
        }

        None
    }
}

// Breadth-first search using std::iter::Unfold. In this situation there's no reason to use it over
// implementing Iterator directly. Unfold seems to shine in situations where we can just pass it a
// closure, but here we cannot use a closure because we need to return an iterator (see
// http://is.gd/2MDM1r).

// struct BFS<'a> {
//     matrix: &'a AdjacencyMatrix,
//     visited: Vec<bool>,
//     queue: Vec<usize>,
//     y: usize,
// }

// impl AdjacencyMatrix {
//     pub fn breadth_first_search(&self, start: usize) ->
//         Unfold<BFS, fn(&mut BFS) -> Option<Edge>> {

//         let mut visited = vec!(false; self.size());
//         visited[start] = true;

//         let state = BFS {
//             matrix: self,
//             visited: visited,
//             queue: vec![start],
//             y: 0
//         };

//         Unfold::new(state, unfold_breadth_first_search)
//     }
// }

// fn unfold_breadth_first_search(state: &mut BFS) -> Option<Edge> {
//     while !state.queue.is_empty() {
//         let x = state.queue[0];

//         for y in state.y..state.matrix.size() {
//             if state.visited[y] || state.matrix[x][y] == 0 {
//                 continue;
//             }

//             state.visited[y] = true;
//             state.queue.push(y);
//             state.y = y + 1;

//             return Some(Edge { x: x, y: y });
//         }

//         // Process the next element in the queue.
//         state.queue.remove(0);
//         state.y = 0;
//     }

//     None
// }

// Breadth-first search using a callback closure. The implementation is much simpler than the
// iterator-based BFS, however the external API is not as nice (forced to use a callback closure
// instead of a classic for loop).

// impl AdjacencyMatrix {
//     pub fn breadth_first_search<C>(&self, start: usize, mut callback: C)
//        where C: FnMut(Edge) -> bool {

//         let mut visited = vec!(false; self.size());
//         visited[start] = true;

//         let mut queue = vec![start];

//         while queue.len() > 0 {
//             // Dequeue first element.
//             let x = queue.remove(0);

//             for y in 0..self.size() {
//                 if visited[y] || self[x][y] == 0 {
//                     continue;
//                 }
//                 visited[y] = true;
//                 queue.push(y);
//                 // The edge callback can return true to abort the current graph traversal.
//                 if callback(Edge { x: x, y: y }) {
//                     return;
//                 }
//             }
//         }
//     }
// }
<commit_msg>[edge_connectivity/rust] Return Self in impl functions<commit_after>use std::ops::{Index, IndexMut};
use std::iter::{Iterator, repeat};

use graph::{Edge, Graph};

pub struct AdjacencyMatrix {
    rows: Vec<Vec<u32>>,
}

impl AdjacencyMatrix {
    fn new(size: usize) -> Self {
        let row = vec![0; size];
        let rows = repeat(row).take(size).collect();

        AdjacencyMatrix { rows: rows }
    }

    pub fn from_graph(g: &Graph) -> Self {
        let mut matrix = AdjacencyMatrix::new(g.vertex_count);

        for &Edge { x, y } in &g.edges {
            matrix[x][y] = 1;
            if !g.directed {
                matrix[y][x] = 1;
            }
        }

        matrix
    }

    pub fn size(&self) -> usize {
        self.rows.len()
    }
}

// For convenience, enable writing matrix[x] instead of matrix.rows[x].

impl Index<usize> for AdjacencyMatrix {
    type Output = Vec<u32>;

    fn index<'a>(&'a self, _index: usize) -> &'a Vec<u32> {
        &self.rows[_index]
    }
}

impl IndexMut<usize> for AdjacencyMatrix {
    fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Vec<u32> {
        &mut self.rows[_index]
    }
}

// Breadth-first search.

struct BreadthFirstSearch<'a> {
    matrix: &'a AdjacencyMatrix,
    visited: Vec<bool>,
    queue: Vec<usize>,
    y: usize,
}

impl AdjacencyMatrix {
    pub fn breadth_first_search(&self, start: usize) -> BreadthFirstSearch {
        let mut visited = vec!(false; self.size());
        visited[start] = true;

        BreadthFirstSearch {
            matrix: self,
            visited: visited,
            queue: vec![start],
            y: 0
        }
    }
}

impl<'a> Iterator for BreadthFirstSearch<'a> {
    type Item = Edge;

    fn next(&mut self) -> Option<Edge> {
        while !self.queue.is_empty() {
            let x = self.queue[0];

            for y in self.y..self.matrix.size() {
                if self.visited[y] || self.matrix[x][y] == 0 {
                    continue;
                }
                self.visited[y] = true;
                self.queue.push(y);
                self.y = y + 1;
                return Some(Edge { x: x, y: y });
            }

            // Process the next element in the queue.
            self.queue.remove(0);
            self.y = 0;
        }

        None
    }
}

// Breadth-first search using std::iter::Unfold. In this situation there's no reason to use it over
// implementing Iterator directly. Unfold seems to shine in situations where we can just pass it a
// closure, but here we cannot use a closure because we need to return an iterator (see
// http://is.gd/2MDM1r).

// struct BFS<'a> {
//     matrix: &'a AdjacencyMatrix,
//     visited: Vec<bool>,
//     queue: Vec<usize>,
//     y: usize,
// }

// impl AdjacencyMatrix {
//     pub fn breadth_first_search(&self, start: usize) ->
//         Unfold<BFS, fn(&mut BFS) -> Option<Edge>> {

//         let mut visited = vec!(false; self.size());
//         visited[start] = true;

//         let state = BFS {
//             matrix: self,
//             visited: visited,
//             queue: vec![start],
//             y: 0
//         };

//         Unfold::new(state, unfold_breadth_first_search)
//     }
// }

// fn unfold_breadth_first_search(state: &mut BFS) -> Option<Edge> {
//     while !state.queue.is_empty() {
//         let x = state.queue[0];

//         for y in state.y..state.matrix.size() {
//             if state.visited[y] || state.matrix[x][y] == 0 {
//                 continue;
//             }

//             state.visited[y] = true;
//             state.queue.push(y);
//             state.y = y + 1;

//             return Some(Edge { x: x, y: y });
//         }

//         // Process the next element in the queue.
//         state.queue.remove(0);
//         state.y = 0;
//     }

//     None
// }

// Breadth-first search using a callback closure. The implementation is much simpler than the
// iterator-based BFS, however the external API is not as nice (forced to use a callback closure
// instead of a classic for loop).

// impl AdjacencyMatrix {
//     pub fn breadth_first_search<C>(&self, start: usize, mut callback: C)
//        where C: FnMut(Edge) -> bool {

//         let mut visited = vec!(false; self.size());
//         visited[start] = true;

//         let mut queue = vec![start];

//         while queue.len() > 0 {
//             // Dequeue first element.
//             let x = queue.remove(0);

//             for y in 0..self.size() {
//                 if visited[y] || self[x][y] == 0 {
//                     continue;
//                 }
//                 visited[y] = true;
//                 queue.push(y);
//                 // The edge callback can return true to abort the current graph traversal.
//                 if callback(Edge { x: x, y: y }) {
//                     return;
//                 }
//             }
//         }
//     }
// }
<|endoftext|>


<commit_before>//!

use super::list_of_types::{ListedTypeIndex, Sublist};
use std::ptr::{self, Shared};
use std::sync::atomic::AtomicUsize;
use std::any::Any;
use std::mem;

struct ArcInnerCommon <List: Sublist, CommonData: Any> {
  index: ListedTypeIndex <List>,
  references: AtomicUsize,
  data: CommonData,
}
#[repr(C)]
struct ArcInner <List: Sublist, CommonData: Any, DifferentiatedData: Any> {
  common: ArcInnerAlways <List, CommonData>,
  differentiated: DifferentiatedData,
}
pub struct DynamicArc <List: Sublist, CommonData: Any> {
  pointer: Shared <ArcInnerCommon <List, CommonData>>,
}
pub struct TypedArc <List: Sublist, CommonData: Any, DifferentiatedData: Any> {
  pointer: Shared <ArcInner <List, CommonData, DifferentiatedData>>,
}

impl <List: Sublist, CommonData: Any, DifferentiatedData: Any> TypedArc <List, CommonData, DifferentiatedData> {
  fn erase_type (self)->DynamicArc <List, CommonData> {
    DynamicArc {pointer: unsafe {mem::transmute (self.pointer)}}
  }
}
impl <List: Sublist, CommonData: Any> DynamicArc <List, CommonData> {
  /// If it's not the correct type, return the original DynamicArc
  fn downcast <DifferentiatedData: Any> (self)->Result <TypedArc <List, CommonData, DifferentiatedData>, DynamicArc <List, CommonData>> {
    if unsafe {self.pointer.as_ref().index} == List::index:: <DifferentiatedData> () {
      Ok (TypedArc {pointer: unsafe {mem::transmute (self.pointer)}})
    }
    else {
      Err (self)
    }
  }
}
<commit_msg>Implemented accessor functions<commit_after>//!

use super::list_of_types::{ListedTypeIndex, Sublist};
use std::ptr::{self, Shared};
use std::sync::atomic::AtomicUsize;
use std::any::Any;
use std::mem;

struct ArcInnerCommon <List: Sublist, CommonData: Any> {
  index: ListedTypeIndex <List>,
  references: AtomicUsize,
  data: CommonData,
}
#[repr(C)]
struct ArcInner <List: Sublist, CommonData: Any, DifferentiatedData: Any> {
  common: ArcInnerCommon <List, CommonData>,
  differentiated: DifferentiatedData,
}
pub struct DynamicArc <List: Sublist, CommonData: Any> {
  pointer: Shared <ArcInnerCommon <List, CommonData>>,
}
pub struct TypedArc <List: Sublist, CommonData: Any, DifferentiatedData: Any> {
  pointer: Shared <ArcInner <List, CommonData, DifferentiatedData>>,
}

impl <List: Sublist, CommonData: Any, DifferentiatedData: Any> TypedArc <List, CommonData, DifferentiatedData> {
  fn erase_type (self)->DynamicArc <List, CommonData> {
    DynamicArc {pointer: unsafe {mem::transmute (self.pointer)}}
  }
  fn common (&self)->& CommonData {
    & unsafe {self.pointer.as_ref()}.common.data
  }
  fn differentiated (&self)->& DifferentiatedData {
    & unsafe {self.pointer.as_ref()}.differentiated
  }
}
impl <List: Sublist, CommonData: Any> DynamicArc <List, CommonData> {
  /// If it's not the correct type, return the original DynamicArc
  fn downcast <DifferentiatedData: Any> (self)->Result <TypedArc <List, CommonData, DifferentiatedData>, DynamicArc <List, CommonData>> {
    if unsafe {self.pointer.as_ref().index} == List::index:: <DifferentiatedData> () {
      Ok (TypedArc {pointer: unsafe {mem::transmute (self.pointer)}})
    }
    else {
      Err (self)
    }
  }
  fn common (&self)->& CommonData {
    & unsafe {self.pointer.as_ref()}.data
  }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::io::{Error as IoError, Read, Write};
use std::path::PathBuf;

use ansi_term::{Color, Style};
use app_dirs::{get_app_root, AppDataType};
use log::debug;
use serde_derive::{Deserialize, Serialize};
use toml;

use crate::error::TealdeerError::{self, ConfigError};

pub const CONFIG_FILE_NAME: &str = "config.toml";

fn default_underline() -> bool {
    false
}

fn default_bold() -> bool {
    false
}

#[serde(rename_all = "lowercase")]
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub enum RawColor {
    Black,
    Red,
    Green,
    Yellow,
    Blue,
    Purple,
    Cyan,
    White,
}

impl From<RawColor> for Color {
    fn from(raw_color: RawColor) -> Self {
        match raw_color {
            RawColor::Black => Color::Black,
            RawColor::Red => Color::Red,
            RawColor::Green => Color::Green,
            RawColor::Yellow => Color::Yellow,
            RawColor::Blue => Color::Blue,
            RawColor::Purple => Color::Purple,
            RawColor::Cyan => Color::Cyan,
            RawColor::White => Color::White,
        }
    }
}

#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
struct RawStyle {
    pub foreground: Option<RawColor>,
    pub background: Option<RawColor>,
    #[serde(default = "default_underline")]
    pub underline: bool,
    #[serde(default = "default_bold")]
    pub bold: bool,
}

impl Default for RawStyle {
    fn default() -> Self {
        Self {
            foreground: None,
            background: None,
            underline: false,
            bold: false,
        }
    }
} // impl RawStyle

impl From<RawStyle> for Style {
    fn from(raw_style: RawStyle) -> Self {
        let mut style = Self::default();

        if let Some(foreground) = raw_style.foreground {
            style = style.fg(Color::from(foreground));
        }

        if let Some(background) = raw_style.background {
            style = style.on(Color::from(background));
        }

        if raw_style.underline {
            style = style.underline();
        }

        if raw_style.bold {
            style = style.bold();
        }

        style
    }
}

#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct RawStyleConfig {
    #[serde(default)]
    pub description: RawStyle,
    #[serde(default)]
    pub command_name: RawStyle,
    #[serde(default)]
    pub example_text: RawStyle,
    #[serde(default)]
    pub example_code: RawStyle,
    #[serde(default)]
    pub example_variable: RawStyle,
}

#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct RawDisplayConfig {
    #[serde(default)]
    pub use_pager: bool,
}

#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct RawConfig {
    #[serde(default)]
    style: RawStyleConfig,
    #[serde(default)]
    display: RawDisplayConfig,
}

impl RawConfig {
    fn new() -> Self {
        let mut raw_config = Self::default();

        // Set default config
        raw_config.style.example_text.foreground = Some(RawColor::Green);
        raw_config.style.command_name.foreground = Some(RawColor::Cyan);
        raw_config.style.example_code.foreground = Some(RawColor::Cyan);
        raw_config.style.example_variable.foreground = Some(RawColor::Cyan);
        raw_config.style.example_variable.underline = true;
        raw_config.display.use_pager = false;

        raw_config
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct StyleConfig {
    pub description: Style,
    pub command_name: Style,
    pub example_text: Style,
    pub example_code: Style,
    pub example_variable: Style,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct DisplayConfig {
    pub use_pager: bool,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Config {
    pub style: StyleConfig,
    pub display: DisplayConfig,
}

impl From<RawConfig> for Config {
    fn from(raw_config: RawConfig) -> Self {
        Self {
            style: StyleConfig {
                command_name: raw_config.style.command_name.into(),
                description: raw_config.style.description.into(),
                example_text: raw_config.style.example_text.into(),
                example_code: raw_config.style.example_code.into(),
                example_variable: raw_config.style.example_variable.into(),
            },
            display: DisplayConfig {
                use_pager: false,
            },
        }
    }
}

#[allow(clippy::needless_pass_by_value)]
fn map_io_err_to_config_err(e: IoError) -> TealdeerError {
    ConfigError(format!("Io Error: {}", e))
}

impl Config {
    pub fn load(enable_styles: bool) -> Result<Self, TealdeerError> {
        debug!("Loading config");

        // Determine path
        let config_file_path = get_config_path()
            .map_err(|e| ConfigError(format!("Could not determine config path: {}", e)))?;

        // Load config
        let raw_config: RawConfig = if config_file_path.exists() && config_file_path.is_file() {
            let mut config_file =
                fs::File::open(config_file_path).map_err(map_io_err_to_config_err)?;
            let mut contents = String::new();
            let _ = config_file
                .read_to_string(&mut contents)
                .map_err(map_io_err_to_config_err)?;
            toml::from_str(&contents)
                .map_err(|err| ConfigError(format!("Failed to parse config file: {}", err)))?
        } else {
            RawConfig::new()
        };

        Ok(if enable_styles {
            Self::from(raw_config)
        } else {
            Self {
                style: StyleConfig {
                    command_name: Style::default(),
                    description: Style::default(),
                    example_text: Style::default(),
                    example_code: Style::default(),
                    example_variable: Style::default(),
                },
                display: DisplayConfig {
                    use_pager: false,
                }
            }
        })
    }
} // impl Config

/// Return the path to the config directory.
///
/// The config dir path can be overridden using the `TEALDEER_CONFIG_DIR` env
/// variable. Otherwise, the user config directory is returned.
///
/// Note that this function does not verify whether the directory at that
/// loation exists, or is a directory.
pub fn get_config_dir() -> Result<PathBuf, TealdeerError> {
    // Allow overriding the config directory by setting the
    // $TEALDEER_CONFIG_DIR env variable.
    if let Ok(value) = env::var("TEALDEER_CONFIG_DIR") {
        return Ok(PathBuf::from(value));
    };

    // Otherwise, fall back to the user config directory.
    match get_app_root(AppDataType::UserConfig, &crate::APP_INFO) {
        Ok(dirs) => Ok(dirs),
        Err(_) => Err(ConfigError(
            "Could not determine the user config directory.".into(),
        )),
    }
}

/// Return the path to the config file.
///
/// Note that this function does not verify whether the file at that location
/// exists, or is a file.
pub fn get_config_path() -> Result<PathBuf, TealdeerError> {
    let config_dir = get_config_dir()?;
    let config_file_path = config_dir.join(CONFIG_FILE_NAME);
    Ok(config_file_path)
}

/// Create default config file.
pub fn make_default_config() -> Result<PathBuf, TealdeerError> {
    let config_dir = get_config_dir()?;

    // Ensure that config directory exists
    if !config_dir.exists() {
        if let Err(e) = fs::create_dir_all(&config_dir) {
            return Err(ConfigError(format!(
                "Could not create config directory: {}",
                e
            )));
        }
    } else if !config_dir.is_dir() {
        return Err(ConfigError(format!(
            "Config directory could not be created: {} already exists but is not a directory",
            config_dir.to_string_lossy(),
        )));
    }

    // Ensure that a config file doesn't get overwritten
    let config_file_path = config_dir.join(CONFIG_FILE_NAME);
    if config_file_path.is_file() {
        return Err(ConfigError(format!(
            "A configuration file already exists at {}, no action was taken.",
            config_file_path.to_str().unwrap()
        )));
    }

    // Create default config
    let serialized_config = toml::to_string(&RawConfig::new())
        .map_err(|err| ConfigError(format!("Failed to serialize default config: {}", err)))?;

    // Write default config
    let mut config_file = fs::File::create(&config_file_path).map_err(map_io_err_to_config_err)?;
    let _wc = config_file
        .write(serialized_config.as_bytes())
        .map_err(map_io_err_to_config_err)?;

    Ok(config_file_path)
}

#[test]
fn test_serialize_deserialize() {
    let raw_config = RawConfig::new();
    let serialized = toml::to_string(&raw_config).unwrap();
    let deserialized: RawConfig = toml::from_str(&serialized).unwrap();
    assert_eq!(raw_config, deserialized);
}
<commit_msg>Don't override display config when styles are disabled<commit_after>use std::env;
use std::fs;
use std::io::{Error as IoError, Read, Write};
use std::path::PathBuf;

use ansi_term::{Color, Style};
use app_dirs::{get_app_root, AppDataType};
use log::debug;
use serde_derive::{Deserialize, Serialize};
use toml;

use crate::error::TealdeerError::{self, ConfigError};

pub const CONFIG_FILE_NAME: &str = "config.toml";

fn default_underline() -> bool {
    false
}

fn default_bold() -> bool {
    false
}

#[serde(rename_all = "lowercase")]
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
pub enum RawColor {
    Black,
    Red,
    Green,
    Yellow,
    Blue,
    Purple,
    Cyan,
    White,
}

impl From<RawColor> for Color {
    fn from(raw_color: RawColor) -> Self {
        match raw_color {
            RawColor::Black => Color::Black,
            RawColor::Red => Color::Red,
            RawColor::Green => Color::Green,
            RawColor::Yellow => Color::Yellow,
            RawColor::Blue => Color::Blue,
            RawColor::Purple => Color::Purple,
            RawColor::Cyan => Color::Cyan,
            RawColor::White => Color::White,
        }
    }
}

#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
struct RawStyle {
    pub foreground: Option<RawColor>,
    pub background: Option<RawColor>,
    #[serde(default = "default_underline")]
    pub underline: bool,
    #[serde(default = "default_bold")]
    pub bold: bool,
}

impl Default for RawStyle {
    fn default() -> Self {
        Self {
            foreground: None,
            background: None,
            underline: false,
            bold: false,
        }
    }
} // impl RawStyle

impl From<RawStyle> for Style {
    fn from(raw_style: RawStyle) -> Self {
        let mut style = Self::default();

        if let Some(foreground) = raw_style.foreground {
            style = style.fg(Color::from(foreground));
        }

        if let Some(background) = raw_style.background {
            style = style.on(Color::from(background));
        }

        if raw_style.underline {
            style = style.underline();
        }

        if raw_style.bold {
            style = style.bold();
        }

        style
    }
}

#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct RawStyleConfig {
    #[serde(default)]
    pub description: RawStyle,
    #[serde(default)]
    pub command_name: RawStyle,
    #[serde(default)]
    pub example_text: RawStyle,
    #[serde(default)]
    pub example_code: RawStyle,
    #[serde(default)]
    pub example_variable: RawStyle,
}

#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct RawDisplayConfig {
    #[serde(default)]
    pub use_pager: bool,
}

#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct RawConfig {
    #[serde(default)]
    style: RawStyleConfig,
    #[serde(default)]
    display: RawDisplayConfig,
}

impl RawConfig {
    fn new() -> Self {
        let mut raw_config = Self::default();

        // Set default config
        raw_config.style.example_text.foreground = Some(RawColor::Green);
        raw_config.style.command_name.foreground = Some(RawColor::Cyan);
        raw_config.style.example_code.foreground = Some(RawColor::Cyan);
        raw_config.style.example_variable.foreground = Some(RawColor::Cyan);
        raw_config.style.example_variable.underline = true;
        raw_config.display.use_pager = false;

        raw_config
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct StyleConfig {
    pub description: Style,
    pub command_name: Style,
    pub example_text: Style,
    pub example_code: Style,
    pub example_variable: Style,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct DisplayConfig {
    pub use_pager: bool,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Config {
    pub style: StyleConfig,
    pub display: DisplayConfig,
}

impl From<RawConfig> for Config {
    fn from(raw_config: RawConfig) -> Self {
        Self {
            style: StyleConfig {
                command_name: raw_config.style.command_name.into(),
                description: raw_config.style.description.into(),
                example_text: raw_config.style.example_text.into(),
                example_code: raw_config.style.example_code.into(),
                example_variable: raw_config.style.example_variable.into(),
            },
            display: DisplayConfig {
                use_pager: false,
            },
        }
    }
}

#[allow(clippy::needless_pass_by_value)]
fn map_io_err_to_config_err(e: IoError) -> TealdeerError {
    ConfigError(format!("Io Error: {}", e))
}

impl Config {
    pub fn load(enable_styles: bool) -> Result<Self, TealdeerError> {
        debug!("Loading config");

        // Determine path
        let config_file_path = get_config_path()
            .map_err(|e| ConfigError(format!("Could not determine config path: {}", e)))?;

        // Load raw config
        let raw_config: RawConfig = if config_file_path.exists() && config_file_path.is_file() {
            let mut config_file =
                fs::File::open(config_file_path).map_err(map_io_err_to_config_err)?;
            let mut contents = String::new();
            let _ = config_file
                .read_to_string(&mut contents)
                .map_err(map_io_err_to_config_err)?;
            toml::from_str(&contents)
                .map_err(|err| ConfigError(format!("Failed to parse config file: {}", err)))?
        } else {
            RawConfig::new()
        };

        // Convert to config
        let mut config = Self::from(raw_config);

        // Potentially override styles
        if !enable_styles {
            config.style = StyleConfig {
                command_name: Style::default(),
                description: Style::default(),
                example_text: Style::default(),
                example_code: Style::default(),
                example_variable: Style::default(),
            };
        }

        Ok(config)
    }
}

/// Return the path to the config directory.
///
/// The config dir path can be overridden using the `TEALDEER_CONFIG_DIR` env
/// variable. Otherwise, the user config directory is returned.
///
/// Note that this function does not verify whether the directory at that
/// loation exists, or is a directory.
pub fn get_config_dir() -> Result<PathBuf, TealdeerError> {
    // Allow overriding the config directory by setting the
    // $TEALDEER_CONFIG_DIR env variable.
    if let Ok(value) = env::var("TEALDEER_CONFIG_DIR") {
        return Ok(PathBuf::from(value));
    };

    // Otherwise, fall back to the user config directory.
    match get_app_root(AppDataType::UserConfig, &crate::APP_INFO) {
        Ok(dirs) => Ok(dirs),
        Err(_) => Err(ConfigError(
            "Could not determine the user config directory.".into(),
        )),
    }
}

/// Return the path to the config file.
///
/// Note that this function does not verify whether the file at that location
/// exists, or is a file.
pub fn get_config_path() -> Result<PathBuf, TealdeerError> {
    let config_dir = get_config_dir()?;
    let config_file_path = config_dir.join(CONFIG_FILE_NAME);
    Ok(config_file_path)
}

/// Create default config file.
pub fn make_default_config() -> Result<PathBuf, TealdeerError> {
    let config_dir = get_config_dir()?;

    // Ensure that config directory exists
    if !config_dir.exists() {
        if let Err(e) = fs::create_dir_all(&config_dir) {
            return Err(ConfigError(format!(
                "Could not create config directory: {}",
                e
            )));
        }
    } else if !config_dir.is_dir() {
        return Err(ConfigError(format!(
            "Config directory could not be created: {} already exists but is not a directory",
            config_dir.to_string_lossy(),
        )));
    }

    // Ensure that a config file doesn't get overwritten
    let config_file_path = config_dir.join(CONFIG_FILE_NAME);
    if config_file_path.is_file() {
        return Err(ConfigError(format!(
            "A configuration file already exists at {}, no action was taken.",
            config_file_path.to_str().unwrap()
        )));
    }

    // Create default config
    let serialized_config = toml::to_string(&RawConfig::new())
        .map_err(|err| ConfigError(format!("Failed to serialize default config: {}", err)))?;

    // Write default config
    let mut config_file = fs::File::create(&config_file_path).map_err(map_io_err_to_config_err)?;
    let _wc = config_file
        .write(serialized_config.as_bytes())
        .map_err(map_io_err_to_config_err)?;

    Ok(config_file_path)
}

#[test]
fn test_serialize_deserialize() {
    let raw_config = RawConfig::new();
    let serialized = toml::to_string(&raw_config).unwrap();
    let deserialized: RawConfig = toml::from_str(&serialized).unwrap();
    assert_eq!(raw_config, deserialized);
}
<|endoftext|>


<commit_before>use hyper::Url;
use openssl::crypto::pkey::PKey;
use serde_json;
use serde_json::Value;
use serde_json::de::Deserializer;
use std::path::PathBuf;
use std::env;
use std::fs::File;
use std::io::Read;

pub struct Config {
    endpoint: Option<Url>,
    user: Option<String>,
    key: Option<PKey>,
}

impl Config {
    pub fn new() -> Config {
        Config {
            endpoint: None,
            user: None,
            key: None,
        }
    }

    /// Load a configuration file from JSON
    pub fn from_json(path: &str) -> Config {
        let path = get_absolute_path(path);
        let cfg = Config::new();
        match File::open(path) {
            Ok(mut fh) => {
                let mut data = String::new();
                fh.read_to_string(&mut data);
                let val: Value = serde_json::from_str(data.as_ref()).unwrap();
                let obj = val.as_object().unwrap();
                let cfg = cfg.key(obj.get("client_key").unwrap().as_string().unwrap());
                let cfg = cfg.endpoint(obj.get("chef_server_url").unwrap().as_string().unwrap());
                let cfg = cfg.user(obj.get("node_name").unwrap().as_string().unwrap());
                cfg
            },
            Err(_) => panic!("Couldn't open config file")
        }
    }

    pub fn key(mut self, path: &str) -> Config {
        let keypath = get_absolute_path(path);
        match File::open(keypath) {
            Ok(mut fh) => {
                self.key = Some(PKey::private_key_from_pem(&mut fh).unwrap());
                self
            }
            Err(_) => panic!("Couldn't open private key"),
        }
    }

    pub fn endpoint(mut self, endpoint: &str) -> Config {
        let url = match Url::parse(endpoint) {
            Ok(url) => url,
            Err(_) => panic!("Please provide a valid URL"),
        };
        self.endpoint = Some(url);
        self
    }

    pub fn user(mut self, user: &str) -> Config {
        self.user = Some(String::from(user));
        self
    }
}

fn get_absolute_path(val: &str) -> String {
    let mut p = PathBuf::from(val);
    if !p.is_absolute() {
        p = env::current_dir().unwrap();
        p.push(val);
    }
    p.to_str().unwrap().to_string()
}

#[cfg(test)]
mod tests {
    use super::*;

    use openssl::crypto::pkey::PKey;
    use std::fs::File;

    const ENDPOINT: &'static str = "https://localhost/organizations/clownco";
    const PRIVATE_KEY: &'static str = "fixtures/spec-user.pem";
    const CONFIG: &'static str = "fixtures/config.json";

    #[test]
    fn test_from_json() {
        let cfg = Config::from_json(CONFIG);
        assert_eq!(cfg.endpoint.unwrap().serialize_path().unwrap(),
                   "/organizations/rs_chef_api")
    }

    #[test]
    fn test_config_endpoint() {
        let cfg = Config::new().endpoint(ENDPOINT);
        assert_eq!(cfg.endpoint.unwrap().serialize_path().unwrap(),
                   "/organizations/clownco")
    }

    #[test]
    fn test_load_key() {
        let mut fh = File::open(PRIVATE_KEY).unwrap();
        let k0 = PKey::private_key_from_pem(&mut fh).unwrap();
        let cfg = Config::new().key(PRIVATE_KEY);
        assert!(cfg.key.unwrap().public_eq(&k0))
    }
}
<commit_msg>implement Debug for Config<commit_after>use hyper::Url;
use openssl::crypto::pkey::PKey;
use serde_json;
use serde_json::Value;
use std::path::PathBuf;
use std::env;
use std::fmt;
use std::fs::File;
use std::io::Read;

pub struct Config {
    pub endpoint: Option<Url>,
    pub user: Option<String>,
    pub key: Option<PKey>,
    keypath: Option<String>,
}

impl fmt::Debug for Config {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Config")
            .field("endpoint", &self.endpoint)
            .field("user", &self.user)
            .field("keypath", &self.keypath)
            .finish()
    }
}

impl Config {
    pub fn new() -> Config {
        Config {
            endpoint: None,
            user: None,
            key: None,
            keypath: None,
        }
    }

    /// Load a configuration file from JSON
    pub fn from_json(path: &str) -> Config {
        let path = get_absolute_path(path);
        let cfg = Config::new();
        match File::open(path) {
            Ok(mut fh) => {
                let mut data = String::new();
                fh.read_to_string(&mut data);
                let val: Value = serde_json::from_str(data.as_ref()).unwrap();
                let obj = val.as_object().unwrap();
                let cfg = cfg.key(obj.get("client_key").unwrap().as_string().unwrap());
                let cfg = cfg.endpoint(obj.get("chef_server_url").unwrap().as_string().unwrap());
                let cfg = cfg.user(obj.get("node_name").unwrap().as_string().unwrap());
                cfg
            },
            Err(_) => panic!("Couldn't open config file")
        }
    }

    pub fn key(mut self, path: &str) -> Config {
        let keypath = get_absolute_path(path);
        self.keypath = Some(keypath.clone());
        match File::open(keypath) {
            Ok(mut fh) => {
                self.key = Some(PKey::private_key_from_pem(&mut fh).unwrap());
                self
            }
            Err(_) => panic!("Couldn't open private key"),
        }
    }

    pub fn endpoint(mut self, endpoint: &str) -> Config {
        let url = match Url::parse(endpoint) {
            Ok(url) => url,
            Err(_) => panic!("Please provide a valid URL"),
        };
        self.endpoint = Some(url);
        self
    }

    pub fn user(mut self, user: &str) -> Config {
        self.user = Some(String::from(user));
        self
    }
}

fn get_absolute_path(val: &str) -> String {
    let mut p = PathBuf::from(val);
    if !p.is_absolute() {
        p = env::current_dir().unwrap();
        p.push(val);
    }
    p.to_str().unwrap().to_string()
}

#[cfg(test)]
mod tests {
    use super::*;

    use openssl::crypto::pkey::PKey;
    use std::fs::File;

    const ENDPOINT: &'static str = "https://localhost/organizations/clownco";
    const PRIVATE_KEY: &'static str = "fixtures/spec-user.pem";
    const CONFIG: &'static str = "fixtures/config.json";

    #[test]
    fn test_from_json() {
        let cfg = Config::from_json(CONFIG);
        assert_eq!(cfg.endpoint.unwrap().serialize_path().unwrap(),
                   "/organizations/rs_chef_api")
    }

    #[test]
    fn test_config_endpoint() {
        let cfg = Config::new().endpoint(ENDPOINT);
        assert_eq!(cfg.endpoint.unwrap().serialize_path().unwrap(),
                   "/organizations/clownco")
    }

    #[test]
    fn test_load_key() {
        let mut fh = File::open(PRIVATE_KEY).unwrap();
        let k0 = PKey::private_key_from_pem(&mut fh).unwrap();
        let cfg = Config::new().key(PRIVATE_KEY);
        assert!(cfg.key.unwrap().public_eq(&k0))
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
}<commit_msg>Add index impl and tests<commit_after>use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Index};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl MulAssign for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
}<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::io::Result;

use dsl::*;
use dsl::Constraint::*;

pub trait LpFileFormat {
    fn to_lp_file_format(&self) -> String;
    fn write_lp(&self, file_model: &str) -> Result<()> {
        let mut buffer = File::create(file_model)?;
        buffer.write(self.to_lp_file_format().as_bytes())?;
        Ok(())
    }
}

impl LpFileFormat for LpProblem {

    fn to_lp_file_format(&self) -> String {

        let mut buffer = String::new();

        buffer.push_str(format!("\\ {}\n\n", &self.name).as_str());

        buffer.push_str( &objective_lp_file_block(self) );

        let constraints_block = constraints_lp_file_block(self);
        if constraints_block.len() > 0 {
            buffer.push_str(format!("\n\nSubject To\n{}", &constraints_block).as_str());
        }

        let bounds_block = bounds_lp_file_block(self);
        if bounds_block.len() > 0 {
            buffer.push_str(format!("\nBounds\n{}", &bounds_block).as_str());
        }

        let integers_block = integers_lp_file_block(self);
        if integers_block.len() > 0 {
            buffer.push_str(format!("\nGenerals\n  {}\n", &integers_block).as_str());
        }

        let binaries_block = binaries_lp_file_block(self);
        if binaries_block.len() > 0 {
            buffer.push_str(format!("\nBinary\n  {}\n", &binaries_block).as_str());
        }

        buffer.push_str("\nEnd");

        buffer
    }
}

fn objective_lp_file_block(prob: &LpProblem) -> String {
    // Write objectives
    let obj_type = match prob.objective_type {
        LpObjective::Maximize => "Maximize\n  ",
        LpObjective::Minimize => "Minimize\n  "
    };
    match &prob.obj_expr_arena {
        Some(expr_arena) => {
            format!("{}obj: {}", obj_type, expr_arena.to_lp_file_format())
        }
        _ => String::new()
    }
}
fn constraints_lp_file_block(prob: &LpProblem) -> String {
    let mut res = String::new();
    let mut constraints = prob.constraints.iter();
    let mut index = 1;
    while let Some(constraint) = constraints.next() {
        res.push_str(&format!("  c{}: {}\n", index.to_string(), constraint.to_lp_file_format()));
        index += 1;
    }
    res
}

fn bounds_lp_file_block(prob: &LpProblem) -> String {
    let mut res = String::new();
    for (_, (constraint_index, lp_expr_arena_index)) in prob.variables() {
        let expr_ref = prob.constraints.get(constraint_index).unwrap().0.expr_ref_at(lp_expr_arena_index);
        match expr_ref {
            &LpExprNode::ConsInt(LpInteger {
                         ref name,
                         lower_bound,
                         upper_bound,
                     })
            | &LpExprNode::ConsCont(LpContinuous {
                            ref name,
                            lower_bound,
                            upper_bound,
                        }) => {
                if let Some(l) = lower_bound {
                    res.push_str(&format!("  {} <= {}", &l.to_string(), &name));
                    if let Some(u) = upper_bound {
                        res.push_str(&format!(" <= {}", &u.to_string()));
                    }
                    res.push_str("\n");
                } else if let Some(u) = upper_bound {
                    res.push_str(&format!("  {} <= {}\n", &name, &u.to_string()));
                } else {
                    match expr_ref {
                        &LpExprNode::ConsCont(LpContinuous { .. }) => {
                            res.push_str(&format!("  {} free\n", &name));
                        } // TODO: IntegerVar => -INF to INF
                        _ => (),
                    }
                }
            }
            _ => (),
        }
    }
    res
}

fn integers_lp_file_block(prob: &LpProblem) -> String {
    let mut res = String::new();
    for (_, (constraint_index, lp_expr_arena_index)) in prob.variables() {
        match prob.constraints.get(constraint_index).unwrap().0.expr_ref_at(lp_expr_arena_index) {
            &LpExprNode::ConsInt(LpInteger { ref name, .. }) => {
                res.push_str(format!("{} ", name).as_str());
            }
            _ => (),
        }
    }
    res
}

fn binaries_lp_file_block(prob: &LpProblem) -> String  {
    let mut res = String::new();
    for (_, (constraint_index, lp_expr_arena_index)) in prob.variables() {
        match prob.constraints.get(constraint_index).unwrap().0.expr_ref_at(lp_expr_arena_index) {
            &LpExprNode::ConsBin(LpBinary { ref name }) => {
                res.push_str(format!("{} ", name).as_str());
            }
            _ => (),
        }
    }
    res
}

impl LpFileFormat for LpExpression {
    fn to_lp_file_format(&self) -> String {
        fn formalize_signs(s: String) -> String {
            let mut s = s.clone();
            let mut t = "".to_string();
            while s != t {
                t = s.clone();
                s = s.replace("+ +", "+ ");
                s = s.replace("- +", "- ");
                s = s.replace("+ -", "- ");
                s = s.replace("- -", "+ ");
                s = s.replace("  ", " ");
            }
            s
        }
        let root_index = self.get_root_index();
        let mut clone = self.clone();
        formalize_signs(clone.simplify().show(&root_index, false))
    }
}

impl LpFileFormat for LpConstraint {
    fn to_lp_file_format(&self) -> String {
        let mut res = String::new();
        res.push_str(&self.0.to_lp_file_format());
        match self.1 {
            GreaterOrEqual => res.push_str(" >= "),
            LessOrEqual => res.push_str(" <= "),
            Equal => res.push_str(" = "),
        }
        res.push_str(&self.2.to_lp_file_format());
        res
    }
}
<commit_msg>add newline after End statement in .lp files, correct(er) files and should help with https://github.com/coin-or/CoinUtils/issues/145<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::io::Result;

use dsl::*;
use dsl::Constraint::*;

pub trait LpFileFormat {
    fn to_lp_file_format(&self) -> String;
    fn write_lp(&self, file_model: &str) -> Result<()> {
        let mut buffer = File::create(file_model)?;
        buffer.write(self.to_lp_file_format().as_bytes())?;
        Ok(())
    }
}

impl LpFileFormat for LpProblem {

    fn to_lp_file_format(&self) -> String {

        let mut buffer = String::new();

        buffer.push_str(format!("\\ {}\n\n", &self.name).as_str());

        buffer.push_str( &objective_lp_file_block(self) );

        let constraints_block = constraints_lp_file_block(self);
        if constraints_block.len() > 0 {
            buffer.push_str(format!("\n\nSubject To\n{}", &constraints_block).as_str());
        }

        let bounds_block = bounds_lp_file_block(self);
        if bounds_block.len() > 0 {
            buffer.push_str(format!("\nBounds\n{}", &bounds_block).as_str());
        }

        let integers_block = integers_lp_file_block(self);
        if integers_block.len() > 0 {
            buffer.push_str(format!("\nGenerals\n  {}\n", &integers_block).as_str());
        }

        let binaries_block = binaries_lp_file_block(self);
        if binaries_block.len() > 0 {
            buffer.push_str(format!("\nBinary\n  {}\n", &binaries_block).as_str());
        }

        buffer.push_str("\nEnd\n");

        buffer
    }
}

fn objective_lp_file_block(prob: &LpProblem) -> String {
    // Write objectives
    let obj_type = match prob.objective_type {
        LpObjective::Maximize => "Maximize\n  ",
        LpObjective::Minimize => "Minimize\n  "
    };
    match &prob.obj_expr_arena {
        Some(expr_arena) => {
            format!("{}obj: {}", obj_type, expr_arena.to_lp_file_format())
        }
        _ => String::new()
    }
}
fn constraints_lp_file_block(prob: &LpProblem) -> String {
    let mut res = String::new();
    let mut constraints = prob.constraints.iter();
    let mut index = 1;
    while let Some(constraint) = constraints.next() {
        res.push_str(&format!("  c{}: {}\n", index.to_string(), constraint.to_lp_file_format()));
        index += 1;
    }
    res
}

fn bounds_lp_file_block(prob: &LpProblem) -> String {
    let mut res = String::new();
    for (_, (constraint_index, lp_expr_arena_index)) in prob.variables() {
        let expr_ref = prob.constraints.get(constraint_index).unwrap().0.expr_ref_at(lp_expr_arena_index);
        match expr_ref {
            &LpExprNode::ConsInt(LpInteger {
                         ref name,
                         lower_bound,
                         upper_bound,
                     })
            | &LpExprNode::ConsCont(LpContinuous {
                            ref name,
                            lower_bound,
                            upper_bound,
                        }) => {
                if let Some(l) = lower_bound {
                    res.push_str(&format!("  {} <= {}", &l.to_string(), &name));
                    if let Some(u) = upper_bound {
                        res.push_str(&format!(" <= {}", &u.to_string()));
                    }
                    res.push_str("\n");
                } else if let Some(u) = upper_bound {
                    res.push_str(&format!("  {} <= {}\n", &name, &u.to_string()));
                } else {
                    match expr_ref {
                        &LpExprNode::ConsCont(LpContinuous { .. }) => {
                            res.push_str(&format!("  {} free\n", &name));
                        } // TODO: IntegerVar => -INF to INF
                        _ => (),
                    }
                }
            }
            _ => (),
        }
    }
    res
}

fn integers_lp_file_block(prob: &LpProblem) -> String {
    let mut res = String::new();
    for (_, (constraint_index, lp_expr_arena_index)) in prob.variables() {
        match prob.constraints.get(constraint_index).unwrap().0.expr_ref_at(lp_expr_arena_index) {
            &LpExprNode::ConsInt(LpInteger { ref name, .. }) => {
                res.push_str(format!("{} ", name).as_str());
            }
            _ => (),
        }
    }
    res
}

fn binaries_lp_file_block(prob: &LpProblem) -> String  {
    let mut res = String::new();
    for (_, (constraint_index, lp_expr_arena_index)) in prob.variables() {
        match prob.constraints.get(constraint_index).unwrap().0.expr_ref_at(lp_expr_arena_index) {
            &LpExprNode::ConsBin(LpBinary { ref name }) => {
                res.push_str(format!("{} ", name).as_str());
            }
            _ => (),
        }
    }
    res
}

impl LpFileFormat for LpExpression {
    fn to_lp_file_format(&self) -> String {
        fn formalize_signs(s: String) -> String {
            let mut s = s.clone();
            let mut t = "".to_string();
            while s != t {
                t = s.clone();
                s = s.replace("+ +", "+ ");
                s = s.replace("- +", "- ");
                s = s.replace("+ -", "- ");
                s = s.replace("- -", "+ ");
                s = s.replace("  ", " ");
            }
            s
        }
        let root_index = self.get_root_index();
        let mut clone = self.clone();
        formalize_signs(clone.simplify().show(&root_index, false))
    }
}

impl LpFileFormat for LpConstraint {
    fn to_lp_file_format(&self) -> String {
        let mut res = String::new();
        res.push_str(&self.0.to_lp_file_format());
        match self.1 {
            GreaterOrEqual => res.push_str(" >= "),
            LessOrEqual => res.push_str(" <= "),
            Equal => res.push_str(" = "),
        }
        res.push_str(&self.2.to_lp_file_format());
        res
    }
}
<|endoftext|>