<commit_before>// Copyright 2020 The Tink-Rust Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

use prost::Message;
use tink_core::{utils::wrap_err, TinkError};

#[test]
fn test_aes_gcm_key_templates() {
    // AES-GCM 128 bit
    let template = tink_aead::aes128_gcm_key_template();
    check_aes_gcm_key_template(&template, 16, tink_proto::OutputPrefixType::Tink)
        .expect("invalid AES-128 GCM key template");
    test_encrypt_decrypt(&template, tink_tests::AES_GCM_TYPE_URL).unwrap();

    // AES-GCM 256 bit
    let template = tink_aead::aes256_gcm_key_template();
    check_aes_gcm_key_template(&template, 32, tink_proto::OutputPrefixType::Tink)
        .expect("invalid AES-256 GCM key template");
    test_encrypt_decrypt(&template, tink_tests::AES_GCM_TYPE_URL).unwrap();

    // AES-GCM 256 bit No Prefix
    let template = tink_aead::aes256_gcm_no_prefix_key_template();
    check_aes_gcm_key_template(&template, 32, tink_proto::OutputPrefixType::Raw)
        .expect("invalid AES-256 GCM No Prefix key template");
    test_encrypt_decrypt(&template, tink_tests::AES_GCM_TYPE_URL).unwrap();
}

fn check_aes_gcm_key_template(
    template: &tink_proto::KeyTemplate,
    key_size: u32,
    output_prefix_type: tink_proto::OutputPrefixType,
) -> Result<(), TinkError> {
    if template.type_url != tink_tests::AES_GCM_TYPE_URL {
        return Err("incorrect type url".into());
    }
    if template.output_prefix_type != output_prefix_type as i32 {
        return Err("incorrect output prefix type".into());
    }
    let key_format = tink_proto::AesGcmKeyFormat::decode(template.value.as_ref())
        .map_err(|e| wrap_err("cannot deserialize key format", e))?;
    if key_format.key_size != key_size {
        return Err(format!(
            "incorrect key size, expect {}, got {}",
            key_size, key_format.key_size
        )
        .into());
    }
    Ok(())
}

#[test]
fn test_aes_gcm_siv_key_templates() {
    // AES-GCM-SIV 128 bit
    let template = tink_aead::aes128_gcm_siv_key_template();
    check_aes_gcm_siv_key_template(&template, 16, tink_proto::OutputPrefixType::Tink)
        .expect("invalid AES-128 GCM SIV key template");
    test_encrypt_decrypt(&template, tink_tests::AES_GCM_SIV_TYPE_URL).unwrap();

    // AES-GCM-SIV 256 bit
    let template = tink_aead::aes256_gcm_siv_key_template();
    check_aes_gcm_siv_key_template(&template, 32, tink_proto::OutputPrefixType::Tink)
        .expect("invalid AES-256 GCM SIV key template");
    test_encrypt_decrypt(&template, tink_tests::AES_GCM_SIV_TYPE_URL).unwrap();

    // AES-GCM-SIV 256 bit No Prefix
    let template = tink_aead::aes256_gcm_siv_no_prefix_key_template();
    check_aes_gcm_siv_key_template(&template, 32, tink_proto::OutputPrefixType::Raw)
        .expect("invalid AES-256 GCM No Prefix key template");
    test_encrypt_decrypt(&template, tink_tests::AES_GCM_SIV_TYPE_URL).unwrap();
}

fn check_aes_gcm_siv_key_template(
    template: &tink_proto::KeyTemplate,
    key_size: u32,
    output_prefix_type: tink_proto::OutputPrefixType,
) -> Result<(), TinkError> {
    if template.type_url != tink_tests::AES_GCM_SIV_TYPE_URL {
        return Err("incorrect type url".into());
    }
    if template.output_prefix_type != output_prefix_type as i32 {
        return Err("incorrect output prefix type".into());
    }
    let key_format = tink_proto::AesGcmKeyFormat::decode(template.value.as_ref())
        .map_err(|e| wrap_err("cannot deserialize key format", e))?;
    if key_format.key_size != key_size {
        return Err(format!(
            "incorrect key size, expect {}, got {}",
            key_size, key_format.key_size
        )
        .into());
    }
    Ok(())
}

#[test]
fn test_aes_ctr_hmac_aead_key_templates() {
    // AES-CTR 128 bit with HMAC SHA-256
    let template = tink_aead::aes128_ctr_hmac_sha256_key_template();
    check_aes_ctr_hmac_aead_key_template(&template, 16, 16, 16)
        .expect("invalid AES-128 CTR HMAC SHA256 key template");
    test_encrypt_decrypt(&template, tink_tests::AES_CTR_HMAC_AEAD_TYPE_URL).unwrap();

    // AES-CTR 256 bit with HMAC SHA-256
    let template = tink_aead::aes256_ctr_hmac_sha256_key_template();
    check_aes_ctr_hmac_aead_key_template(&template, 32, 16, 32)
        .expect("invalid AES-256 CTR HMAC SHA256 key template");
    test_encrypt_decrypt(&template, tink_tests::AES_CTR_HMAC_AEAD_TYPE_URL).unwrap();
}

fn check_aes_ctr_hmac_aead_key_template(
    template: &tink_proto::KeyTemplate,
    key_size: u32,
    iv_size: u32,
    tag_size: u32,
) -> Result<(), TinkError> {
    if template.type_url != tink_tests::AES_CTR_HMAC_AEAD_TYPE_URL {
        return Err("incorrect type url".into());
    }
    let key_format = tink_proto::AesCtrHmacAeadKeyFormat::decode(template.value.as_ref())
        .map_err(|e| wrap_err("cannot deserialize key format", e))?;
    let aes_format = key_format
        .aes_ctr_key_format
        .as_ref()
        .ok_or_else(|| TinkError::new("missing aes_ctr_key_format"))?;
    if aes_format.key_size != key_size {
        return Err(format!(
            "incorrect key size, expect {}, got {}",
            key_size, aes_format.key_size
        )
        .into());
    }
    if aes_format.params.as_ref().unwrap().iv_size != iv_size {
        return Err(format!(
            "incorrect IV size, expect {}, got {}",
            iv_size,
            aes_format.params.as_ref().unwrap().iv_size
        )
        .into());
    }
    let hmac_format = key_format
        .hmac_key_format
        .as_ref()
        .ok_or_else(|| TinkError::new("missing hmac_key_format"))?;
    if hmac_format.key_size != 32 {
        return Err(format!(
            "incorrect HMAC key size, expect 32, got {}",
            hmac_format.key_size
        )
        .into());
    }
    let hmac_params = hmac_format
        .params
        .as_ref()
        .ok_or_else(|| TinkError::new("missing hmac_format.params"))?;
    if hmac_params.tag_size != tag_size {
        return Err(format!(
            "incorrect HMAC tag size, expect {}, got {}",
            tag_size, hmac_params.tag_size
        )
        .into());
    }
    if hmac_params.hash != tink_proto::HashType::Sha256 as i32 {
        return Err(format!(
            "incorrect HMAC hash, expect {:?}, got {}",
            tink_proto::HashType::Sha256,
            hmac_params.hash
        )
        .into());
    }
    Ok(())
}

#[test]
fn test_cha_cha20_poly1305_key_template() {
    let template = tink_aead::cha_cha20_poly1305_key_template();
    assert_eq!(
        template.type_url,
        tink_tests::CHA_CHA20_POLY1305_TYPE_URL,
        "incorrect type url"
    );
    test_encrypt_decrypt(&template, tink_tests::CHA_CHA20_POLY1305_TYPE_URL).unwrap();
}

#[test]
fn test_x_cha_cha20_poly1305_key_template() {
    let template = tink_aead::x_cha_cha20_poly1305_key_template();
    assert_eq!(
        template.type_url,
        tink_tests::X_CHA_CHA20_POLY1305_TYPE_URL,
        "incorrect type url"
    );
    test_encrypt_decrypt(&template, tink_tests::X_CHA_CHA20_POLY1305_TYPE_URL).unwrap();
}

#[test]
fn test_kms_envelope_aead_key_templates() {
    tink_aead::init();
    let fake_kms_client = tink_tests::fakekms::FakeClient::new("fake-kms://").unwrap();
    tink_core::registry::register_kms_client(fake_kms_client);

    let fixed_key_uri = "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE";
    let new_key_uri = tink_tests::fakekms::new_key_uri().unwrap();

    let test_cases = vec![
        (
            "Fixed Fake KMS Envelope AEAD Key with AES128_GCM",
            tink_aead::kms_envelope_aead_key_template(
                fixed_key_uri,
                tink_aead::aes128_gcm_key_template(),
            ),
        ),
        (
            "New Fake KMS Envelope AEAD Key with AES128_GCM",
            tink_aead::kms_envelope_aead_key_template(
                &new_key_uri,
                tink_aead::aes128_gcm_key_template(),
            ),
        ),
    ];
    for (name, template) in test_cases {
        assert!(
            test_encrypt_decrypt(&template, &template.type_url).is_ok(),
            "failed for {}",
            name
        );
    }
}

fn test_encrypt_decrypt(
    template: &tink_proto::KeyTemplate,
    type_url: &str,
) -> Result<(), TinkError> {
    tink_aead::init();
    let sk = tink_core::registry::new_key(template)
        .map_err(|e| wrap_err("failed to get serialized key from template, error", e))?;

    let p = tink_core::registry::primitive(type_url, &sk)
        .map_err(|e| wrap_err("failed to get primitive from serialized key", e))?;
    let primitive = match p {
        tink_core::Primitive::Aead(p) => p,
        _ => return Err("failed to convert AEAD primitive".into()),
    };

    let plaintext = b"some data to encrypt";
    let aad = b"extra data to authenticate";
    let ciphertext = primitive
        .encrypt(&plaintext[..], &aad[..])
        .map_err(|e| wrap_err("encryption failed", e))?;
    let decrypted = primitive
        .decrypt(&ciphertext, &aad[..])
        .map_err(|e| wrap_err("decryption failed", e))?;

    if plaintext.to_vec() != decrypted {
        return Err(format!(
            "decrypted data doesn't match plaintext, got: {}, want: {}",
            hex::encode(&decrypted),
            hex::encode(&plaintext[..])
        )
        .into());
    }
    Ok(())
}
<commit_msg>tink-aead: tweak key template test<commit_after>// Copyright 2020 The Tink-Rust Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

