如何使用`js_of_ocaml`从`bytes`产生`ArrayBuffer`

时间:2018-09-17 09:53:09

标签: javascript string ocaml arraybuffer js-of-ocaml

我正在构建一个JavaScript库,该库在Ocaml中实现,并使用js_of_ocaml编译为JavaScript。

我的Ocaml函数之一返回带有二进制数据的public partial class Booking { public Booking() { BookingDetail = new HashSet<BookingDetail>(); Invoice = new HashSet<Invoice>(); } [Column(TypeName = "bigint(20)")] public long Id { get; set; } [Required] [Column(TypeName = "varchar(50)")] public string TempId { get; set; } [InverseProperty("Booking")] public ICollection<BookingDetail> BookingDetail { get; set; } [InverseProperty("Booking")] public ICollection<Invoice> Invoice { get; set; } } public partial class BookingDetail { public BookingDetail() { Invoice = new HashSet<Invoice>(); } [Column(TypeName = "bigint(20)")] public long Id { get; set; } [Required] [Column(TypeName = "varchar(50)")] public string CreatedBy { get; set; } [Column(TypeName = "datetime")] public DateTime CreatedOn { get; set; } [Required] [Column(TypeName = "varchar(50)")] public string ModifiedBy { get; set; } [Column(TypeName = "datetime")] public DateTime ModifiedOn { get; set; } [Column(TypeName = "bigint(20)")] public long BookingId { get; set; } [ForeignKey("BookingId")] [InverseProperty("BookingDetail")] public Booking Booking { get; set; } [InverseProperty("BookingDetail")] public ICollection<Invoice> Invoice { get; set; } } public partial class Invoice { [Column(TypeName = "bigint(20)")] public long Id { get; set; } [Column(TypeName = "bigint(20)")] public long BookingId { get; set; } [Column(TypeName = "bigint(20)")] public long BookingDetailId { get; set; } [Column(TypeName = "datetime")] public DateTime CreatedOn { get; set; } [Column(TypeName = "datetime")] public DateTime CreatedBy { get; set; } [Column(TypeName = "datetime")] public DateTime ModifiedOn { get; set; } [Required] [Column(TypeName = "varchar(50)")] public string ModifiedBy { get; set; } [ForeignKey("BookingId")] [InverseProperty("Invoice")] public Booking Booking { get; set; } [ForeignKey("BookingDetailId")] [InverseProperty("Invoice")] public BookingDetail BookingDetail { get; set; } } public class Class1 { HMEBookingContext context = new HMEBookingContext(); #region declarations public long BookingId { get; set; } public string CustomerEmailId { get; set; } = "admin@holidayme.com"; #endregion Random rnd = new Random(); public void insert() { try { Booking booking = new Booking(); booking.TempBookingId = BookingRefNumber.ToString(); var bookingDetail = new List<BookingDetail>(); BookingDetail detail = new BookingDetail(); detail.CreatedBy = CustomerEmailId; detail.CreatedOn = DateTime.Now; detail.ModifiedBy = "1"; detail.ModifiedOn = DateTime.UtcNow; detail.BookingStatusId = 1; var invoices = new List<Invoice>(); Invoice invoice = new Invoice(); invoices.Add(invoice); detail.Invoice = invoices; bookingDetail.Add(detail); booking.BookingDetail = bookingDetail; context.Add(booking); context.SaveChanges(true); BookingId=booking.Id } catch(DbUpdateException upd) { } catch(Exception ex) { } } } 。我如何使用string作为js_of_ocaml来公开它?

1 个答案:

答案 0 :(得分:7)

当您编译为javascript时,在string s中处理二进制数据非常容易出错!

根本原因是对js_of_ocaml的选择存在疑问: 因为javascript字符串是用UTF16编码的,而OCaml的字符串是(隐式的)以UTF8编码的,所以js_of_ocaml试图在2之间进行导航。因此,当它遇到代码大于127的“字符”时,{{1} }如果将其转换为原始二进制数据,那将是一场灾难!

解决方案是操纵js_of_ocaml而不是bigstring。 大字符串在原始OCaml中是string,但是越来越多的库将它们作为别名。 尤其是,它们是(char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t中的Typed_array.​Bigstring.t(您可以在其中看到要与js_of_ocaml进行转换的函数)

如果您的函数在用javascript编译后确实可以通过魔术作用于字符串,则在大字符串和字符串之间的多个位置都有转换函数。 例如,bigstring库:http://c-cube.github.io/ocaml-bigstring/,但这些功能在lwtArrayBuffer

中也可用

您可以在同一主题上看到另一个问题(包括使用javascript处理OCaml字符串而不用Lwt_bytes完全触摸它们的方式) https://discuss.ocaml.org/t/handling-binary-data-in-ocaml-and-javascript/1519