{"action":"created","comment":{"url":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/comments/169654733","pull_request_review_id":98214746,"id":169654733,"diff_hunk":"@@ -0,0 +1,308 @@\n+// Copyright 2018 The Servo Project Developers. See the COPYRIGHT\n+// file at the top-level directory of this distribution.\n+//\n+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\n+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\n+// option. This file may not be copied, modified, or distributed\n+// except according to those terms.\n+\n+use std;\n+use sys;\n+\n+use {Direction, Language};\n+\n+/// A series of Unicode characters.\n+///\n+/// ## Adding Text\n+///\n+/// Since in Rust, a value of type `&str` must contain valid UTF-8\n+/// text, adding text to a `Buffer` is simple:\n+///\n+/// ```\n+/// # use harfbuzz::Buffer;\n+/// let mut b = Buffer::new();\n+/// b.add_str(\"Hello World\");\n+/// assert_eq!(b.is_empty(), false);\n+/// ```\n+///\n+/// or, more simply:\n+///\n+/// ```\n+/// # use harfbuzz::Buffer;\n+/// let b = Buffer::with(\"Hello World\");\n+/// assert_eq!(b.is_empty(), false);\n+/// ```\n+///\n+/// ## Segment Properties\n+///\n+/// In addition to the text itself, there are three important properties\n+/// that influence how a piece of text is shaped:\n+///\n+/// * Direction: The direction in which the output glyphs flow. This is\n+///   typically left to right or right to left. This is controlled via\n+///   the [`set_direction`] method on `Buffer`.\n+/// * Script: Script is crucial for choosing the proper shaping behaviour\n+///   for scripts that require it (e.g. Arabic) and the which OpenType\n+///   features defined in the font to be applied. This is controlled via\n+///   the [`set_script`] method on `Buffer`.\n+/// * Language: Languages are crucial for selecting which OpenType feature\n+///   to apply to the buffer which can result in applying language-specific\n+///   behaviour. Languages are orthogonal to the scripts, and though they\n+///   are related, they are different concepts and should not be confused\n+///   with each other. This is controlled via the [`set_language`] method\n+///   on `Buffer`.\n+///\n+/// Additionally, Harfbuzz can attempt to infer the values for these\n+/// properties using the [`guess_segment_properties`] method on `Buffer`:\n+///\n+/// ```\n+/// # use harfbuzz::{Buffer, Direction, sys};\n+/// let mut b = Buffer::with(\"مساء الخير\");\n+/// b.guess_segment_properties();\n+/// assert_eq!(b.get_direction(), Direction::RTL);\n+/// assert_eq!(b.get_script(), sys::HB_SCRIPT_ARABIC);\n+/// ```\n+///\n+/// [`set_direction`]: #method.set_direction\n+/// [`set_script`]: #method.set_script\n+/// [`set_language`]: #method.set_language\n+/// [`guess_segment_properties`]: #method.guess_segment_properties\n+pub struct Buffer {\n+    /// The underlying `hb_buffer_t` from the `harfbuzz-sys` crate.\n+    ///\n+    /// This isn't commonly needed unless interfacing directly with\n+    /// functions from the `harfbuzz-sys` crate that haven't been\n+    /// safely exposed.\n+    pub raw: *mut sys::hb_buffer_t,\n+}\n+\n+impl Buffer {\n+    /// Create a new, empty buffer.\n+    ///\n+    /// ```\n+    /// # use harfbuzz::Buffer;\n+    /// let b = Buffer::new();\n+    /// assert!(b.is_empty());\n+    /// ```\n+    pub fn new() -> Self {\n+        Buffer::default()\n+    }\n+\n+    /// Create a new buffer with the given text.\n+    pub fn with(text: &str) -> Self {\n+        let mut b = Buffer::new();\n+        b.add_str(text);\n+        b\n+    }\n+\n+    /// Create a new, empty buffer with the specified capacity.\n+    pub fn with_capacity(capacity: usize) -> Self {\n+        let mut b = Buffer::default();\n+        b.reserve(capacity);\n+        b\n+    }\n+\n+    /// Add UTF-8 encoded text to the buffer.\n+    pub fn add_str(&mut self, text: &str) {\n+        unsafe {\n+            sys::hb_buffer_add_utf8(\n+                self.raw,\n+                text.as_ptr() as *const std::os::raw::c_char,\n+                text.len() as std::os::raw::c_int,\n+                0,\n+                text.len() as std::os::raw::c_int,","path":"harfbuzz/src/buffer.rs","position":114,"original_position":114,"commit_id":"d48c9a8861b834efb7e06af2133111ca1cb9ca86","original_commit_id":"d48c9a8861b834efb7e06af2133111ca1cb9ca86","user":{"login":"khaledhosny","id":93914,"avatar_url":"https://avatars0.githubusercontent.com/u/93914?v=4","gravatar_id":"","url":"https://api.github.com/users/khaledhosny","html_url":"https://github.com/khaledhosny","followers_url":"https://api.github.com/users/khaledhosny/followers","following_url":"https://api.github.com/users/khaledhosny/following{/other_user}","gists_url":"https://api.github.com/users/khaledhosny/gists{/gist_id}","starred_url":"https://api.github.com/users/khaledhosny/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/khaledhosny/subscriptions","organizations_url":"https://api.github.com/users/khaledhosny/orgs","repos_url":"https://api.github.com/users/khaledhosny/repos","events_url":"https://api.github.com/users/khaledhosny/events{/privacy}","received_events_url":"https://api.github.com/users/khaledhosny/received_events","type":"User","site_admin":false},"body":"I don’t speak rust, but someway to expose this should be fine I think.","created_at":"2018-02-21T14:33:53Z","updated_at":"2018-02-21T14:33:53Z","html_url":"https://github.com/servo/rust-harfbuzz/pull/105#discussion_r169654733","pull_request_url":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/105","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/comments/169654733"},"html":{"href":"https://github.com/servo/rust-harfbuzz/pull/105#discussion_r169654733"},"pull_request":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/105"}},"in_reply_to_id":169482849},"pull_request":{"url":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/105","id":170154996,"html_url":"https://github.com/servo/rust-harfbuzz/pull/105","diff_url":"https://github.com/servo/rust-harfbuzz/pull/105.diff","patch_url":"https://github.com/servo/rust-harfbuzz/pull/105.patch","issue_url":"https://api.github.com/repos/servo/rust-harfbuzz/issues/105","number":105,"state":"open","locked":false,"title":"Add a new safe harfbuzz crate.","user":{"login":"waywardmonkeys","id":178582,"avatar_url":"https://avatars3.githubusercontent.com/u/178582?v=4","gravatar_id":"","url":"https://api.github.com/users/waywardmonkeys","html_url":"https://github.com/waywardmonkeys","followers_url":"https://api.github.com/users/waywardmonkeys/followers","following_url":"https://api.github.com/users/waywardmonkeys/following{/other_user}","gists_url":"https://api.github.com/users/waywardmonkeys/gists{/gist_id}","starred_url":"https://api.github.com/users/waywardmonkeys/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waywardmonkeys/subscriptions","organizations_url":"https://api.github.com/users/waywardmonkeys/orgs","repos_url":"https://api.github.com/users/waywardmonkeys/repos","events_url":"https://api.github.com/users/waywardmonkeys/events{/privacy}","received_events_url":"https://api.github.com/users/waywardmonkeys/received_events","type":"User","site_admin":false},"body":"There is an orphaned crate, https://crates.io/crates/harfbuzz. This was previously published by the Servo project, but now the Servo project really only maintains `harfbuzz-sys` which doesn't present a safe API.\r\n\r\nThis is proposing adding back a `harfbuzz` crate that could be used by Servo and other projects, but would be safe and have somewhat better ergonomics.\r\n\r\nThis also would address my question from issue #90 about using `enum` and bit flags.\r\n\r\nThoughts?\n\n<!-- Reviewable:start -->\n---\nThis change is [<img src=\"https://reviewable.io/review_button.svg\" height=\"34\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/servo/rust-harfbuzz/105)\n<!-- Reviewable:end -->\n","created_at":"2018-02-20T10:40:25Z","updated_at":"2018-02-21T14:33:53Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b56907152af89c6053de2eac4501cb326f78a47b","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/105/commits","review_comments_url":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/105/comments","review_comment_url":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/comments{/number}","comments_url":"https://api.github.com/repos/servo/rust-harfbuzz/issues/105/comments","statuses_url":"https://api.github.com/repos/servo/rust-harfbuzz/statuses/d48c9a8861b834efb7e06af2133111ca1cb9ca86","head":{"label":"waywardmonkeys:harfbuzz-crate","ref":"harfbuzz-crate","sha":"d48c9a8861b834efb7e06af2133111ca1cb9ca86","user":{"login":"waywardmonkeys","id":178582,"avatar_url":"https://avatars3.githubusercontent.com/u/178582?v=4","gravatar_id":"","url":"https://api.github.com/users/waywardmonkeys","html_url":"https://github.com/waywardmonkeys","followers_url":"https://api.github.com/users/waywardmonkeys/followers","following_url":"https://api.github.com/users/waywardmonkeys/following{/other_user}","gists_url":"https://api.github.com/users/waywardmonkeys/gists{/gist_id}","starred_url":"https://api.github.com/users/waywardmonkeys/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waywardmonkeys/subscriptions","organizations_url":"https://api.github.com/users/waywardmonkeys/orgs","repos_url":"https://api.github.com/users/waywardmonkeys/repos","events_url":"https://api.github.com/users/waywardmonkeys/events{/privacy}","received_events_url":"https://api.github.com/users/waywardmonkeys/received_events","type":"User","site_admin":false},"repo":{"id":114468927,"name":"rust-harfbuzz","full_name":"waywardmonkeys/rust-harfbuzz","owner":{"login":"waywardmonkeys","id":178582,"avatar_url":"https://avatars3.githubusercontent.com/u/178582?v=4","gravatar_id":"","url":"https://api.github.com/users/waywardmonkeys","html_url":"https://github.com/waywardmonkeys","followers_url":"https://api.github.com/users/waywardmonkeys/followers","following_url":"https://api.github.com/users/waywardmonkeys/following{/other_user}","gists_url":"https://api.github.com/users/waywardmonkeys/gists{/gist_id}","starred_url":"https://api.github.com/users/waywardmonkeys/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/waywardmonkeys/subscriptions","organizations_url":"https://api.github.com/users/waywardmonkeys/orgs","repos_url":"https://api.github.com/users/waywardmonkeys/repos","events_url":"https://api.github.com/users/waywardmonkeys/events{/privacy}","received_events_url":"https://api.github.com/users/waywardmonkeys/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/waywardmonkeys/rust-harfbuzz","description":"Rust bindings to HarfBuzz","fork":true,"url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz","forks_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/forks","keys_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/keys{/key_id}","collaborators_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/teams","hooks_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/hooks","issue_events_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/issues/events{/number}","events_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/events","assignees_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/assignees{/user}","branches_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/branches{/branch}","tags_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/tags","blobs_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/git/refs{/sha}","trees_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/git/trees{/sha}","statuses_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/statuses/{sha}","languages_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/languages","stargazers_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/stargazers","contributors_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/contributors","subscribers_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/subscribers","subscription_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/subscription","commits_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/commits{/sha}","git_commits_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/git/commits{/sha}","comments_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/comments{/number}","issue_comment_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/issues/comments{/number}","contents_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/contents/{+path}","compare_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/compare/{base}...{head}","merges_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/merges","archive_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/downloads","issues_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/issues{/number}","pulls_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/pulls{/number}","milestones_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/milestones{/number}","notifications_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/labels{/name}","releases_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/releases{/id}","deployments_url":"https://api.github.com/repos/waywardmonkeys/rust-harfbuzz/deployments","created_at":"2017-12-16T15:04:11Z","updated_at":"2017-12-16T15:04:14Z","pushed_at":"2018-02-20T10:36:57Z","git_url":"git://github.com/waywardmonkeys/rust-harfbuzz.git","ssh_url":"git@github.com:waywardmonkeys/rust-harfbuzz.git","clone_url":"https://github.com/waywardmonkeys/rust-harfbuzz.git","svn_url":"https://github.com/waywardmonkeys/rust-harfbuzz","homepage":"","size":3892,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"servo:master","ref":"master","sha":"d812e1978721112fa21e6eb0710129501b4c0ab5","user":{"login":"servo","id":2566135,"avatar_url":"https://avatars1.githubusercontent.com/u/2566135?v=4","gravatar_id":"","url":"https://api.github.com/users/servo","html_url":"https://github.com/servo","followers_url":"https://api.github.com/users/servo/followers","following_url":"https://api.github.com/users/servo/following{/other_user}","gists_url":"https://api.github.com/users/servo/gists{/gist_id}","starred_url":"https://api.github.com/users/servo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/servo/subscriptions","organizations_url":"https://api.github.com/users/servo/orgs","repos_url":"https://api.github.com/users/servo/repos","events_url":"https://api.github.com/users/servo/events{/privacy}","received_events_url":"https://api.github.com/users/servo/received_events","type":"Organization","site_admin":false},"repo":{"id":4301795,"name":"rust-harfbuzz","full_name":"servo/rust-harfbuzz","owner":{"login":"servo","id":2566135,"avatar_url":"https://avatars1.githubusercontent.com/u/2566135?v=4","gravatar_id":"","url":"https://api.github.com/users/servo","html_url":"https://github.com/servo","followers_url":"https://api.github.com/users/servo/followers","following_url":"https://api.github.com/users/servo/following{/other_user}","gists_url":"https://api.github.com/users/servo/gists{/gist_id}","starred_url":"https://api.github.com/users/servo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/servo/subscriptions","organizations_url":"https://api.github.com/users/servo/orgs","repos_url":"https://api.github.com/users/servo/repos","events_url":"https://api.github.com/users/servo/events{/privacy}","received_events_url":"https://api.github.com/users/servo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/servo/rust-harfbuzz","description":"Rust bindings to HarfBuzz","fork":false,"url":"https://api.github.com/repos/servo/rust-harfbuzz","forks_url":"https://api.github.com/repos/servo/rust-harfbuzz/forks","keys_url":"https://api.github.com/repos/servo/rust-harfbuzz/keys{/key_id}","collaborators_url":"https://api.github.com/repos/servo/rust-harfbuzz/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/servo/rust-harfbuzz/teams","hooks_url":"https://api.github.com/repos/servo/rust-harfbuzz/hooks","issue_events_url":"https://api.github.com/repos/servo/rust-harfbuzz/issues/events{/number}","events_url":"https://api.github.com/repos/servo/rust-harfbuzz/events","assignees_url":"https://api.github.com/repos/servo/rust-harfbuzz/assignees{/user}","branches_url":"https://api.github.com/repos/servo/rust-harfbuzz/branches{/branch}","tags_url":"https://api.github.com/repos/servo/rust-harfbuzz/tags","blobs_url":"https://api.github.com/repos/servo/rust-harfbuzz/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/servo/rust-harfbuzz/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/servo/rust-harfbuzz/git/refs{/sha}","trees_url":"https://api.github.com/repos/servo/rust-harfbuzz/git/trees{/sha}","statuses_url":"https://api.github.com/repos/servo/rust-harfbuzz/statuses/{sha}","languages_url":"https://api.github.com/repos/servo/rust-harfbuzz/languages","stargazers_url":"https://api.github.com/repos/servo/rust-harfbuzz/stargazers","contributors_url":"https://api.github.com/repos/servo/rust-harfbuzz/contributors","subscribers_url":"https://api.github.com/repos/servo/rust-harfbuzz/subscribers","subscription_url":"https://api.github.com/repos/servo/rust-harfbuzz/subscription","commits_url":"https://api.github.com/repos/servo/rust-harfbuzz/commits{/sha}","git_commits_url":"https://api.github.com/repos/servo/rust-harfbuzz/git/commits{/sha}","comments_url":"https://api.github.com/repos/servo/rust-harfbuzz/comments{/number}","issue_comment_url":"https://api.github.com/repos/servo/rust-harfbuzz/issues/comments{/number}","contents_url":"https://api.github.com/repos/servo/rust-harfbuzz/contents/{+path}","compare_url":"https://api.github.com/repos/servo/rust-harfbuzz/compare/{base}...{head}","merges_url":"https://api.github.com/repos/servo/rust-harfbuzz/merges","archive_url":"https://api.github.com/repos/servo/rust-harfbuzz/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/servo/rust-harfbuzz/downloads","issues_url":"https://api.github.com/repos/servo/rust-harfbuzz/issues{/number}","pulls_url":"https://api.github.com/repos/servo/rust-harfbuzz/pulls{/number}","milestones_url":"https://api.github.com/repos/servo/rust-harfbuzz/milestones{/number}","notifications_url":"https://api.github.com/repos/servo/rust-harfbuzz/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/servo/rust-harfbuzz/labels{/name}","releases_url":"https://api.github.com/repos/servo/rust-harfbuzz/releases{/id}","deployments_url":"https://api.github.com/repos/servo/rust-harfbuzz/deployments","created_at":"2012-05-11T21:13:40Z","updated_at":"2018-02-10T22:12:27Z","pushed_at":"2018-02-20T10:40:30Z","git_url":"git://github.com/servo/rust-harfbuzz.git","ssh_url":"git@github.com:servo/rust-harfbuzz.git","clone_url":"https://github.com/servo/rust-harfbuzz.git","svn_url":"https://github.com/servo/rust-harfbuzz","homepage":"","size":3900,"stargazers_count":17,"watchers_count":17,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":36,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":36,"open_issues":5,"watchers":17,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/105"},"html":{"href":"https://github.com/servo/rust-harfbuzz/pull/105"},"issue":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/issues/105"},"comments":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/issues/105/comments"},"review_comments":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/105/comments"},"review_comment":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/pulls/105/commits"},"statuses":{"href":"https://api.github.com/repos/servo/rust-harfbuzz/statuses/d48c9a8861b834efb7e06af2133111ca1cb9ca86"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"khaledhosny"}}