use tink_core::{utils::wrap_err, TinkError};

#[test]
fn test_key_templates() {
    tink_aead::init();
    let test_cases = vec![
        ("AES128_GCM", tink_aead::aes128_gcm_key_template()),
        ("AES256_GCM", tink_aead::aes256_gcm_key_template()),
        (
            "AES128_CTR_HMAC_SHA256",
            tink_aead::aes128_ctr_hmac_sha256_key_template(),
        ),
        (
            "AES256_CTR_HMAC_SHA256",
            tink_aead::aes256_ctr_hmac_sha256_key_template(),
        ),
        ("AES128_GCM_SIV", tink_aead::aes128_gcm_siv_key_template()),
        ("AES256_GCM_SIV", tink_aead::aes256_gcm_siv_key_template()),
        (
            "CHACHA20_POLY1305",
            tink_aead::cha_cha20_poly1305_key_template(),
        ),
        (
            "XCHACHA20_POLY1305",
            tink_aead::x_cha_cha20_poly1305_key_template(),
        ),
    ];
    for (name, template) in test_cases {
        let want = tink_tests::key_template_proto("aead", name).unwrap();
        assert_eq!(want, template);
        assert!(test_encrypt_decrypt(&template).is_ok());
    }
}

#[test]
fn test_no_prefix_key_templates() {
    tink_aead::init();
    let test_cases = vec![
        ("AES256_GCM", tink_aead::aes256_gcm_no_prefix_key_template()),
        (
            "AES256_GCM_SIV",
            tink_aead::aes256_gcm_siv_no_prefix_key_template(),
        ),
    ];
    for (name, template) in test_cases {
        let mut want = tink_tests::key_template_proto("aead", name).unwrap();
        want.output_prefix_type = tink_proto::OutputPrefixType::Raw as i32;
        assert_eq!(want, template);
        assert!(test_encrypt_decrypt(&template).is_ok());
    }
}

#[test]
fn test_kms_envelope_aead_key_templates() {
    tink_aead::init();
    let fake_kms_client = tink_tests::fakekms::FakeClient::new("fake-kms://").unwrap();
    tink_core::registry::register_kms_client(fake_kms_client);

    let fixed_key_uri = "fake-kms://CM2b3_MDElQKSAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVzR2NtS2V5EhIaEIK75t5L-adlUwVhWvRuWUwYARABGM2b3_MDIAE";
    let new_key_uri = tink_tests::fakekms::new_key_uri().unwrap();

    let test_cases = vec![
        (
            "Fixed Fake KMS Envelope AEAD Key with AES128_GCM",
            tink_aead::kms_envelope_aead_key_template(
                fixed_key_uri,
                tink_aead::aes128_gcm_key_template(),
            ),
        ),
        (
            "New Fake KMS Envelope AEAD Key with AES128_GCM",
            tink_aead::kms_envelope_aead_key_template(
                &new_key_uri,
                tink_aead::aes128_gcm_key_template(),
            ),
        ),
    ];
    for (name, template) in test_cases {
        assert!(
            test_encrypt_decrypt(&template).is_ok(),
            "failed for {}",
            name
        );
    }
}

fn test_encrypt_decrypt(template: &tink_proto::KeyTemplate) -> Result<(), TinkError> {
    tink_aead::init();
    let handle = tink_core::keyset::Handle::new(template).unwrap();
    let primitive = tink_aead::new(&handle).unwrap();

    let plaintext = b"some data to encrypt";
    let aad = b"extra data to authenticate";
    let ciphertext = primitive
        .encrypt(&plaintext[..], &aad[..])
        .map_err(|e| wrap_err("encryption failed", e))?;
    let decrypted = primitive
        .decrypt(&ciphertext, &aad[..])
        .map_err(|e| wrap_err("decryption failed", e))?;

    if plaintext.to_vec() != decrypted {
        return Err(format!(
            "decrypted data doesn't match plaintext, got: {}, want: {}",
            hex::encode(&decrypted),
            hex::encode(&plaintext[..])
        )
        .into());
    }
    Ok(())
}
<|endoftext|>


<commit_before>use std::fmt;
use core::Message;
use descriptor::*;

fn print_bytes_to(bytes: &[u8], buf: &mut String) {
    buf.push('"');
    for &b in bytes.iter() {
        if b < 0x20 || b >= 0x7f {
            buf.push('\\');
            buf.push((b'0' + ((b >> 6) & 3)) as char);
            buf.push((b'0' + ((b >> 3) & 7)) as char);
            buf.push((b'0' + (b & 7)) as char);
        } else if b == b'"' {
            buf.push_str("\\\"");
        } else if b == b'\\' {
            buf.push_str("\\\\");
        } else {
            buf.push(b as char);
        }
    }
    buf.push('"');
}

fn print_str_to(s: &str, buf: &mut String) {
    // TODO: keep printable Unicode
    print_bytes_to(s.as_bytes(), buf);
}

fn do_indent(buf: &mut String, pretty: bool, indent: usize) {
    if pretty && indent > 0 {
        for _ in 0..indent {
            buf.push_str("  ");
        }
    }
}

fn print_to_internal(m: &Message, buf: &mut String, pretty: bool, indent: usize) {
    let d = m.descriptor();
    let mut first = true;
    for f in d.fields().iter() {
        if f.is_repeated() {
            for i in 0..f.len_field(m) {
                if !first && !pretty {
                    buf.push_str(" ");
                }
                do_indent(buf, pretty, indent);
                first = false;
                buf.push_str(f.name());
                match f.proto().get_field_type() {
                    FieldDescriptorProto_Type::TYPE_MESSAGE => {
                        buf.push_str(" {");
                        if pretty {
                            buf.push_str("\n");
                        }
                        print_to_internal(f.get_rep_message_item(m, i), buf, pretty, indent+1);
                        do_indent(buf, pretty, indent);
                        buf.push_str("}");
                    },
                    FieldDescriptorProto_Type::TYPE_ENUM => {
                        buf.push_str(": ");
                        buf.push_str(f.get_rep_enum_item(m, i).name());
                    },
                    FieldDescriptorProto_Type::TYPE_STRING => {
                        buf.push_str(": ");
                        print_str_to(f.get_rep_str_item(m, i), buf);
                    },
                    FieldDescriptorProto_Type::TYPE_BYTES => {
                        buf.push_str(": ");
                        print_bytes_to(f.get_rep_bytes_item(m, i), buf);
                    },
                    FieldDescriptorProto_Type::TYPE_INT32 |
                    FieldDescriptorProto_Type::TYPE_SINT32 |
                    FieldDescriptorProto_Type::TYPE_SFIXED32 => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_rep_i32(m)[i].to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_INT64 |
                    FieldDescriptorProto_Type::TYPE_SINT64 |
                    FieldDescriptorProto_Type::TYPE_SFIXED64 => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_rep_i64(m)[i].to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_UINT32 |
                    FieldDescriptorProto_Type::TYPE_FIXED32 => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_rep_u32(m)[i].to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_UINT64 |
                    FieldDescriptorProto_Type::TYPE_FIXED64 => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_rep_u64(m)[i].to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_BOOL => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_rep_bool(m)[i].to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_FLOAT => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_rep_f32(m)[i].to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_DOUBLE => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_rep_f64(m)[i].to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_GROUP => {
                        buf.push_str(": <TYPE_GROUP>");
                    }
                }
                if pretty {
                    buf.push_str("\n");
                }
            }
        } else {
            if f.has_field(m) {
                if !first && !pretty {
                    buf.push_str(" ");
                }
                do_indent(buf, pretty, indent);
                first = false;
                buf.push_str(f.name());
                match f.proto().get_field_type() {
                    FieldDescriptorProto_Type::TYPE_MESSAGE => {
                        buf.push_str(" {");
                        if pretty {
                            buf.push_str("\n");
                        }
                        print_to_internal(f.get_message(m), buf, pretty, indent+1);
                        do_indent(buf, pretty, indent);
                        buf.push_str("}");
                    },
                    FieldDescriptorProto_Type::TYPE_ENUM => {
                        buf.push_str(": ");
                        buf.push_str(f.get_enum(m).name());
                    },
                    FieldDescriptorProto_Type::TYPE_STRING => {
                        buf.push_str(": ");
                        print_str_to(f.get_str(m), buf);
                    },
                    FieldDescriptorProto_Type::TYPE_BYTES => {
                        buf.push_str(": ");
                        print_bytes_to(f.get_bytes(m), buf);
                    },
                    FieldDescriptorProto_Type::TYPE_INT32 |
                    FieldDescriptorProto_Type::TYPE_SINT32 |
                    FieldDescriptorProto_Type::TYPE_SFIXED32 => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_i32(m).to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_INT64 |
                    FieldDescriptorProto_Type::TYPE_SINT64 |
                    FieldDescriptorProto_Type::TYPE_SFIXED64 => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_i64(m).to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_UINT32 |
                    FieldDescriptorProto_Type::TYPE_FIXED32 => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_u32(m).to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_UINT64 |
                    FieldDescriptorProto_Type::TYPE_FIXED64 => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_u64(m).to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_BOOL => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_bool(m).to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_FLOAT => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_f32(m).to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_DOUBLE => {
                        buf.push_str(": ");
                        buf.push_str(&f.get_f64(m).to_string());
                    },
                    FieldDescriptorProto_Type::TYPE_GROUP => {
                        buf.push_str(": <TYPE_GROUP>");
                    }
                }
                if pretty {
                    buf.push_str("\n");
                }
            }
        }
    }

    // TODO: unknown fields
}

pub fn print_to(m: &Message, buf: &mut String) {
    print_to_internal(m, buf, false, 0)
}

fn print_to_string_internal(m: &Message, pretty: bool) -> String {
    let mut r = String::new();
    print_to_internal(m, &mut r, pretty, 0);
    r.to_string()
}

pub fn print_to_string(m: &Message) -> String {
    print_to_string_internal(m, false)
}

pub fn fmt(m: &Message, f: &mut fmt::Formatter) -> fmt::Result {
    let pretty = f.alternate();
    f.write_str(&print_to_string_internal(m, pretty))
}
<commit_msg>rewrite text_format without copy-paste between singular and repeated field serialization<commit_after>use std::fmt;
use core::Message;
use reflect::FieldDescriptor;
use reflect::EnumValueDescriptor;
use descriptor::*;

