Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Rust + Ruby/mruby
Search
Gosuke Miyashita
November 25, 2017
Technology
1.9k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Rust + Ruby/mruby
Gosuke Miyashita
November 25, 2017
More Decks by Gosuke Miyashita
See All by Gosuke Miyashita
なぜインフラコードのモジュール化は難しいのか - アプリケーションコードとの本質的な違いから考える
mizzy
76
41k
Serverspec(をつくった自分)のそれまでとその後
mizzy
9
3.4k
A method for separating policy definition and behavior control by an intermediate language to achieve optimal server configuration management according to the situation
mizzy
3
330
Past and future of Infrastructure as Code
mizzy
0
410
Configuration Managementツールのポリシー定義用中間言語に関する考察/Considerations about an intermediate language of configuration management tools
mizzy
0
550
Infrastructure as Codeのこれまでとこれから/Infra Study Meetup #1
mizzy
28
13k
エンジニアかつ研究者としての今後のキャリアについて/My Career As An Engineer And A Researcher
mizzy
0
470
Compare OCI Runtimes
mizzy
2
1.7k
Serverspec and OSS at IEICE Society Conference 2018
mizzy
2
410
Other Decks in Technology
See All in Technology
クラウドサインを止めずに Nuxt へ 次の10年のために先に決めたこと
bengo4com
1
160
(swiftc) NonCopyableとライフタイム修飾子
teamhimeh
0
140
AI秘書と毎日働くのはもう当たり前。開発以外の業務に足りない機能をどう埋める?
minorun365
PRO
4
1.8k
E2Eってつらくないですか?E2Eの管理コストを下げる手段とその実践
akaboshinit
5
2.2k
なぜAI時代に技術記事を書くのか?どう書くのか? 〜bunの場合〜
kworkdev
PRO
0
150
Deep Data Security 機能解説
oracle4engineer
PRO
3
950
AIで選択肢が広がった組織設計の理想と現実
konifar
14
6.3k
データマネジメント × 法務で作りあげる、 freeeの新しいデータガバナンスへの軌跡
freee
PRO
2
480
「作れる」と「リリースできる」の間にあったもの── PdMを外して見えた、PdMがやるべき仕事/Buildable ≠ Shippable: What Removing the PM Taught Me About the PM’s Job
yappli_developers
0
310
日本AIベンチャーレポート2026
kentarofujii
0
250
Vue.jsのGitHubから学ぶ意思決定
yut0naga1_fa
1
310
AWSDirectConnectの構築の進め方を整理してみた
masa_my
1
200
Featured
See All Featured
Docker and Python
trallard
47
4.2k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
WCS-LA-2024
lcolladotor
0
920
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
510
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.6k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
350
A better future with KSS
kneath
240
18k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
550
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3.2k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
3
3.9k
Transcript
RustͰॻ͍ͨϥΠϒϥϦ ΛRuby/mruby͔Βݺ ͼग़࣮͢ફతͳํ๏ ԬRubyձٞ02 1
ࣗݾհ • ٶԼ ߶ี • ߹ಉձࣾServerspec Operationsද • ϑϦʔϥϯεͷιϑτΣΞΤϯδχΞ •
http://mizzy.org/ • mizzy@github, gosukenator@twitter ԬRubyձٞ02 2
ஶॻɾ༁ॻ ԬRubyձٞ02 3
ࠓͷൃදʹࢸΔܦҢ • libspecinfraͱ͍͏OSSϓϩδΣΫτΛ͍ͬͯΔ • ͜ͷϓϩδΣΫτҎԼͷߏཁૉΛ࣋ͭ • RustͰ࣮ͨ͠ڞ༗ϥΠϒϥϦ • ڞ༗ϥΠϒϥϦΛར༻͢ΔͨΊͷ֤छݴޠόΠϯσΟϯά ԬRubyձٞ02
4
ࠓͷൃදʹࢸΔܦҢʢ͖ͭͮʣ • Ruby/mrubyόΠϯσΟϯάΛ։ൃ͢ΔͨΊͷํ๏Λௐͨ • ॳาతͳใͨ͘͞Μ͋Δ͕࣮ફతͳใҊ֎গͳ͍ • ৭ʑࢼߦࡨޡͨ͠ͷͰ·ͱΊ͓ͯ͜͏ͱࢥͬͨ • ؒҧ͍ΑΓྑ͍Γํ͕͋Εࣝऀ͕ࢦఠͯ͘͠Εͦ͏ •
ٱʑʹԬʹߦ͘ޱ࣮͕ཉ͔ͬͨ͠ ԬRubyձٞ02 5
ΞδΣϯμ • RustͱFFI • ೖRust + Ruby/mruby • ࣮ફRust +
Ruby/mruby • libspecinfraϓϩδΣΫτͷ֓ཁʢ͕࣌ؒ͋Εʣ • ※Rustͷݴޠ༷తͳ͠·ͤΜ ԬRubyձٞ02 6
RustͱFFI ԬRubyձٞ02 7
FFIͱ • Foreign Function Interface • ͋Δϓϩάϥϛϯάݴޠ͔ΒଞͷϓϩάϥϛϯάݴޠͰఆٛ ͞ΕͨؔͳͲΛར༻͢ΔͨΊͷػߏ • RustɺRubyɺmrubyʹݶΒͳ͍
ԬRubyձٞ02 8
RustͱFFI • RustʹFFI͕Έࠐ·Ε͓ͯΓެࣜυΩϡϝϯτ͋Δ • ओͳػೳେ͖͘2ͭ • ଞݴޠͰॻ͔ΕͨϥΠϒϥϦͷؔΛݺͿػೳ • ଞݴޠʢओʹCʣ͔ΒؔΛݺΔΑ͏ʹ͢Δػೳ ԬRubyձٞ02
9
ଞݴޠͰॻ͔ΕͨϥΠϒϥϦؔΛݺͿ #[link(name = "snappy")] extern { fn snappy_max_compressed_length(source_length: size_t) ->
size_t; } fn main() { let x = unsafe { snappy_max_compressed_length(100) }; println!("max compressed length of a 100 byte buffer: {}", x); } https://doc.rust-lang.org/book/first-edition/ffi.html#calling- foreign-functions ԬRubyձٞ02 10
ଞݴޠ͔ΒؔΛݺΔΑ͏ʹ͢Δ #[no_mangle] pub extern "C" fn hello_rust() -> *const u8
{ "Hello, world!\0".as_ptr() } https://doc.rust-lang.org/book/first-edition/ffi.html#calling-rust- code-from-c ԬRubyձٞ02 11
hello_rust()ΛC͔Βݺͼग़͢ #include <stdio.h> extern char *hello_rust(void); int main() { printf("%s\n",
hello_rust()); } cc hello.c -L. -lhello LD_LIBRARY_PATH=. ./a.out Hello, world! ԬRubyձٞ02 12
RustͱFFI·ͱΊ • FFI = Foreign Function Interface • ͋Δϓϩάϥϛϯάݴޠ͔ΒଞͷϓϩάϥϛϯάݴޠͰఆٛ ͞ΕͨؔͳͲΛར༻͢ΔͨΊͷػߏ
• RustʹFFI͕Έࠐ·Ε͍ͯͯɺଞͷݴޠͰॻ͔ΕͨϥΠϒ ϥϦͷؔΛݺͼग़ͨ͠Γɺଞͷݴޠ͔ΒRustͰॻ͍ͨϥΠ ϒϥϦͷؔΛݺͼग़ͨ͠ΓͰ͖Δ ԬRubyձٞ02 13
ೖRust + Ruby/mruby ԬRubyձٞ02 14
RustͰॻ͔ΕͨϥΠϒϥϦΛͲ͏ݺͿ͔ • Ruby • native extension • ffi gemΛར༻ͯ͠libffiܦ༝Ͱݺͼग़͢ •
mruby • CͰ֦ு(mrbgem)Λॻ͘ ԬRubyձٞ02 15
ೖRust + Ruby/mruby • RustͱRuby/mrubyΛͲ͏ܨ͙͔۩ମతͳίʔυͰࣔ͠·͢ • ͕ࣗlibspecinfraͷόΠϯσΟϯά։ൃͷͨΊʹֶΜͩͷͱಉ͡εςοϓΛḷ ͬͯΈ·͢ • จࣈΛେ͖ͯ͘͠εϥΠυΛݟ͘͢͢ΔͨΊίʔυΛলུͨ͠Γਪ͞Εͳ
͍ॻ͖ํΛͯ͠Δ෦͋Γ·͢ • શͳίʔυGitHubʹஔ͍ͯ͋Γ·͢ • https://github.com/mizzy/fukuokark02_code_examples • εϥΠυͱඍົʹҧ͏෦͋Γ·͕͢ ԬRubyձٞ02 16
ԬRubyձٞ02 17
ͷ͠ࢉΛߦ͏Rustίʔυ extern crate libc; use libc::uint32_t; #[no_mangle] pub extern "C"
fn addition(a: uint32_t, b: uint32_t) -> uint32_t { a + b } ԬRubyձٞ02 18
RustͷؔΛݺͼग़͢Rubyίʔυ require 'ffi' module Integers extend FFI::Library ffi_lib 'addition' attach_function
:addition, [:uint32, :uint32], :uint32 end puts Integers.addition(1, 2) ԬRubyձٞ02 19
RustͷؔΛݺͼग़͢mrbgemίʔυ extern uint32_t addition(uint32_t, uint32_t); static mrb_value addition_(mrb_state *mrb, mrb_value
self) { mrb_int a, b; mrb_get_args(mrb, "ii", &a, &b); return mrb_fixnum_value(addition(a, b)); } void mrb_mruby_addition_gem_init(mrb_state *mrb) { struct RClass *i = mrb_define_module(mrb, "Integers"); mrb_define_class_method( mrb, i, "addition", addition_, MRB_ARGS_REQ(2) ); } ԬRubyձٞ02 20
mrbgemΛར༻ͨ͠mrubyίʔυ puts Integers.addition(1, 2) ԬRubyձٞ02 21
จࣈྻ ԬRubyձٞ02 22
จࣈྻʹ!!!ΛՃ͢ΔRustίʔυ pub extern "C" fn emphasize(ptr: *const c_char) -> *const
c_char { let s = unsafe { assert!(!ptr.is_null()); CStr::from_ptr(ptr) }.to_str().unwrap(); let str = s.to_owned() + "!!!"; CString::new(str).unwrap().into_raw() } ԬRubyձٞ02 23
RustͷؔΛݺͼग़͢Rubyίʔυ module Strings extend FFI::Library ffi_lib 'emphasize' attach_function :emphasize, [:string],
:string end puts Strings.emphasize("Hello") ԬRubyձٞ02 24
RustͷؔΛݺͼग़͢mrbgemίʔυ extern char *emphasize(char *); static mrb_value emphasize_(mrb_state *mrb, mrb_value
self) { char *arg, *ret; mrb_int len; mrb_value str; mrb_get_args(mrb, "s", &arg, &len); ret = emphasize(arg); str = mrb_str_buf_new(mrb, sizeof(ret)); return mrb_str_cat_cstr(mrb, str, ret); } ԬRubyձٞ02 25
mrbgemΛར༻ͨ͠mrubyίʔυ puts Strings.emphasize("Hello") ԬRubyձٞ02 26
ߏମ ԬRubyձٞ02 27
ߏମ • ͜Εলུ • ҰԠॻ͖͔͚ͷίʔυαϯϓϧϦϙδτϦʹ͋Γ·͢ • ҎԼͷهࣄ͕ࢀߟʹͳΓ·͢ • Ruby-FFIʹ͍ͭͯௐͯΈͨɻʢͦͷ2ʣ -
͍ͷ·ɻ • http://yamaimo.hatenablog.jp/entry/2015/05/22/200000 • mruby Ͱ C ݴޠͷߏମΛϥοϓͨ͠ΦϒδΣΫτΛ࡞Δਖ਼͍͠ํ๏ - Qiita • https://qiita.com/tsahara@github/items/86610a696f8ca792db45 ԬRubyձٞ02 28
ߏମ • ׂͱ໘͍͘͞ • RustଆͱRuby/mrubyͰಉ͡ߏମΛఆٛ͢Δඞཁ͕͋Δ • ߏମͷதRuby/mruby͔ΒݟΕͲ͏Ͱ͍͍ʢ͕ࣗ։ൃ͠ ͯΔlibspecinfraͰʣ • ΦϒδΣΫτͱͯ͠ѻ͍͍ͨ
• RustଆͷstructΛࣔ͢ϙΠϯλͱͦΕΛѻ͏͚ؔͩ͋ΕेͰ ʁ ԬRubyձٞ02 29
ೖRust + Ruby/mruby·ͱΊ • ҾͱฦΓɺจࣈྻҾͱฦΓΛѻ͏ίʔυྫΛࣔͨ͠ • ߏମʹ͍ͭͯɺlibspecinfra։ൃͷͨΊʹௐͯΔ్தͰɺ ͜ΕࣗͷΓ͍ͨ͜ͱͱҧ͏ɺͱࢥͬͨͷͰུ • ߏମ(Rustͷstruct)Λߏମͱͯ͠ѻ͍͍ͨͷͰͳ͘ɺΦϒδ
ΣΫτͱͯ͠ѻ͍͍ͨ • ͦͷΓํ࣍Ͱղઆ͠·͢ ԬRubyձٞ02 30
࣮ફRust + Ruby/mruby ԬRubyձٞ02 31
࣮ફRust + Ruby/mruby • ͔͜͜Β࣮ࡍͷlibspecinfraͷίʔυΛϕʔεͱͨ͠ղઆΛ ͠·͢ • શʹಉ͡ίʔυͰͳ͘؆ུԽͯ͋͠Γ·͢ • ͪ͜ΒͷίʔυGitHubʹ͋Γ·͢
• https://github.com/mizzy/fukuokark02_code_examples ԬRubyձٞ02 32
ΦϒδΣΫτ ԬRubyձٞ02 33
ΦϒδΣΫτΛѻ͏ίʔυ(Rust) ͜Μͳײ͡ͰϑΝΠϧͷύʔϛογϣϯΛऔಘ͍ͨ͠ let s = Specinfra::new(); let f = s.file("/etc/passwd");
println!("{:o}", f.mode()); ԬRubyձٞ02 34
SpecinfraΦϒδΣΫτͷఆٛ(Rust) pub struct Specinfra; impl Specinfra { pub fn new()
-> Specinfra { Specinfra } pub fn file(self, name: &str) -> File { File { name: name } } } ԬRubyձٞ02 35
FileΦϒδΣΫτͷఆٛ(Rust) pub struct File<'a> { name: &'a str, } impl<'a>
File<'a> { pub fn mode(self) -> i32 { // ύʔϛογϣϯΛऔಘͯ͠ฦ͢ॲཧ } } ԬRubyձٞ02 36
SpecinfraΦϒδΣΫτͷ֎෦༻ఆٛ(Rust) pub extern "C" fn specinfra_new() -> *const Specinfra {
let s = Specinfra::new(); Box::into_raw(Box::new(s)) } pub extern "C" fn specinfra_file<'a>(ptr: *const Specinfra, name: *const c_char) -> *const File<'a> { let s = unsafe { &*ptr }; let name = unsafe { CStr::from_ptr(name) }; Box::into_raw(Box::new(s.file(name.to_str().unwrap()))) } ԬRubyձٞ02 37
FileΦϒδΣΫτͷ֎෦༻ఆٛ(Rust) pub extern "C" fn file_mode(ptr: *const File) -> int32_t
{ let f = unsafe { assert!(!ptr.is_null()); &*ptr }; f.mode() } ԬRubyձٞ02 38
ΦϒδΣΫτ։์༻ͷؔ(Rust) pub extern "C" fn specinfra_free(ptr: *mut Specinfra) { unsafe
{ Box::from_raw(ptr); } } pub extern "C" fn file_free(ptr: *mut File) { unsafe { Box::from_raw(ptr); } } ԬRubyձٞ02 39
ΦϒδΣΫτΛѻ͏ίʔυ(Ruby) ͜Μͳײ͡ͰϑΝΠϧͷύʔϛογϣϯऔಘ͍ͨ͠ s = Specinfra::Binding.new f = s.file("/etc/passwd") printf("%#o\n", f.mode)
ԬRubyձٞ02 40
SpecinfraΦϒδΣΫτ(Ruby) class Specinfra < FFI::AutoPointer def self.release(ptr) Binding.free(ptr) end def
file(name) Binding.file(self, name) end module Binding attach_function :new, :specinfra_new, [], Specinfra attach_function :free, :specinfra_free, [Specinfra], :void attach_function :file, :specinfra_file, [Specinfra, :string], File end end ԬRubyձٞ02 41
FileΦϒδΣΫτ(Ruby) class File < FFI::AutoPointer def self.release(ptr) file_free(ptr) end def
mode() file_mode(self) end attach_function :file_free, [File], :void attach_function :file_mode, [File], :int end ԬRubyձٞ02 42
ΦϒδΣΫτΛѻ͏ίʔυ(mruby) ͜Μͳײ͡ͰϑΝΠϧͷύʔϛογϣϯऔಘ͍ͨ͠ s = Specinfra.new f = s.file("/etc/passwd") printf("%#o\n", f.mode)
ԬRubyձٞ02 43
FileΦϒδΣΫτؔ࿈ఆٛ(mrbgem) typedef int file; extern int file_mode(file *); extern void
file_free(file *); struct mrb_data_type mrb_file_type = { "File", mrb_file_free }; ԬRubyձٞ02 44
SpecinfraΦϒδΣΫτؔ࿈ఆٛ(mrbgem) typedef int specinfra; extern specinfra *specinfra_new(void); extern file *specinfra_file(specinfra
*, char *); extern void specinfra_free(specinfra *); struct mrb_data_type mrb_specinfra_type = { "Specinfra", mrb_specinfra_free }; ԬRubyձٞ02 45
Specinfra.new(mrbgem) mrb_value specinfra_new_(mrb_state *mrb, mrb_value self) { specinfra *s =
specinfra_new(); DATA_TYPE(self) = &mrb_specinfra_type; DATA_PTR(self) = s; return self; } ԬRubyձٞ02 46
Specinfra#file(mrbgem) mrb_value specinfra_file_(mrb_state *mrb, mrb_value self) { mrb_value v; mrb_get_args(mrb,
"S", &v); char *name = mrb_str_to_cstr(mrb, v); file *f = specinfra_file(DATA_PTR(self), name); struct RClass file_class = mrb_class_get(mrb, "File"); mrb_value file_object = mrb_obj_new(mrb, file_class, 0, NULL); DATA_TYPE(file_object) = &mrb_file_type; DATA_PTR(file_object) = f; return file_object; } ԬRubyձٞ02 47
SpecinfraΦϒδΣΫτ։์༻ؔ(mrbgem) void mrb_specinfra_free(mrb_state *mrb, void *ptr) { specinfra_free(ptr); } ԬRubyձٞ02
48
File#mode(mrbgem) mrb_value file_mode_(mrb_state *mrb, mrb_value self) { file *f; int
m; f = DATA_PTR(self); m = file_mode(f); return mrb_fixnum_value(m); } ԬRubyձٞ02 49
FileΦϒδΣΫτ։์༻ؔ(mrbgem) void mrb_file_free(mrb_state *mrb, void *ptr) { file_free(ptr); } ԬRubyձٞ02
50
ॳظԽ(mrbgem) void mrb_mruby_object_gem_init(mrb_state *mrb) { struct RClass *s = mrb_define_class(mrb,
"Specinfra", mrb->object_class); mrb_define_method(mrb, s, "initialize", specinfra_new_, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "file", specinfra_file_, MRB_ARGS_REQ(1)); struct RClass *f = mrb_define_class(mrb, "File", mrb->object_class); mrb_define_method(mrb, f, "mode", file_mode_, MRB_ARGS_NONE()); } ԬRubyձٞ02 51
τϨΠτ ԬRubyձٞ02 52
τϨΠτΛѻ͏ίʔυ(Rust) ͜Μͳײ͡ͰBackendτϨΠτΛ࣮ͨ͠DirectΦϒδΣΫτΛ ͍ͨ͠ let b = Direct::new(); let s =
Specinfra::new(b); ԬRubyձٞ02 53
SpecinfraΦϒδΣΫτͷमਖ਼(Rust) pub struct Specinfra<'a> { backend: &'a Backend, } impl<'a>
Specinfra<'a> { pub fn new(b: &Backend) -> Specinfra { b.detect_platform(); Specinfra { backend: b } } ... ԬRubyձٞ02 54
BackendτϨΠτͷఆٛͱ࣮(Rust) pub trait Backend { fn detect_platform(&self) -> &str; }
pub struct Direct; impl Backend for Direct { fn detect_platform(&self) -> &str { // ϓϥοτϑΥʔϜผॲཧ } } ԬRubyձٞ02 55
SpecinfraΦϒδΣΫτͷ֎෦༻ఆٛ(Rust) ҾͰτϨΠτΛड͚औΔΑ͏ʹ͍ͯ͠Δͱ… pub extern "C" fn specinfra_new<'a>(ptr: *const Backend) ->
*const Specinfra<'a> { let b = unsafe { &*ptr }; let s = Specinfra::new(b); // ͜ͷॲཧதͷ… Box::into_raw(Box::new(s)) } ԬRubyձٞ02 56
ηάϑΥ…(Rust) impl<'a> Specinfra<'a> { pub fn new(b: &Backend) -> Specinfra
{ b.detect_platform(); // ͜͜ͰηάϑΥ͢Δ Specinfra { backend: b } } ԬRubyձٞ02 57
BackendWrapper structͷಋೖ(Rust) τϨΠτҾͰͣ͞BackendWrapperͰ͘ΔΉ pub struct BackendWrapper(pub Box<Backend>); pub extern "C"
fn specinfra_new<'a>(ptr: *const BackendWrapper) -> *const Specinfra<'a> { let b = unsafe { &*ptr }; let s = Specinfra::new(&*b.0); Box::into_raw(Box::new(s)) } ԬRubyձٞ02 58
DirectΦϒδΣΫτͷ֎෦༻ఆٛ(Rust) pub extern "C" fn direct_new() -> *const Direct {
let d = Direct::new(); Box::into_raw(Box::new(d)) } ΛҎԼͷΑ͏ʹ͢Δ pub extern "C" fn direct_new() -> *const BackendWrapper { let d = Direct::new(); let b = BackendWrapper(Box::new(d)); Box::into_raw(Box::new(b)) } ԬRubyձٞ02 59
τϨΠτΛѻ͏ίʔυ(Ruby) ͜͏ॻ͖͍ͨ b = Direct::Binding.new s = Specinfra::Binding.new(b) f =
s.file("/etc/passwd") printf("%#o\n", f.mode) ԬRubyձٞ02 60
DirectΦϒδΣΫτͷఆٛ(Ruby) class Direct < FFI::AutoPointer def self.release(ptr) Binding.free(ptr) end module
Binding attach_function :free, :direct_free, [Direct], :void attach_function :new, :direct_new, [], Direct end end ԬRubyձٞ02 61
SpecinfraΦϒδΣΫτͷमਖ਼(Ruby) class Specinfra < FFI::AutoPointer ... module Binding ... attach_function
:new, :specinfra_new, [:pointer], Specinfra ... end end ԬRubyձٞ02 62
τϨΠτΛѻ͏ίʔυ(mruby) ͜͏ॻ͖͍ͨ b = Direct.new s = Specinfra.new(b) f =
s.file("/etc/passwd") printf("%#o\n", f.mode) ԬRubyձٞ02 63
τϨΠτؔ࿈ఆٛ(mrbgem) typedef int backend; extern specinfra *specinfra_new(backend *); extern backend
*direct_new(void); struct mrb_data_type mrb_direct_type = { "Direct", mrb_free }; ԬRubyձٞ02 64
Direct.new(mrbgem) mrb_value direct_new_(mrb_state *mrb, mrb_value self) { backend *b; b
= direct_new(); DATA_TYPE(self) = &mrb_direct_type; DATA_PTR(self) = b; return self; } ԬRubyձٞ02 65
Specinfra.newͷमਖ਼(mrbgem) mrb_value specinfra_new_(mrb_state *mrb, mrb_value self) { mrb_value b; mrb_get_args(mrb,
"o", &b); specinfra *s = specinfra_new(DATA_PTR(b)); DATA_TYPE(self) = &mrb_specinfra_type; DATA_PTR(self) = s; return self; } ԬRubyձٞ02 66
ॳظԽ(mrbgem) void mrb_mruby_trait_gem_init(mrb_state *mrb) { ... s = mrb_define_class(mrb, "Specinfra",
mrb->object_class); mrb_define_method(mrb, s, "initialize", new, MRB_ARGS_REQ(1)); ... struct RClass *d = mrb_define_class(mrb, "Direct", mrb->object_class); mrb_define_method(mrb, d, "initialize", direct_new_, MRB_ARGS_NONE()); } ԬRubyձٞ02 67
Τϥʔ ԬRubyձٞ02 68
Τϥʔॲཧ • RustଆͰൃੜͨ͠ΤϥʔΛ֎෦ݴޠʹͲ͏͑Δͷ͔ɺΛࣗ ͳΓʹߟ͑ͯΈͨ • ͬͱ͍͍ํ๏͋Εڭ͍͑ͯͩ͘͞ ԬRubyձٞ02 69
ΤϥʔΛൃੜͤ͞Δίʔυ(Rust) ύʔϛογϣϯऔಘ࣌ʹΤϥʔ͕ൃੜ͢Δ͜ͱΛఆ pub struct File<'a> { name: &'a str, error:
&'a str, } impl<'a> File<'a> { pub fn mode(self) -> Result<i32, &'a str> { // ύʔϛογϣϯΛऔಘͯ͠ฦ͢ॲཧΛೖΕΔ } } ԬRubyձٞ02 70
ύʔϛογϣϯऔಘؔͷ֎෦ఆٛΛमਖ਼(Rust) pub extern "C" fn file_mode(ptr: *mut File) -> int32_t
{ let f = unsafe { &mut *ptr }; match f.mode() { Ok(mode) => mode, Err(e) => { f.error = e; -1 } } } ԬRubyձٞ02 71
ΤϥʔϝοηʔδऔಘͷͨΊͷ֎෦༻ؔఆٛ(Rust) pub extern "C" fn file_error(ptr: *const File) -> *const
c_char { let f = unsafe { &*ptr }; CString::new(f.error).unwrap().into_raw() } ԬRubyձٞ02 72
Τϥʔॲཧ(Ruby) ͜͏ॲཧ͍ͨ͠ b = Direct::Binding.new s = Specinfra::Binding.new(b) f =
s.file("/etc/passwd") begin printf("%#o\n", f.mode) rescue => e puts e.message end ԬRubyձٞ02 73
File#modeΛमਖ਼(Ruby) class File < FFI::AutoPointer ... def mode() mode =
file_mode(self) if mode == -1 raise file_error(self) end mode end ... attach_function :file_error, [File], :string end ԬRubyձٞ02 74
Τϥʔॲཧ(mruby) ͜͏ॲཧ͍ͨ͠ b = Direct.new s = Specinfra.new(b) f =
s.file("/etc/passwd") begin printf("%#o\n", f.mode) rescue => e puts e.message end ԬRubyձٞ02 75
File#modeͷमਖ਼(mrbgem) mrb_value mode(mrb_state *mrb, mrb_value self) { file *f =
DATA_PTR(self); int m = file_mode(f); if (m < 0) { mrb_raise(mrb, E_RUNTIME_ERROR, file_error(f)); } else { return mrb_fixnum_value(m); } } ԬRubyձٞ02 76
࣮ફRust + Ruby/mruby·ͱΊ • ΦϒδΣΫτɺτϨΠτɺΤϥʔΛѻ͏ํ๏ʹ͍ͭͯղઆ͠ ͨ • ͜ͷลΓ͋·Γใ͕ͳ͘ɺࢼߦࡨޡͯ͠ḷΓண͍ͨΓํ ͳͷͰɺؒҧ͍͕͋ͬͨΓɺͬͱ͍͍Γํ͕͋Δ͔͠ Ε·ͤΜ
ԬRubyձٞ02 77
libspcinfraͱ ԬRubyձٞ02 78
libspecinfraͱ • SpecinfraͷRustʹΑΔ࠶࣮ϓϩδΣΫτ ԬRubyձٞ02 79
Specinfraͱ • Serverspec͔Βੜͨ͠ϥΠϒϥϦ • OS/σΟετϦϏϡʔγϣϯຖͷίϚϯυͷҧ͍ͷநԽ • ɺSSHܦ༝ɺDocker APIܦ༝ͳͲ࣮ߦܗࣜͷநԽ • ͜ΕΒͷநԽʹΑͬͯγεςϜཧܥπʔϧͷ։ൃΛࢧԉ
ԬRubyձٞ02 80
SpecinfraΛ༻͍ͨϓϩμΫτͷίʔυྫ ServerspecʹΑΔςετίʔυ set :backend, :exec describe package('nginx') do it {
should be_installed } end describe service('nginx') do it { should be_enabled } it { should be_running } end ԬRubyձٞ02 81
Specinfra͔Βlibspecinfra • SpecinfrarubygemͳͷͰଞͷݴޠ͔Β͑ͳ͍ • libpseicnraҎԼͷܗͰଟݴޠରԠΛࢦ͢ • ڞ༗ϥΠϒϥϦΛఏڙ • ֤छݴޠόΠϯσΟϯάఏڙ ԬRubyձٞ02
82
libspecinfraࢀߟࢿྉ • libspecinfra ϓϩδΣΫτͷ֓ཁͱࠓޙʹ͍ͭͯ | Advanced Technology Lab • http://atl.recruit-tech.co.jp/blog/4339/
• libspecinfra ։ൃऀ͚νϡʔτϦΞϧ | Advanced Technology Lab • http://atl.recruit-tech.co.jp/blog/4349/ • libspecinfraͷ֓ཁͱݱঢ়ͱࠓޙ • https://speakerdeck.com/mizzy/overview-of-libspecinfra-project ԬRubyձٞ02 83
ͳͥRust? • ڞ༗ϥΠϒϥϦΛఏڙͱ͍͏తͳΒCC++͕͋Δ • Ͱ৽نͰϓϩδΣΫτ͡ΊΔͳΒRust͔ͳɺͱ • Cݴޠͱͷੑʢ㲈ଞݴޠͱͷੑʣ • mrubylibffiͱܨ͍͗͢ •
RustΛ֮͑ͯΈ͔ͨͬͨ ԬRubyձٞ02 84
ଞݴޠ࿈ܞΛߟྀͨ͠Rustڞ༗ϥΠϒϥϦͷ։ൃํ 1. ॳظஈ֊Ͱଞݴޠ࿈ܞҰߟྀͤͣɺRust୯ମͰ͏ϥΠϒϥϦͱ͍ͯ͠ ͍͢ίʔυʹ͢Δ 2. 1ͷϑΣʔζͰॻ͍ͨίʔυΛ֎෦͔Βݺͼग़ͨ͢ΊͷϥούʔؔΛॻ͘ • ͜ͷ࣌ɺ1ͷϑΣʔζͰॻ͍ͨίʔυجຊతʹ৮Βͳ͍ • ϥούʔؔͰɺϓϦϛςΟϒͳͱϙΠϯλ͚ͩΛѻ͏
3. ݴޠόΠϯσΟϯάΛॻ͘ • RustͰexportͯ͠Δؔͦͷ··ͩͱ֤ݴޠͷ׳शʹ߹Θͳ͍ͷͰɺ׳शͱ ͷࠩҧΛόΠϯσΟϯάͰٵऩ͍͘͢͢͠Δ ԬRubyձٞ02 85
ࢀߟࢿྉ • The Rust FFI Omnibus • http://jakegoulding.com/rust-ffi-omnibus/ ԬRubyձٞ02 86
͓ΘΓʹ • ۦ͚Ͱઆ໌ͨ͠ͷͰΘ͔Γʹ͍͘ͱ͜Ζ͕ଟʑ͋ͬͨͱࢥ͍·͢ • ڵຯΛ࣋ͬͨํαϯϓϧίʔυΛಈ͔͠ͳ͕Βࢼͯ͠Έͯͩ͘͞ ͍ • αϯϓϧίʔυͪ͜Β https://github.com/mizzy/ fukuokark02_code_examples
• ಈ͔ͳ͍ɺΘ͔Γʹ͍͘ͳͲԿ͔͋Γ·ͨ͠ΒɺGitHub Issues gosukenator@twitter·Ͱ͓Β͍ͤͩ͘͞ ԬRubyձٞ02 87