Files
ruby/ext/zap/stream_fd_message_reader.cc
zeekay 41415a22ef Finish capnp→ZAP rebrand; fix Ruby 4 build + bump dev deps
Rebrand all ZAP-facing identifiers off Cap'n Proto:
- module Capnp→Zap, ext binding namespace ruby_capn_proto→ruby_zap,
  header guard RUBY_CAPN_PROTO_H→RUBY_ZAP_H, entry point Init_zap,
  gem capn_proto→zap, schemas .capnp→.zap, media/logo, gemspec, README,
  spec, examples. Zero capnp/Cap'n Proto brand prose remains.

Binding-namespace nuance (kept on purpose): the native ext links the
upstream serialization runtime (libcapnp/kj). Its capnp:: C++ symbols and
<capnp/...> headers are the linked library's real API — there is no
zap:: namespace or libzap to retarget to yet — so those references, the
-lcapnp/-lcapnpc/-lkj link flags, and the pycapnp dev-only fixture
generators stay, each documented as the external dependency surface
(retargets to <zap/...>/-lzap when the ZAP C++ runtime ships).

Build/modernization:
- extconf.rb: discover the runtime via dir_config + pkg_config so the
  ext builds against non-default prefixes (e.g. Homebrew), not just
  /usr/local. Native ext now compiles + links cleanly (zap.bundle).
- ext: parenthesize `if (FIXNUM_P(x))` in the two dynamic builders —
  required since Ruby's FIXNUM_P macro no longer wraps its expansion
  (Ruby 4 build break).
- Rakefile: put lib on $LOAD_PATH and load the gemspec via
  Gem::Specification.load; pin rake-compiler ~> 0.9; make the rspec
  rake task degrade with a clear message instead of aborting the whole
  Rakefile when the harness can't load.
- gemspec: bump dev deps within-major (rspec ~> 2.14, rake ~> 13.0,
  rake-compiler ~> 0.9); add required_ruby_version.
- .gitignore: ignore native-ext build artifacts (*.o, Makefile,
  mkmf.log, *.bundle.dSYM, *.gem).

Verified: all spec/zap_spec.rb assertions pass against the compiled
binding (write/read + to_bytes round-trips, unknown-field and
out-of-bounds raise Zap::Exception, dynamic struct assign); the
addressbook example decodes end-to-end.
2026-06-19 23:57:58 -07:00

60 lines
1.6 KiB
C++

#include "ruby_zap.h"
#include "message_reader.h"
#include "stream_fd_message_reader.h"
#include "struct_schema.h"
#include "dynamic_struct_reader.h"
#include "class_builder.h"
#include "exception.h"
namespace ruby_zap {
using WrappedType = capnp::StreamFdMessageReader;
VALUE StreamFdMessageReader::Class;
void StreamFdMessageReader::Init() {
ClassBuilder("StreamFdMessageReader", MessageReader::Class).
defineAlloc(&alloc).
defineMethod("initialize", &initialize).
defineMethod("get_root", &get_root).
store(&Class);
}
VALUE StreamFdMessageReader::alloc(VALUE klass) {
return Data_Wrap_Struct(klass, NULL, free, ruby_xmalloc(sizeof(WrappedType)));
}
VALUE StreamFdMessageReader::initialize(VALUE self, VALUE rb_io) {
VALUE rb_fileno = rb_funcall(rb_io, rb_intern("fileno"), 0);
auto fileno = FIX2INT(rb_fileno);
WrappedType* p = unwrap(self);
try {
new (p) WrappedType(fileno);
} catch (kj::Exception ex) {
return Exception::raise(ex);
}
return Qnil;
}
void StreamFdMessageReader::free(WrappedType* p) {
p->~StreamFdMessageReader();
ruby_xfree(p);
}
WrappedType* StreamFdMessageReader::unwrap(VALUE self) {
WrappedType* p;
Data_Get_Struct(self, WrappedType, p);
return p;
}
VALUE StreamFdMessageReader::get_root(VALUE self, VALUE rb_schema) {
if (rb_respond_to(rb_schema, rb_intern("schema"))) {
rb_schema = rb_funcall(rb_schema, rb_intern("schema"), 0);
}
auto schema = *StructSchema::unwrap(rb_schema);
auto reader = unwrap(self)->getRoot<capnp::DynamicStruct>(schema);
return DynamicStructReader::create(reader, self);
}
}