fn print_bytes_to(bytes: &[u8], buf: &mut String) {
    buf.push('"');
    for &b in bytes.iter() {
        if b < 0x20 || b >= 0x7f {
            buf.push('\\');
            buf.push((b'0' + ((b >> 6) & 3)) as char);
            buf.push((b'0' + ((b >> 3) & 7)) as char);
            buf.push((b'0' + (b & 7)) as char);
        } else if b == b'"' {
            buf.push_str("\\\"");
        } else if b == b'\\' {
            buf.push_str("\\\\");
        } else {
            buf.push(b as char);
        }
    }
    buf.push('"');
}

fn print_str_to(s: &str, buf: &mut String) {
    // TODO: keep printable Unicode
    print_bytes_to(s.as_bytes(), buf);
}

fn do_indent(buf: &mut String, pretty: bool, indent: usize) {
    if pretty && indent > 0 {
        for _ in 0..indent {
            buf.push_str("  ");
        }
    }
}

// internal helper
impl FieldDescriptor {
    // len fo repeated field, or 1 or 0 for singular field
    fn len_field_x(&self, m: &Message) -> usize {
        if self.is_repeated() {
            self.len_field(m)
        } else {
            match self.has_field(m) {
                true => 1,
                false => 0,
            }
        }
    }

    // get item by index for repeated fields, or just field for singular fields

    fn get_rep_message_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a Message {
        if self.is_repeated() {
            self.get_rep_message_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_message(m)
        }
    }

    fn get_rep_enum_item_x(&self, m: &Message, index: usize) -> &'static EnumValueDescriptor {
        if self.is_repeated() {
            self.get_rep_enum_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_enum(m)
        }
    }

    fn get_rep_str_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a str {
        if self.is_repeated() {
            self.get_rep_str_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_str(m)
        }
    }

    fn get_rep_bytes_item_x<'a>(&self, m: &'a Message, index: usize) -> &'a [u8] {
        if self.is_repeated() {
            self.get_rep_bytes_item(m, index)
        } else {
            assert_eq!(0, index);
            self.get_bytes(m)
        }
    }

    fn get_rep_i32_item_x(&self, m: &Message, index: usize) -> i32 {
        if self.is_repeated() {
            self.get_rep_i32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_i32(m)
        }
    }

    fn get_rep_u32_item_x(&self, m: &Message, index: usize) -> u32 {
        if self.is_repeated() {
            self.get_rep_u32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_u32(m)
        }
    }

    fn get_rep_i64_item_x(&self, m: &Message, index: usize) -> i64 {
        if self.is_repeated() {
            self.get_rep_i64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_i64(m)
        }
    }

    fn get_rep_u64_item_x(&self, m: &Message, index: usize) -> u64 {
        if self.is_repeated() {
            self.get_rep_u64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_u64(m)
        }
    }

    fn get_rep_bool_item_x(&self, m: &Message, index: usize) -> bool {
        if self.is_repeated() {
            self.get_rep_bool(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_bool(m)
        }
    }

    fn get_rep_f32_item_x(&self, m: &Message, index: usize) -> f32 {
        if self.is_repeated() {
            self.get_rep_f32(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_f32(m)
        }
    }

    fn get_rep_f64_item_x(&self, m: &Message, index: usize) -> f64 {
        if self.is_repeated() {
            self.get_rep_f64(m)[index]
        } else {
            assert_eq!(0, index);
            self.get_f64(m)
        }
    }

}

fn print_to_internal(m: &Message, buf: &mut String, pretty: bool, indent: usize) {
    let d = m.descriptor();
    let mut first = true;
    for f in d.fields().iter() {
        for i in 0..f.len_field_x(m) {
            if !first && !pretty {
                buf.push_str(" ");
            }
            do_indent(buf, pretty, indent);
            first = false;
            buf.push_str(f.name());
            match f.proto().get_field_type() {
                FieldDescriptorProto_Type::TYPE_MESSAGE => {
                    buf.push_str(" {");
                    if pretty {
                        buf.push_str("\n");
                    }
                    print_to_internal(f.get_rep_message_item_x(m, i), buf, pretty, indent+1);
                    do_indent(buf, pretty, indent);
                    buf.push_str("}");
                },
                FieldDescriptorProto_Type::TYPE_ENUM => {
                    buf.push_str(": ");
                    buf.push_str(f.get_rep_enum_item_x(m, i).name());
                },
                FieldDescriptorProto_Type::TYPE_STRING => {
                    buf.push_str(": ");
                    print_str_to(f.get_rep_str_item_x(m, i), buf);
                },
                FieldDescriptorProto_Type::TYPE_BYTES => {
                    buf.push_str(": ");
                    print_bytes_to(f.get_rep_bytes_item_x(m, i), buf);
                },
                FieldDescriptorProto_Type::TYPE_INT32 |
                FieldDescriptorProto_Type::TYPE_SINT32 |
                FieldDescriptorProto_Type::TYPE_SFIXED32 => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_i32_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_INT64 |
                FieldDescriptorProto_Type::TYPE_SINT64 |
                FieldDescriptorProto_Type::TYPE_SFIXED64 => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_i64_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_UINT32 |
                FieldDescriptorProto_Type::TYPE_FIXED32 => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_u32_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_UINT64 |
                FieldDescriptorProto_Type::TYPE_FIXED64 => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_u64_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_BOOL => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_bool_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_FLOAT => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_f32_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_DOUBLE => {
                    buf.push_str(": ");
                    buf.push_str(&f.get_rep_f64_item_x(m, i).to_string());
                },
                FieldDescriptorProto_Type::TYPE_GROUP => {
                    buf.push_str(": <TYPE_GROUP>");
                }
            }
            if pretty {
                buf.push_str("\n");
            }
        }
    }

    // TODO: unknown fields
}

pub fn print_to(m: &Message, buf: &mut String) {
    print_to_internal(m, buf, false, 0)
}

fn print_to_string_internal(m: &Message, pretty: bool) -> String {
    let mut r = String::new();
    print_to_internal(m, &mut r, pretty, 0);
    r.to_string()
}

pub fn print_to_string(m: &Message) -> String {
    print_to_string_internal(m, false)
}

pub fn fmt(m: &Message, f: &mut fmt::Formatter) -> fmt::Result {
    let pretty = f.alternate();
    f.write_str(&print_to_string_internal(m, pretty))
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 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.

//! Base64 binary-to-text encoding
use std::str;

/// Available encoding character sets
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`)
    Standard,
    /// The URL safe character set (uses `-` and `_`)
    UrlSafe
}

/// Contains configuration parameters for `to_base64`.
pub struct Config {
    /// Character set to use
    priv char_set: CharacterSet,
    /// True to pad output with `=` characters
    priv pad: bool,
    /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping
    priv line_length: Option<uint>
}

/// Configuration for RFC 4648 standard base64 encoding
pub static STANDARD: Config =
    Config {char_set: Standard, pad: true, line_length: None};

/// Configuration for RFC 4648 base64url encoding
pub static URL_SAFE: Config =
    Config {char_set: UrlSafe, pad: false, line_length: None};

/// Configuration for RFC 2045 MIME base64 encoding
pub static MIME: Config =
    Config {char_set: Standard, pad: true, line_length: Some(76)};

static STANDARD_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                                             "abcdefghijklmnopqrstuvwxyz",
                                             "0123456789+/");

static URLSAFE_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                                            "abcdefghijklmnopqrstuvwxyz",
                                            "0123456789-_");

/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
    /// Converts the value of `self` to a base64 value following the specified
    /// format configuration, returning the owned string.
    fn to_base64(&self, config: Config) -> ~str;
}

impl<'a> ToBase64 for &'a [u8] {
    /**
     * Turn a vector of `u8` bytes into a base64 string.
     *
     * # Example
     *
     * ```rust
     * extern mod extra;
     * use extra::base64::{ToBase64, STANDARD};
     *
     * fn main () {
     *     let str = [52,32].to_base64(STANDARD);
     *     println!("base 64 output: {}", str);
     * }
     * ```
     */
    fn to_base64(&self, config: Config) -> ~str {
        let bytes = match config.char_set {
            Standard => STANDARD_CHARS,
            UrlSafe => URLSAFE_CHARS
        };

        let mut v: ~[u8] = ~[];
        let mut i = 0;
        let mut cur_length = 0;
        let len = self.len();
        while i < len - (len % 3) {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                        cur_length = 0;
                    },
                None => ()
            }

            let n = (self[i] as u32) << 16 |
                    (self[i + 1] as u32) << 8 |
                    (self[i + 2] as u32);

            // This 24-bit number gets separated into four 6-bit numbers.
            v.push(bytes[(n >> 18) & 63]);
            v.push(bytes[(n >> 12) & 63]);
            v.push(bytes[(n >> 6 ) & 63]);
            v.push(bytes[n & 63]);

            cur_length += 4;
            i += 3;
        }

        if len % 3 != 0 {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                    },
                None => ()
            }
        }

        // Heh, would be cool if we knew this was exhaustive
        // (the dream of bounded integer types)
        match len % 3 {
            0 => (),
            1 => {
                let n = (self[i] as u32) << 16;
                v.push(bytes[(n >> 18) & 63]);
                v.push(bytes[(n >> 12) & 63]);
                if config.pad {
                    v.push('=' as u8);
                    v.push('=' as u8);
                }
            }
            2 => {
                let n = (self[i] as u32) << 16 |
                    (self[i + 1u] as u32) << 8;
                v.push(bytes[(n >> 18) & 63]);
                v.push(bytes[(n >> 12) & 63]);
                v.push(bytes[(n >> 6 ) & 63]);
                if config.pad {
                    v.push('=' as u8);
                }
            }
            _ => fail!("Algebra is broken, please alert the math police")
        }

        unsafe {
            str::raw::from_utf8_owned(v)
        }
    }
}

/// A trait for converting from base64 encoded values.
pub trait FromBase64 {
    /// Converts the value of `self`, interpreted as base64 encoded data, into
    /// an owned vector of bytes, returning the vector.
    fn from_base64(&self) -> Result<~[u8], ~str>;
}

impl<'a> FromBase64 for &'a str {
    /**
     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
     * to the byte values it encodes.
     *
     * You can use the `from_utf8_owned` function in `std::str`
     * to turn a `[u8]` into a string with characters corresponding to those
     * values.
     *
     * # Example
     *
     * This converts a string literal to base64 and back.
     *
     * ```rust
     * extern mod extra;
     * use extra::base64::{ToBase64, FromBase64, STANDARD};
     * use std::str;
     *
     * fn main () {
     *     let hello_str = bytes!("Hello, World").to_base64(STANDARD);
     *     println!("base64 output: {}", hello_str);
     *     let res = hello_str.from_base64();
     *     if res.is_ok() {
     *       let optBytes = str::from_utf8_owned_opt(res.unwrap());
     *       if optBytes.is_some() {
     *         println!("decoded from base64: {}", optBytes.unwrap());
     *       }
     *     }
     * }
     * ```
     */
    fn from_base64(&self) -> Result<~[u8], ~str> {
        let mut r = ~[];
        let mut buf: u32 = 0;
        let mut modulus = 0;

        let mut it = self.bytes().enumerate();
        for (idx, byte) in it {
            let val = byte as u32;

            match byte as char {
                'A'..'Z' => buf |= val - 0x41,
                'a'..'z' => buf |= val - 0x47,
                '0'..'9' => buf |= val + 0x04,
                '+'|'-' => buf |= 0x3E,
                '/'|'_' => buf |= 0x3F,
                '\r'|'\n' => continue,
                '=' => break,
                _ => return Err(format!("Invalid character '{}' at position {}",
                                     self.char_at(idx), idx))
            }

            buf <<= 6;
            modulus += 1;
            if modulus == 4 {
                modulus = 0;
                r.push((buf >> 22) as u8);
                r.push((buf >> 14) as u8);
                r.push((buf >> 6 ) as u8);
            }
        }

        for (idx, byte) in it {
            if (byte as char) != '=' {
                return Err(format!("Invalid character '{}' at position {}",
                                self.char_at(idx), idx));
            }
        }

        match modulus {
            2 => {
                r.push((buf >> 10) as u8);
            }
            3 => {
                r.push((buf >> 16) as u8);
                r.push((buf >> 8 ) as u8);
            }
            0 => (),
            _ => return Err(~"Invalid Base64 length")
        }

        Ok(r)
    }
}

#[cfg(test)]
mod test {
    use test::BenchHarness;
    use base64::*;

    #[test]
    fn test_to_base64_basic() {
        assert_eq!("".as_bytes().to_base64(STANDARD), ~"");
        assert_eq!("f".as_bytes().to_base64(STANDARD), ~"Zg==");
        assert_eq!("fo".as_bytes().to_base64(STANDARD), ~"Zm8=");
        assert_eq!("foo".as_bytes().to_base64(STANDARD), ~"Zm9v");
        assert_eq!("foob".as_bytes().to_base64(STANDARD), ~"Zm9vYg==");
        assert_eq!("fooba".as_bytes().to_base64(STANDARD), ~"Zm9vYmE=");
        assert_eq!("foobar".as_bytes().to_base64(STANDARD), ~"Zm9vYmFy");
    }

    #[test]
    fn test_to_base64_line_break() {
        assert!(![0u8, ..1000].to_base64(Config {line_length: None, ..STANDARD})
                .contains("\r\n"));
        assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
                                                         ..STANDARD}),
                   ~"Zm9v\r\nYmFy");
    }

    #[test]
    fn test_to_base64_padding() {
        assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
        assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
    }

    #[test]
    fn test_to_base64_url_safe() {
        assert_eq!([251, 255].to_base64(URL_SAFE), ~"-_8");
        assert_eq!([251, 255].to_base64(STANDARD), ~"+/8=");
    }

    #[test]
    fn test_from_base64_basic() {
        assert_eq!("".from_base64().unwrap(), "".as_bytes().to_owned());
        assert_eq!("Zg==".from_base64().unwrap(), "f".as_bytes().to_owned());
        assert_eq!("Zm8=".from_base64().unwrap(), "fo".as_bytes().to_owned());
        assert_eq!("Zm9v".from_base64().unwrap(), "foo".as_bytes().to_owned());
        assert_eq!("Zm9vYg==".from_base64().unwrap(), "foob".as_bytes().to_owned());
        assert_eq!("Zm9vYmE=".from_base64().unwrap(), "fooba".as_bytes().to_owned());
        assert_eq!("Zm9vYmFy".from_base64().unwrap(), "foobar".as_bytes().to_owned());
    }

    #[test]
    fn test_from_base64_newlines() {
        assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap(),
                   "foobar".as_bytes().to_owned());
    }

    #[test]
    fn test_from_base64_urlsafe() {
        assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap());
    }

    #[test]
    fn test_from_base64_invalid_char() {
        assert!("Zm$=".from_base64().is_err())
        assert!("Zg==$".from_base64().is_err());
    }

    #[test]
    fn test_from_base64_invalid_padding() {
        assert!("Z===".from_base64().is_err());
    }

    #[test]
    fn test_base64_random() {
        use std::rand::{task_rng, random, Rng};
        use std::vec;

        1000.times(|| {
            let times = task_rng().gen_range(1u, 100);
            let v = vec::from_fn(times, |_| random::<u8>());
            assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
        })
    }

    #[bench]
    pub fn bench_to_base64(bh: & mut BenchHarness) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        bh.iter(|| {
            s.as_bytes().to_base64(STANDARD);
        });
        bh.bytes = s.len() as u64;
    }

    #[bench]
    pub fn bench_from_base64(bh: & mut BenchHarness) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        let b = s.as_bytes().to_base64(STANDARD);
        bh.iter(|| {
            b.from_base64();
        });
        bh.bytes = b.len() as u64;
    }

}
<commit_msg>Make base64::config fields public again<commit_after>// Copyright 2012-2013 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.

//! Base64 binary-to-text encoding
use std::str;

/// Available encoding character sets
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`)
    Standard,
    /// The URL safe character set (uses `-` and `_`)
    UrlSafe
}

/// Contains configuration parameters for `to_base64`.
pub struct Config {
    /// Character set to use
    char_set: CharacterSet,
    /// True to pad output with `=` characters
    pad: bool,
    /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping
    line_length: Option<uint>
}

/// Configuration for RFC 4648 standard base64 encoding
pub static STANDARD: Config =
    Config {char_set: Standard, pad: true, line_length: None};

/// Configuration for RFC 4648 base64url encoding
pub static URL_SAFE: Config =
    Config {char_set: UrlSafe, pad: false, line_length: None};

/// Configuration for RFC 2045 MIME base64 encoding
pub static MIME: Config =
    Config {char_set: Standard, pad: true, line_length: Some(76)};

static STANDARD_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                                             "abcdefghijklmnopqrstuvwxyz",
                                             "0123456789+/");

static URLSAFE_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                                            "abcdefghijklmnopqrstuvwxyz",
                                            "0123456789-_");

/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
    /// Converts the value of `self` to a base64 value following the specified
    /// format configuration, returning the owned string.
    fn to_base64(&self, config: Config) -> ~str;
}

impl<'a> ToBase64 for &'a [u8] {
    /**
     * Turn a vector of `u8` bytes into a base64 string.
     *
     * # Example
     *
     * ```rust
     * extern mod extra;
     * use extra::base64::{ToBase64, STANDARD};
     *
     * fn main () {
     *     let str = [52,32].to_base64(STANDARD);
     *     println!("base 64 output: {}", str);
     * }
     * ```
     */
    fn to_base64(&self, config: Config) -> ~str {
        let bytes = match config.char_set {
            Standard => STANDARD_CHARS,
            UrlSafe => URLSAFE_CHARS
        };

        let mut v: ~[u8] = ~[];
        let mut i = 0;
        let mut cur_length = 0;
        let len = self.len();
        while i < len - (len % 3) {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                        cur_length = 0;
                    },
                None => ()
            }

            let n = (self[i] as u32) << 16 |
                    (self[i + 1] as u32) << 8 |
                    (self[i + 2] as u32);

            // This 24-bit number gets separated into four 6-bit numbers.
            v.push(bytes[(n >> 18) & 63]);
            v.push(bytes[(n >> 12) & 63]);
            v.push(bytes[(n >> 6 ) & 63]);
            v.push(bytes[n & 63]);

            cur_length += 4;
            i += 3;
        }

        if len % 3 != 0 {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                    },
                None => ()
            }
        }

        // Heh, would be cool if we knew this was exhaustive
        // (the dream of bounded integer types)
        match len % 3 {
            0 => (),
            1 => {
                let n = (self[i] as u32) << 16;
                v.push(bytes[(n >> 18) & 63]);
                v.push(bytes[(n >> 12) & 63]);
                if config.pad {
                    v.push('=' as u8);
                    v.push('=' as u8);
                }
            }
            2 => {
                let n = (self[i] as u32) << 16 |
                    (self[i + 1u] as u32) << 8;
                v.push(bytes[(n >> 18) & 63]);
                v.push(bytes[(n >> 12) & 63]);
                v.push(bytes[(n >> 6 ) & 63]);
                if config.pad {
                    v.push('=' as u8);
                }
            }
            _ => fail!("Algebra is broken, please alert the math police")
        }

        unsafe {
            str::raw::from_utf8_owned(v)
        }
    }
}

/// A trait for converting from base64 encoded values.
pub trait FromBase64 {
    /// Converts the value of `self`, interpreted as base64 encoded data, into
    /// an owned vector of bytes, returning the vector.
    fn from_base64(&self) -> Result<~[u8], ~str>;
}

impl<'a> FromBase64 for &'a str {
    /**
     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
     * to the byte values it encodes.
     *
     * You can use the `from_utf8_owned` function in `std::str`
     * to turn a `[u8]` into a string with characters corresponding to those
     * values.
     *
     * # Example
     *
     * This converts a string literal to base64 and back.
     *
     * ```rust
     * extern mod extra;
     * use extra::base64::{ToBase64, FromBase64, STANDARD};
     * use std::str;
     *
     * fn main () {
     *     let hello_str = bytes!("Hello, World").to_base64(STANDARD);
     *     println!("base64 output: {}", hello_str);
     *     let res = hello_str.from_base64();
     *     if res.is_ok() {
     *       let optBytes = str::from_utf8_owned_opt(res.unwrap());
     *       if optBytes.is_some() {
     *         println!("decoded from base64: {}", optBytes.unwrap());
     *       }
     *     }
     * }
     * ```
     */
    fn from_base64(&self) -> Result<~[u8], ~str> {
        let mut r = ~[];
        let mut buf: u32 = 0;
        let mut modulus = 0;

        let mut it = self.bytes().enumerate();
        for (idx, byte) in it {
            let val = byte as u32;

            match byte as char {
                'A'..'Z' => buf |= val - 0x41,
                'a'..'z' => buf |= val - 0x47,
                '0'..'9' => buf |= val + 0x04,
                '+'|'-' => buf |= 0x3E,
                '/'|'_' => buf |= 0x3F,
                '\r'|'\n' => continue,
                '=' => break,
                _ => return Err(format!("Invalid character '{}' at position {}",
                                     self.char_at(idx), idx))
            }

            buf <<= 6;
            modulus += 1;
            if modulus == 4 {
                modulus = 0;
                r.push((buf >> 22) as u8);
                r.push((buf >> 14) as u8);
                r.push((buf >> 6 ) as u8);
            }
        }

        for (idx, byte) in it {
            if (byte as char) != '=' {
                return Err(format!("Invalid character '{}' at position {}",
                                self.char_at(idx), idx));
            }
        }

        match modulus {
            2 => {
                r.push((buf >> 10) as u8);
            }
            3 => {
                r.push((buf >> 16) as u8);
                r.push((buf >> 8 ) as u8);
            }
            0 => (),
            _ => return Err(~"Invalid Base64 length")
        }

        Ok(r)
    }
}

#[cfg(test)]
mod test {
    use test::BenchHarness;
    use base64::*;

    #[test]
    fn test_to_base64_basic() {
        assert_eq!("".as_bytes().to_base64(STANDARD), ~"");
        assert_eq!("f".as_bytes().to_base64(STANDARD), ~"Zg==");
        assert_eq!("fo".as_bytes().to_base64(STANDARD), ~"Zm8=");
        assert_eq!("foo".as_bytes().to_base64(STANDARD), ~"Zm9v");
        assert_eq!("foob".as_bytes().to_base64(STANDARD), ~"Zm9vYg==");
        assert_eq!("fooba".as_bytes().to_base64(STANDARD), ~"Zm9vYmE=");
        assert_eq!("foobar".as_bytes().to_base64(STANDARD), ~"Zm9vYmFy");
    }

    #[test]
    fn test_to_base64_line_break() {
        assert!(![0u8, ..1000].to_base64(Config {line_length: None, ..STANDARD})
                .contains("\r\n"));
        assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
                                                         ..STANDARD}),
                   ~"Zm9v\r\nYmFy");
    }

    #[test]
    fn test_to_base64_padding() {
        assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
        assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
    }

    #[test]
    fn test_to_base64_url_safe() {
        assert_eq!([251, 255].to_base64(URL_SAFE), ~"-_8");
        assert_eq!([251, 255].to_base64(STANDARD), ~"+/8=");
    }

    #[test]
    fn test_from_base64_basic() {
        assert_eq!("".from_base64().unwrap(), "".as_bytes().to_owned());
        assert_eq!("Zg==".from_base64().unwrap(), "f".as_bytes().to_owned());
        assert_eq!("Zm8=".from_base64().unwrap(), "fo".as_bytes().to_owned());
        assert_eq!("Zm9v".from_base64().unwrap(), "foo".as_bytes().to_owned());
        assert_eq!("Zm9vYg==".from_base64().unwrap(), "foob".as_bytes().to_owned());
        assert_eq!("Zm9vYmE=".from_base64().unwrap(), "fooba".as_bytes().to_owned());
        assert_eq!("Zm9vYmFy".from_base64().unwrap(), "foobar".as_bytes().to_owned());
    }

    #[test]
    fn test_from_base64_newlines() {
        assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap(),
                   "foobar".as_bytes().to_owned());
    }

    #[test]
    fn test_from_base64_urlsafe() {
        assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap());
    }

    #[test]
    fn test_from_base64_invalid_char() {
        assert!("Zm$=".from_base64().is_err())
        assert!("Zg==$".from_base64().is_err());
    }

    #[test]
    fn test_from_base64_invalid_padding() {
        assert!("Z===".from_base64().is_err());
    }

    #[test]
    fn test_base64_random() {
        use std::rand::{task_rng, random, Rng};
        use std::vec;

        1000.times(|| {
            let times = task_rng().gen_range(1u, 100);
            let v = vec::from_fn(times, |_| random::<u8>());
            assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
        })
    }

    #[bench]
    pub fn bench_to_base64(bh: & mut BenchHarness) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        bh.iter(|| {
            s.as_bytes().to_base64(STANDARD);
        });
        bh.bytes = s.len() as u64;
    }

    #[bench]
    pub fn bench_from_base64(bh: & mut BenchHarness) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        let b = s.as_bytes().to_base64(STANDARD);
        bh.iter(|| {
            b.from_base64();
        });
        bh.bytes = b.len() as u64;
    }

}
<|endoftext|>


<commit_before>use std::env;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    let target = env::var("TARGET").expect("TARGET was not set");

    if cfg!(feature = "llvm-libunwind")
        && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
    {
        // Build the unwinding from libunwind C/C++ source code.
        llvm_libunwind::compile();
    } else if target.contains("linux") {
        if target.contains("musl") {
            // linking for musl is handled in lib.rs
            llvm_libunwind::compile();
        } else if !target.contains("android") {
            println!("cargo:rustc-link-lib=gcc_s");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("rumprun") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("netbsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("openbsd") {
        if target.contains("sparc64") {
            println!("cargo:rustc-link-lib=gcc");
        } else {
            println!("cargo:rustc-link-lib=c++abi");
        }
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("illumos") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("dragonfly") {
        println!("cargo:rustc-link-lib=gcc_pic");
    } else if target.contains("pc-windows-gnu") {
        // This is handled in the target spec with late_link_args_[static|dynamic]

        // cfg!(bootstrap) doesn't work in build scripts
        if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) {
            println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
            println!("cargo:rustc-link-lib=static-nobundle=pthread");
        }
    } else if target.contains("uwp-windows-gnu") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("fuchsia") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("haiku") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("redox") {
        // redox is handled in lib.rs
    } else if target.contains("cloudabi") {
        println!("cargo:rustc-link-lib=unwind");
    }
}

mod llvm_libunwind {
    use std::env;
    use std::path::Path;

    /// Compile the libunwind C/C++ source code.
    pub fn compile() {
        let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
        let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
        let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
        let cfg = &mut cc::Build::new();

        cfg.cpp(true);
        cfg.cpp_set_stdlib(None);
        cfg.warnings(false);

        // libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
        if target_endian_little {
            cfg.define("__LITTLE_ENDIAN__", Some("1"));
        }

        if target_env == "msvc" {
            // Don't pull in extra libraries on MSVC
            cfg.flag("/Zl");
            cfg.flag("/EHsc");
            cfg.define("_CRT_SECURE_NO_WARNINGS", None);
            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
        } else {
            cfg.flag("-std=c99");
            cfg.flag("-std=c++11");
            cfg.flag("-nostdinc++");
            cfg.flag("-fno-exceptions");
            cfg.flag("-fno-rtti");
            cfg.flag("-fstrict-aliasing");
            cfg.flag("-funwind-tables");
            cfg.flag("-fvisibility=hidden");
        }

        let mut unwind_sources = vec![
            "Unwind-EHABI.cpp",
            "Unwind-seh.cpp",
            "Unwind-sjlj.c",
            "UnwindLevel1-gcc-ext.c",
            "UnwindLevel1.c",
            "UnwindRegistersRestore.S",
            "UnwindRegistersSave.S",
            "libunwind.cpp",
        ];

        if target_vendor == "apple" {
            unwind_sources.push("Unwind_AppleExtras.cpp");
        }

        let root = Path::new("../llvm-project/libunwind");
        cfg.include(root.join("include"));
        for src in unwind_sources {
            cfg.file(root.join("src").join(src));
        }

        if target_env == "musl" {
            // use the same C compiler command to compile C++ code so we do not need to setup the
            // C++ compiler env variables on the builders
            cfg.cpp(false);
            // linking for musl is handled in lib.rs
            cfg.cargo_metadata(false);
            println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
        }

        cfg.compile("unwind");
    }
}
<commit_msg>Auto merge of #72746 - petrhosek:libunwind-hermetic, r=tmandry<commit_after>use std::env;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    let target = env::var("TARGET").expect("TARGET was not set");

    if cfg!(feature = "llvm-libunwind")
        && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
    {
        // Build the unwinding from libunwind C/C++ source code.
        llvm_libunwind::compile();
    } else if target.contains("linux") {
        if target.contains("musl") {
            // linking for musl is handled in lib.rs
            llvm_libunwind::compile();
        } else if !target.contains("android") {
            println!("cargo:rustc-link-lib=gcc_s");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("rumprun") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("netbsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("openbsd") {
        if target.contains("sparc64") {
            println!("cargo:rustc-link-lib=gcc");
        } else {
            println!("cargo:rustc-link-lib=c++abi");
        }
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("illumos") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("dragonfly") {
        println!("cargo:rustc-link-lib=gcc_pic");
    } else if target.contains("pc-windows-gnu") {
        // This is handled in the target spec with late_link_args_[static|dynamic]

        // cfg!(bootstrap) doesn't work in build scripts
        if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) {
            println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
            println!("cargo:rustc-link-lib=static-nobundle=pthread");
        }
    } else if target.contains("uwp-windows-gnu") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("fuchsia") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("haiku") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("redox") {
        // redox is handled in lib.rs
    } else if target.contains("cloudabi") {
        println!("cargo:rustc-link-lib=unwind");
    }
}

mod llvm_libunwind {
    use std::env;
    use std::path::Path;

    /// Compile the libunwind C/C++ source code.
    pub fn compile() {
        let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
        let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
        let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
        let cfg = &mut cc::Build::new();

        cfg.cpp(true);
        cfg.cpp_set_stdlib(None);
        cfg.warnings(false);

        // libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
        if target_endian_little {
            cfg.define("__LITTLE_ENDIAN__", Some("1"));
        }

        if target_env == "msvc" {
            // Don't pull in extra libraries on MSVC
            cfg.flag("/Zl");
            cfg.flag("/EHsc");
            cfg.define("_CRT_SECURE_NO_WARNINGS", None);
            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
        } else {
            cfg.flag("-std=c99");
            cfg.flag("-std=c++11");
            cfg.flag("-nostdinc++");
            cfg.flag("-fno-exceptions");
            cfg.flag("-fno-rtti");
            cfg.flag("-fstrict-aliasing");
            cfg.flag("-funwind-tables");
            cfg.flag("-fvisibility=hidden");
            cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
        }

        let mut unwind_sources = vec![
            "Unwind-EHABI.cpp",
            "Unwind-seh.cpp",
            "Unwind-sjlj.c",
            "UnwindLevel1-gcc-ext.c",
            "UnwindLevel1.c",
            "UnwindRegistersRestore.S",
            "UnwindRegistersSave.S",
            "libunwind.cpp",
        ];

        if target_vendor == "apple" {
            unwind_sources.push("Unwind_AppleExtras.cpp");
        }

        let root = Path::new("../llvm-project/libunwind");
        cfg.include(root.join("include"));
        for src in unwind_sources {
            cfg.file(root.join("src").join(src));
        }

        if target_env == "musl" {
            // use the same C compiler command to compile C++ code so we do not need to setup the
            // C++ compiler env variables on the builders
            cfg.cpp(false);
            // linking for musl is handled in lib.rs
            cfg.cargo_metadata(false);
            println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
        }

        cfg.compile("unwind");
    }
}
<|endoftext|>


<commit_before>// Higher level OpenCL wrappers.

use CL::*;
use CL::ll::*;

struct Platform {
    id: cl_platform_id
}

fn get_platforms() -> ~[Platform] {
    let mut num_platforms = 0;

    // TODO: Check result status
    clGetPlatformIDs(0, ptr::null(), ptr::addr_of(&num_platforms));

    let ids = vec::to_mut(vec::from_elem(num_platforms as uint,
                                         0 as cl_platform_id));

    do vec::as_imm_buf(ids) |ids, len| {
        clGetPlatformIDs(len as cl_uint,
                         ids, ptr::addr_of(&num_platforms))
    };

    do ids.map |id| { Platform { id: *id } }
}

struct Device {
    id: cl_device_id
}

fn get_devices(platform: Platform) -> ~[Device] {
    let mut num_devices = 0;

    clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, 0, ptr::null(),
                   ptr::addr_of(&num_devices));

    let ids = vec::to_mut(vec::from_elem(num_devices as uint,
                                         0 as cl_device_id));
    do vec::as_imm_buf(ids) |ids, len| {
        clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, len as cl_uint,
                       ids, ptr::addr_of(&num_devices));
    };

    do ids.map |id| { Device {id: *id }}
}

struct Context {
    ctx: cl_context,

    drop {
        clReleaseContext(self.ctx);
    }
}
<commit_msg>make the functions in hl module public.<commit_after>// Higher level OpenCL wrappers.

use CL::*;
use CL::ll::*;

struct Platform {
    id: cl_platform_id
}

pub fn get_platforms() -> ~[Platform] {
    let mut num_platforms = 0;

    // TODO: Check result status
    clGetPlatformIDs(0, ptr::null(), ptr::addr_of(&num_platforms));

    let ids = vec::to_mut(vec::from_elem(num_platforms as uint,
                                         0 as cl_platform_id));

    do vec::as_imm_buf(ids) |ids, len| {
        clGetPlatformIDs(len as cl_uint,
                         ids, ptr::addr_of(&num_platforms))
    };

    do ids.map |id| { Platform { id: *id } }
}

struct Device {
    id: cl_device_id
}

pub fn get_devices(platform: Platform) -> ~[Device] {
    let mut num_devices = 0;

    clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, 0, ptr::null(),
                   ptr::addr_of(&num_devices));

    let ids = vec::to_mut(vec::from_elem(num_devices as uint,
                                         0 as cl_device_id));
    do vec::as_imm_buf(ids) |ids, len| {
        clGetDeviceIDs(platform.id, CL_DEVICE_TYPE_GPU, len as cl_uint,
                       ids, ptr::addr_of(&num_devices));
    };

    do ids.map |id| { Device {id: *id }}
}

struct Context {
    ctx: cl_context,

    drop {
        clReleaseContext(self.ctx);
    }
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;

use std::borrow::Cow;
use std::io::Cursor;

use serde::{Deserialize, Serialize};
use rmps::{Deserializer, Serializer};

#[test]
fn round_trip_option() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct Foo {
        v: Option<Vec<u8>>,
    }

    let expected = Foo { v: None };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_optional_enum() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    pub enum SimpleEnum {
        Variant,
    }
    let expected = Some(SimpleEnum::Variant);

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));
    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_cow() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Foo<'a> {
        v: Cow<'a, [u8]>,
    }

    let expected = Foo { v : Cow::Borrowed(&[]) };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_option_cow() {
    use std::borrow::Cow;
    use std::io::Cursor;
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Foo<'a> {
        v: Option<Cow<'a, [u8]>>,
    }

    let expected = Foo { v : None };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum_with_struct_map() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected
        .serialize(&mut Serializer::new(&mut buf).with_struct_map())
        .unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum_with_struct_tuple() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected
        .serialize(&mut Serializer::new(&mut buf).with_struct_tuple())
        .unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_enum_with_newtype_struct() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Newtype(String);

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A(Newtype),
    }

    let expected = Enum::A(Newtype("le message".into()));
    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_untagged_enum_with_enum_associated_data() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    #[serde(untagged)]
    enum Foo {
        A(Bar),
    }

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Bar {
        B,
        C(String),
        D(u64, u64, u64),
        E{f1: String},
    }

    let data1_1 = Foo::A(Bar::B);
    let bytes_1 = rmps::to_vec(&data1_1).unwrap();
    let data1_2 = rmps::from_slice(&bytes_1).unwrap();
    assert_eq!(data1_1, data1_2);

    let data2_1 = Foo::A(Bar::C("Hello".into()));
    let bytes_2 = rmps::to_vec(&data2_1).unwrap();
    let data2_2 = rmps::from_slice(&bytes_2).unwrap();
    assert_eq!(data2_1, data2_2);

    let data3_1 = Foo::A(Bar::D(1,2,3));
    let bytes_3 = rmps::to_vec(&data3_1).unwrap();
    let data3_2 = rmps::from_slice(&bytes_3).unwrap();
    assert_eq!(data3_1, data3_2);

    let data4_1 = Foo::A(Bar::E{f1: "Hello".into()});
    let bytes_4 = rmps::to_vec(&data4_1).unwrap();
    let data4_2 = rmps::from_slice(&bytes_4).unwrap();
    assert_eq!(data4_1, data4_2);
}

// Checks whether deserialization and serialization can both work with structs as maps
#[test]
fn round_struct_as_map() {
    use rmps::to_vec_named;
    use rmps::decode::from_slice;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog1 {
        name: String,
        age: u16,
    }
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog2 {
        age: u16,
        name: String,
    }

    let dog1 = Dog1 {
        name: "Frankie".into(),
        age: 42,
    };

    let serialized: Vec<u8> = to_vec_named(&dog1).unwrap();
    let deserialized: Dog2 = from_slice(&serialized).unwrap();

    let check = Dog1 {
        age: deserialized.age,
        name: deserialized.name,
    };

    assert_eq!(dog1, check);
}

#[test]
fn round_struct_as_map_in_vec() {
    // See: issue #205
    use rmps::decode::from_slice;
    use rmps::to_vec_named;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog1 {
        name: String,
        age: u16,
    }
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog2 {
        age: u16,
        name: String,
    }

    let dog1 = Dog1 {
        name: "Frankie".into(),
        age: 42,
    };

    let data = vec![dog1];

    let serialized: Vec<u8> = to_vec_named(&data).unwrap();
    let deserialized: Vec<Dog2> = from_slice(&serialized).unwrap();

    let dog2 = &deserialized[0];

    assert_eq!(dog2.name, "Frankie");
    assert_eq!(dog2.age, 42);
}

#[test]
fn round_trip_unit_struct() {
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Message1 {
        data: u8,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Message2;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    enum Messages {
        Message1(Message1),
        Message2(Message2),
    }

    let msg2 = Messages::Message2(Message2);

    // struct-as-tuple
    {
        let serialized: Vec<u8> = rmps::to_vec(&msg2).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msg2);
    }

    // struct-as-map
    {
        let serialized: Vec<u8> = rmps::to_vec_named(&msg2).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msg2);
    }
}

#[test]
#[ignore]
fn round_trip_unit_struct_untagged_enum() {
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct UnitStruct;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct MessageA {
        some_int: i32,
        unit: UnitStruct,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    #[serde(untagged)]
    enum Messages {
        MessageA(MessageA),
    }

    let msga = Messages::MessageA(MessageA {
        some_int: 32,
        unit: UnitStruct,
    });

    // struct-as-tuple
    {
        let serialized: Vec<u8> = rmps::to_vec(&msga).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msga);
    }

    // struct-as-map
    {
        let serialized: Vec<u8> = rmps::to_vec_named(&msga).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msga);
    }
}
<commit_msg>Add a round-trip test for encoding enum variants as strings.<commit_after>extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;

use std::borrow::Cow;
use std::io::Cursor;

use serde::{Deserialize, Serialize};
use rmps::{Deserializer, Serializer};

#[test]
fn round_trip_option() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct Foo {
        v: Option<Vec<u8>>,
    }

    let expected = Foo { v: None };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_optional_enum() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    pub enum SimpleEnum {
        Variant,
    }
    let expected = Some(SimpleEnum::Variant);

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));
    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_cow() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Foo<'a> {
        v: Cow<'a, [u8]>,
    }

    let expected = Foo { v : Cow::Borrowed(&[]) };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_option_cow() {
    use std::borrow::Cow;
    use std::io::Cursor;
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Foo<'a> {
        v: Option<Cow<'a, [u8]>>,
    }

    let expected = Foo { v : None };

    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(Cursor::new(&buf[..]));

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum_with_struct_map() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected
        .serialize(&mut Serializer::new(&mut buf).with_struct_map())
        .unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_struct_like_enum_with_struct_tuple() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A { data: u32 },
    }

    let expected = Enum::A { data: 42 };
    let mut buf = Vec::new();
    expected
        .serialize(&mut Serializer::new(&mut buf).with_struct_tuple())
        .unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_enum_with_newtype_struct() {
    use serde::Serialize;

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    struct Newtype(String);

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Enum {
        A(Newtype),
    }

    let expected = Enum::A(Newtype("le message".into()));
    let mut buf = Vec::new();
    expected.serialize(&mut Serializer::new(&mut buf)).unwrap();

    let mut de = Deserializer::new(&buf[..]);

    assert_eq!(expected, Deserialize::deserialize(&mut de).unwrap());
}

#[test]
fn round_trip_untagged_enum_with_enum_associated_data() {
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    #[serde(untagged)]
    enum Foo {
        A(Bar),
    }

    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    enum Bar {
        B,
        C(String),
        D(u64, u64, u64),
        E{f1: String},
    }

    let data1_1 = Foo::A(Bar::B);
    let bytes_1 = rmps::to_vec(&data1_1).unwrap();
    let data1_2 = rmps::from_slice(&bytes_1).unwrap();
    assert_eq!(data1_1, data1_2);

    let data2_1 = Foo::A(Bar::C("Hello".into()));
    let bytes_2 = rmps::to_vec(&data2_1).unwrap();
    let data2_2 = rmps::from_slice(&bytes_2).unwrap();
    assert_eq!(data2_1, data2_2);

    let data3_1 = Foo::A(Bar::D(1,2,3));
    let bytes_3 = rmps::to_vec(&data3_1).unwrap();
    let data3_2 = rmps::from_slice(&bytes_3).unwrap();
    assert_eq!(data3_1, data3_2);

    let data4_1 = Foo::A(Bar::E{f1: "Hello".into()});
    let bytes_4 = rmps::to_vec(&data4_1).unwrap();
    let data4_2 = rmps::from_slice(&bytes_4).unwrap();
    assert_eq!(data4_1, data4_2);
}

// Checks whether deserialization and serialization can both work with structs as maps
#[test]
fn round_struct_as_map() {
    use rmps::to_vec_named;
    use rmps::decode::from_slice;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog1 {
        name: String,
        age: u16,
    }
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog2 {
        age: u16,
        name: String,
    }

    let dog1 = Dog1 {
        name: "Frankie".into(),
        age: 42,
    };

    let serialized: Vec<u8> = to_vec_named(&dog1).unwrap();
    let deserialized: Dog2 = from_slice(&serialized).unwrap();

    let check = Dog1 {
        age: deserialized.age,
        name: deserialized.name,
    };

    assert_eq!(dog1, check);
}

#[test]
fn round_struct_as_map_in_vec() {
    // See: issue #205
    use rmps::decode::from_slice;
    use rmps::to_vec_named;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog1 {
        name: String,
        age: u16,
    }
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Dog2 {
        age: u16,
        name: String,
    }

    let dog1 = Dog1 {
        name: "Frankie".into(),
        age: 42,
    };

    let data = vec![dog1];

    let serialized: Vec<u8> = to_vec_named(&data).unwrap();
    let deserialized: Vec<Dog2> = from_slice(&serialized).unwrap();

    let dog2 = &deserialized[0];

    assert_eq!(dog2.name, "Frankie");
    assert_eq!(dog2.age, 42);
}

#[test]
fn round_trip_unit_struct() {
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Message1 {
        data: u8,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct Message2;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    enum Messages {
        Message1(Message1),
        Message2(Message2),
    }

    let msg2 = Messages::Message2(Message2);

    // struct-as-tuple
    {
        let serialized: Vec<u8> = rmps::to_vec(&msg2).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msg2);
    }

    // struct-as-map
    {
        let serialized: Vec<u8> = rmps::to_vec_named(&msg2).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msg2);
    }
}

#[test]
#[ignore]
fn round_trip_unit_struct_untagged_enum() {
    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct UnitStruct;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    struct MessageA {
        some_int: i32,
        unit: UnitStruct,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    #[serde(untagged)]
    enum Messages {
        MessageA(MessageA),
    }

    let msga = Messages::MessageA(MessageA {
        some_int: 32,
        unit: UnitStruct,
    });

    // struct-as-tuple
    {
        let serialized: Vec<u8> = rmps::to_vec(&msga).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msga);
    }

    // struct-as-map
    {
        let serialized: Vec<u8> = rmps::to_vec_named(&msga).unwrap();
        let deserialized: Messages = rmps::from_slice(&serialized).unwrap();
        assert_eq!(deserialized, msga);
    }
}

// Checks whether deserialization and serialization can both work with enum variants as strings
#[test]
fn round_variant_string() {
    use rmps::decode::from_slice;

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    enum Animal1 {
        Dog { breed: String },
        Cat,
        Emu,
    }

    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
    enum Animal2 {
        Emu,
        Dog { breed: String },
        Cat,
    }

    // use helper macro so that we can test many combinations at once. Needs to be a macro to deal
    // with the serializer owning a reference to the Vec.
    macro_rules! do_test {
        ($ser:expr) => {
            {
                let animal1 = Animal1::Dog { breed: "Pitbull".to_owned() };
                let expected = Animal2::Dog { breed: "Pitbull".to_owned() };
                let mut buf = Vec::new();
                animal1.serialize(&mut $ser(&mut buf)).unwrap();

                let deserialized: Animal2 = from_slice(&buf).unwrap();
                assert_eq!(deserialized, expected);
            }
        }
    }

    do_test!(|b| Serializer::new(b).with_string_variants());
    do_test!(|b| Serializer::new(b).with_struct_map().with_string_variants());
    do_test!(|b| Serializer::new(b).with_struct_tuple().with_string_variants());
    do_test!(|b| Serializer::new(b).with_string_variants().with_struct_map());
    do_test!(|b| Serializer::new(b).with_string_variants().with_struct_tuple());
    do_test!(|b| {
        Serializer::new(b)
            .with_string_variants()
            .with_struct_tuple()
            .with_struct_map()
            .with_struct_tuple()
            .with_struct_map()
    });
    do_test!(|b| Serializer::new(b).with_integer_variants().with_string_variants());
}
<|endoftext|>


<commit_before>use ptr::{null, addr_of};
use result::{Result, Ok, Err};
use libc::{c_char, c_uint};
use name_pool::{name_pool, add};
use str::raw::from_c_str;
use io::WriterUtil;
use jsapi::{JSBool, JSClass, JSContext, JSErrorReport, JSFunctionSpec,
               JSObject, JSRuntime, JSString, JSVERSION_LATEST, jsval,
               JSPropertySpec, JSPropertyOp, JSStrictPropertyOp};
use jsapi::bindgen::{JS_free, JS_AddObjectRoot, JS_DefineFunctions,
                        JS_DestroyContext, JS_EncodeString, JS_EvaluateScript,
                        JS_Finish, JS_GetContextPrivate, JS_GetPrivate,
                        JS_Init, JS_InitStandardClasses,
                        JS_NewGlobalObject, JS_NewContext,
                        JS_RemoveObjectRoot, JS_SetContextPrivate,
                        JS_SetErrorReporter, JS_SetOptions, JS_SetPrivate,
                        JS_SetVersion, JS_ValueToString, JS_DefineProperties,
                        JS_DefineProperty, JS_NewObject, JS_ComputeThis};
use libc::types::common::c99::{int8_t, int16_t, int32_t, int64_t, uint8_t,
                                  uint16_t, uint32_t, uint64_t};
use glue::bindgen::{RUST_JSVAL_TO_OBJECT, RUST_JSVAL_IS_PRIMITIVE};
use rust::jsobj;

export JSOPTION_STRICT;
export JSOPTION_WERROR;
export JSOPTION_VAROBJFIX;
export JSOPTION_METHODJIT;

export JSPROP_ENUMERATE;
export JSPROP_SHARED;
export JSPROP_NATIVE_ACCESSORS;

export JSCLASS_GLOBAL_FLAGS;
export JSCLASS_HAS_RESERVED_SLOTS;

export rust;
export name_pool;

export jsapi;
export global;
export glue;
export crust;

export ptr_methods;

// These are just macros in jsapi.h
use JS_NewRuntime = jsapi::bindgen::JS_Init;
export JS_NewRuntime;
use JS_DestroyRuntime = jsapi::bindgen::JS_Finish;
export JS_DestroyRuntime;
/*
FIXME: Not sure where JS_Lock is
use JS_LockRuntime = jsapi::bindgen::JS_Lock;
export JS_LockRuntime;
use JS_UnlockRuntime = jsapi::bindgen::JS_Unlock;
export JS_UnlockRuntime;
*/

export JS_ARGV;
export JS_SET_RVAL;
export JS_THIS_OBJECT;
export JSVAL_VOID;
export JSVAL_NULL;
export JSVAL_ZERO;
export JSVAL_ONE;
export JSVAL_FALSE;
export JSVAL_TRUE;

// FIXME: Add the remaining options
const JSOPTION_STRICT: uint32_t =    0b00000000000001u32;
const JSOPTION_WERROR: uint32_t =    0b00000000000010u32;
const JSOPTION_VAROBJFIX: uint32_t = 0b00000000000100u32;
//const JSOPTION_METHODJIT: uint32_t = 0b100000000000000u32;
const JSOPTION_METHODJIT: uint32_t = (1 << 14) as u32;

const default_heapsize: u32 = 8_u32 * 1024_u32 * 1024_u32;
const default_stacksize: uint = 8192u;
const ERR: JSBool = 0_i32;

const JSVAL_TAG_MAX_DOUBLE: u64 = 0x1FFF0;

const JSVAL_TYPE_DOUBLE: u64 = 0x00;
const JSVAL_TYPE_INT32: u64 = 0x01;
const JSVAL_TYPE_UNDEFINED: u64 = 0x02;
const JSVAL_TYPE_BOOLEAN: u64 = 0x03;
const JSVAL_TYPE_MAGIC: u64 = 0x04;
const JSVAL_TYPE_STRING: u64 = 0x05;
const JSVAL_TYPE_NULL: u64 = 0x06;
const JSVAL_TYPE_OBJECT: u64 = 0x07;
const JSVAL_TYPE_UNKNOWN: u64 = 0x20;

const JSVAL_TAG_SHIFT: int = 47;

//The following constants are totally broken on non-64bit platforms.
//See jsapi.h for the proper macro definitions.
const JSVAL_VOID: u64 = (JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNKNOWN) << JSVAL_TAG_SHIFT;
const JSVAL_NULL: u64 = (JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL) << JSVAL_TAG_SHIFT;
const JSVAL_ZERO: u64 = (JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32) << JSVAL_TAG_SHIFT;
const JSVAL_ONE: u64 = ((JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32) << JSVAL_TAG_SHIFT) | 1;
const JSVAL_FALSE: u64 = (JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN) << JSVAL_TAG_SHIFT;
const JSVAL_TRUE: u64 = ((JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN) << JSVAL_TAG_SHIFT) | 1;

const JSPROP_ENUMERATE: c_uint = 0x01;
const JSPROP_READONLY: c_uint  = 0x02;
const JSPROP_SHARED: c_uint =    0x40;
const JSPROP_NATIVE_ACCESSORS: c_uint = 0x08;

const JSCLASS_RESERVED_SLOTS_SHIFT: c_uint = 8;
const JSCLASS_RESERVED_SLOTS_WIDTH: c_uint = 8;
const JSCLASS_RESERVED_SLOTS_MASK: c_uint = ((1 << JSCLASS_RESERVED_SLOTS_WIDTH) - 1);

const JSCLASS_HIGH_FLAGS_SHIFT: c_uint =
    JSCLASS_RESERVED_SLOTS_SHIFT + JSCLASS_RESERVED_SLOTS_WIDTH;
const JSCLASS_IS_GLOBAL: c_uint = (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1));

// The 41 is derived from the number of entries in jsproto.tbl. See jsapi.h for more info.
const JSCLASS_GLOBAL_SLOT_COUNT: c_uint = 41 * 3 + 24;

pure fn JSCLASS_HAS_RESERVED_SLOTS(n: c_uint) -> c_uint {
    (n & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT
}

fn result(n: JSBool) -> Result<(),()> {
    if n != ERR {Ok(())} else {Err(())}
}
fn result_obj(o: jsobj) -> Result<jsobj, ()> {
    if o.ptr != null() {Ok(o)} else {Err(())}
}

type named_functions = @{
    names: ~[~str],
    funcs: ~[JSFunctionSpec]
};

#[inline(always)]
unsafe fn JS_ARGV(_cx: *JSContext, vp: *jsval) -> *jsval {
    ptr::offset(vp, 2u)
}

unsafe fn JS_SET_RVAL(_cx: *JSContext, vp: *jsval, v: jsval) {
    let vp: *mut jsval = unsafe::reinterpret_cast(&vp);
    *vp = v;
}

#[inline(always)]
unsafe fn JS_THIS_OBJECT(cx: *JSContext, vp: *jsval) -> *JSObject unsafe {
    let r = RUST_JSVAL_TO_OBJECT(
        if RUST_JSVAL_IS_PRIMITIVE(*ptr::offset(vp, 1)) == 0 {
            JS_ComputeThis(cx, vp)
        } else {
            *ptr::offset(vp, 1)
        });
    r
}

<commit_msg>Use fewer magic numbers.<commit_after>use ptr::{null, addr_of};
use result::{Result, Ok, Err};
use libc::{c_char, c_uint};
use name_pool::{name_pool, add};
use str::raw::from_c_str;
use io::WriterUtil;
use jsapi::{JSBool, JSClass, JSContext, JSErrorReport, JSFunctionSpec,
               JSObject, JSRuntime, JSString, JSVERSION_LATEST, jsval,
               JSPropertySpec, JSPropertyOp, JSStrictPropertyOp};
use jsapi::bindgen::{JS_free, JS_AddObjectRoot, JS_DefineFunctions,
                        JS_DestroyContext, JS_EncodeString, JS_EvaluateScript,
                        JS_Finish, JS_GetContextPrivate, JS_GetPrivate,
                        JS_Init, JS_InitStandardClasses,
                        JS_NewGlobalObject, JS_NewContext,
                        JS_RemoveObjectRoot, JS_SetContextPrivate,
                        JS_SetErrorReporter, JS_SetOptions, JS_SetPrivate,
                        JS_SetVersion, JS_ValueToString, JS_DefineProperties,
                        JS_DefineProperty, JS_NewObject, JS_ComputeThis};
use libc::types::common::c99::{int8_t, int16_t, int32_t, int64_t, uint8_t,
                                  uint16_t, uint32_t, uint64_t};
use glue::bindgen::{RUST_JSVAL_TO_OBJECT, RUST_JSVAL_IS_PRIMITIVE};
use rust::jsobj;

export JSOPTION_STRICT;
export JSOPTION_WERROR;
export JSOPTION_VAROBJFIX;
export JSOPTION_METHODJIT;

export JSPROP_ENUMERATE;
export JSPROP_SHARED;
export JSPROP_NATIVE_ACCESSORS;

export JSCLASS_GLOBAL_FLAGS;
export JSCLASS_HAS_RESERVED_SLOTS;

export rust;
export name_pool;

export jsapi;
export global;
export glue;
export crust;

export ptr_methods;

// These are just macros in jsapi.h
use JS_NewRuntime = jsapi::bindgen::JS_Init;
export JS_NewRuntime;
use JS_DestroyRuntime = jsapi::bindgen::JS_Finish;
export JS_DestroyRuntime;
/*
FIXME: Not sure where JS_Lock is
use JS_LockRuntime = jsapi::bindgen::JS_Lock;
export JS_LockRuntime;
use JS_UnlockRuntime = jsapi::bindgen::JS_Unlock;
export JS_UnlockRuntime;
*/

export JS_ARGV;
export JS_SET_RVAL;
export JS_THIS_OBJECT;
export JSVAL_VOID;
export JSVAL_NULL;
export JSVAL_ZERO;
export JSVAL_ONE;
export JSVAL_FALSE;
export JSVAL_TRUE;

// FIXME: Add the remaining options
const JSOPTION_STRICT: uint32_t =    0b00000000000001u32;
const JSOPTION_WERROR: uint32_t =    0b00000000000010u32;
const JSOPTION_VAROBJFIX: uint32_t = 0b00000000000100u32;
//const JSOPTION_METHODJIT: uint32_t = 0b100000000000000u32;
const JSOPTION_METHODJIT: uint32_t = (1 << 14) as u32;

const default_heapsize: u32 = 8_u32 * 1024_u32 * 1024_u32;
const default_stacksize: uint = 8192u;
const ERR: JSBool = 0_i32;

const JSVAL_TAG_MAX_DOUBLE: u64 = 0x1FFF0;

const JSVAL_TYPE_DOUBLE: u64 = 0x00;
const JSVAL_TYPE_INT32: u64 = 0x01;
const JSVAL_TYPE_UNDEFINED: u64 = 0x02;
const JSVAL_TYPE_BOOLEAN: u64 = 0x03;
const JSVAL_TYPE_MAGIC: u64 = 0x04;
const JSVAL_TYPE_STRING: u64 = 0x05;
const JSVAL_TYPE_NULL: u64 = 0x06;
const JSVAL_TYPE_OBJECT: u64 = 0x07;
const JSVAL_TYPE_UNKNOWN: u64 = 0x20;

const JSVAL_TAG_SHIFT: int = 47;

//The following constants are totally broken on non-64bit platforms.
//See jsapi.h for the proper macro definitions.
const JSVAL_VOID: u64 = (JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNKNOWN) << JSVAL_TAG_SHIFT;
const JSVAL_NULL: u64 = (JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL) << JSVAL_TAG_SHIFT;
const JSVAL_ZERO: u64 = (JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32) << JSVAL_TAG_SHIFT;
const JSVAL_ONE: u64 = ((JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32) << JSVAL_TAG_SHIFT) | 1;
const JSVAL_FALSE: u64 = (JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN) << JSVAL_TAG_SHIFT;
const JSVAL_TRUE: u64 = ((JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN) << JSVAL_TAG_SHIFT) | 1;

const JSPROP_ENUMERATE: c_uint = 0x01;
const JSPROP_READONLY: c_uint  = 0x02;
const JSPROP_SHARED: c_uint =    0x40;
const JSPROP_NATIVE_ACCESSORS: c_uint = 0x08;

const JSCLASS_RESERVED_SLOTS_SHIFT: c_uint = 8;
const JSCLASS_RESERVED_SLOTS_WIDTH: c_uint = 8;
const JSCLASS_RESERVED_SLOTS_MASK: c_uint = ((1 << JSCLASS_RESERVED_SLOTS_WIDTH) - 1);

const JSCLASS_HIGH_FLAGS_SHIFT: c_uint =
    JSCLASS_RESERVED_SLOTS_SHIFT + JSCLASS_RESERVED_SLOTS_WIDTH;
const JSCLASS_IS_GLOBAL: c_uint = (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1));

const JSCLASS_GLOBAL_SLOT_COUNT: c_uint = JSProto_LIMIT * 3 + 24;

pure fn JSCLASS_HAS_RESERVED_SLOTS(n: c_uint) -> c_uint {
    (n & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT
}

fn result(n: JSBool) -> Result<(),()> {
    if n != ERR {Ok(())} else {Err(())}
}
fn result_obj(o: jsobj) -> Result<jsobj, ()> {
    if o.ptr != null() {Ok(o)} else {Err(())}
}

type named_functions = @{
    names: ~[~str],
    funcs: ~[JSFunctionSpec]
};

#[inline(always)]
unsafe fn JS_ARGV(_cx: *JSContext, vp: *jsval) -> *jsval {
    ptr::offset(vp, 2u)
}

unsafe fn JS_SET_RVAL(_cx: *JSContext, vp: *jsval, v: jsval) {
    let vp: *mut jsval = unsafe::reinterpret_cast(&vp);
    *vp = v;
}

#[inline(always)]
unsafe fn JS_THIS_OBJECT(cx: *JSContext, vp: *jsval) -> *JSObject unsafe {
    let r = RUST_JSVAL_TO_OBJECT(
        if RUST_JSVAL_IS_PRIMITIVE(*ptr::offset(vp, 1)) == 0 {
            JS_ComputeThis(cx, vp)
        } else {
            *ptr::offset(vp, 1)
        });
    r
}

<|endoftext|>


<commit_before>use std::collections::HashMap;

pub fn frequency(input: &[&str], worker_count: i32) -> HashMap<char, u32> {
    unimplemented!(
        "Count the frequency of letters in the given input '{:?}'. Ensure that you are using {} to process the input.",
        input,
        match worker_count {
            1 => format!("1 worker"),
            _ => format!("{} workers", worker_count),
        }
    );
}
<commit_msg>parallel-letter-frequency: Using usize as the input and output types<commit_after>use std::collections::HashMap;

pub fn frequency(input: &[&str], worker_count: usize) -> HashMap<char, usize> {
    unimplemented!(
        "Count the frequency of letters in the given input '{:?}'. Ensure that you are using {} to process the input.",
        input,
        match worker_count {
            1 => format!("1 worker"),
            _ => format!("{} workers", worker_count),
        }
    );
}
<|endoftext|>