tring list
)
"Rust.ml" 294 10178 10229 "Rust.ml" 294 10178 10230
type(
  string
)
ident(
  int_ref x "Rust.ml" 294 10178 10222 "Rust.ml" 294 10178 10223
)
"Rust.ml" 294 10178 10233 "Rust.ml" 294 10178 10234
type(
  string list
)
type(
  string list
)
"Rust.ml" 294 10178 10245 "Rust.ml" 294 10178 10250
type(
  bool
)
"Rust.ml" 294 10178 10238 "Rust.ml" 294 10178 10250
type(
  string
)
"Rust.ml" 294 10178 10199 "Rust.ml" 294 10178 10250
type(
  string
)
"Rust.ml" 295 10254 10260 "Rust.ml" 295 10254 10262
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 296 10263 10271 "Rust.ml" 296 10263 10341
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 297 10342 10350 "Rust.ml" 297 10342 10359
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 297 10342 10360 "Rust.ml" 297 10342 10369
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 295 10254 10260 "Rust.ml" 297 10342 10369
type(
  unit
)
"Rust.ml" 298 10371 10377 "Rust.ml" 298 10371 10379
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 298 10371 10380 "Rust.ml" 298 10371 10409
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 298 10371 10410 "Rust.ml" 298 10371 10418
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 294 10178 10188 "Rust.ml" 294 10178 10196
)
"Rust.ml" 298 10371 10419 "Rust.ml" 298 10371 10428
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 298 10371 10377 "Rust.ml" 298 10371 10428
type(
  unit
)
"Rust.ml" 295 10254 10260 "Rust.ml" 298 10371 10428
type(
  unit
)
"Rust.ml" 294 10178 10184 "Rust.ml" 298 10371 10428
type(
  unit
)
"Rust.ml" 299 10429 10438 "Rust.ml" 299 10429 10439
type(
  string
)
"Rust.ml" 299 10429 10433 "Rust.ml" 299 10429 10439
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 300 10443 10453 "Rust.ml" 300 10443 10461
type(
  string
)
ident(
  def ffi_name "Rust.ml" 301 10519 10525 "Rust.ml" 304 10674 10731
)
"Rust.ml" 300 10443 10470 "Rust.ml" 300 10443 10479
type(
  string list
)
ident(
  int_ref ffi_names "Rust.ml" 274 9279 9285 "Rust.ml" 274 9279 9294
)
"Rust.ml" 300 10443 10487 "Rust.ml" 300 10443 10488
type(
  string
)
ident(
  def x "Rust.ml" 300 10443 10494 "Rust.ml" 300 10443 10495
)
"Rust.ml" 300 10443 10485 "Rust.ml" 300 10443 10490
type(
  string list
)
type(
  string list
)
"Rust.ml" 300 10443 10494 "Rust.ml" 300 10443 10495
type(
  string
)
ident(
  int_ref x "Rust.ml" 300 10443 10487 "Rust.ml" 300 10443 10488
)
"Rust.ml" 300 10443 10498 "Rust.ml" 300 10443 10499
type(
  string list
)
type(
  string list
)
"Rust.ml" 300 10443 10510 "Rust.ml" 300 10443 10515
type(
  bool
)
"Rust.ml" 300 10443 10503 "Rust.ml" 300 10443 10515
type(
  string
)
"Rust.ml" 300 10443 10464 "Rust.ml" 300 10443 10515
type(
  string
)
"Rust.ml" 301 10519 10525 "Rust.ml" 301 10519 10527
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 301 10519 10528 "Rust.ml" 301 10519 10543
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 301 10519 10544 "Rust.ml" 301 10519 10553
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 301 10519 10525 "Rust.ml" 301 10519 10553
type(
  unit
)
"Rust.ml" 302 10555 10561 "Rust.ml" 302 10555 10563
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 302 10555 10564 "Rust.ml" 302 10555 10617
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 302 10555 10618 "Rust.ml" 302 10555 10627
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 302 10555 10561 "Rust.ml" 302 10555 10627
type(
  unit
)
"Rust.ml" 303 10629 10635 "Rust.ml" 303 10629 10637
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 303 10629 10638 "Rust.ml" 303 10629 10672
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 303 10629 10635 "Rust.ml" 303 10629 10672
type(
  unit
)
"Rust.ml" 304 10674 10680 "Rust.ml" 304 10674 10682
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 304 10674 10683 "Rust.ml" 304 10674 10712
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 304 10674 10713 "Rust.ml" 304 10674 10721
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 300 10443 10453 "Rust.ml" 300 10443 10461
)
"Rust.ml" 304 10674 10722 "Rust.ml" 304 10674 10731
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 304 10674 10680 "Rust.ml" 304 10674 10731
type(
  unit
)
"Rust.ml" 303 10629 10635 "Rust.ml" 304 10674 10731
type(
  unit
)
"Rust.ml" 302 10555 10561 "Rust.ml" 304 10674 10731
type(
  unit
)
"Rust.ml" 301 10519 10525 "Rust.ml" 304 10674 10731
type(
  unit
)
"Rust.ml" 300 10443 10449 "Rust.ml" 304 10674 10731
type(
  unit
)
"Rust.ml" 305 10732 10747 "Rust.ml" 305 10732 10748
type(
  string
)
"Rust.ml" 305 10732 10736 "Rust.ml" 305 10732 10748
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 306 10752 10762 "Rust.ml" 306 10752 10770
type(
  string
)
ident(
  def ffi_name "Rust.ml" 309 10975 10981 "Rust.ml" 323 11730 11791
)
"Rust.ml" 306 10752 10779 "Rust.ml" 306 10752 10788
type(
  string list
)
ident(
  int_ref ffi_names "Rust.ml" 274 9279 9285 "Rust.ml" 274 9279 9294
)
"Rust.ml" 306 10752 10796 "Rust.ml" 306 10752 10797
type(
  string
)
ident(
  def x "Rust.ml" 306 10752 10803 "Rust.ml" 306 10752 10804
)
"Rust.ml" 306 10752 10794 "Rust.ml" 306 10752 10799
type(
  string list
)
type(
  string list
)
"Rust.ml" 306 10752 10803 "Rust.ml" 306 10752 10804
type(
  string
)
ident(
  int_ref x "Rust.ml" 306 10752 10796 "Rust.ml" 306 10752 10797
)
"Rust.ml" 306 10752 10807 "Rust.ml" 306 10752 10808
type(
  string list
)
type(
  string list
)
"Rust.ml" 306 10752 10819 "Rust.ml" 306 10752 10824
type(
  bool
)
"Rust.ml" 306 10752 10812 "Rust.ml" 306 10752 10824
type(
  string
)
"Rust.ml" 306 10752 10773 "Rust.ml" 306 10752 10824
type(
  string
)
"Rust.ml" 309 10975 10981 "Rust.ml" 309 10975 10983
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 309 10975 10984 "Rust.ml" 309 10975 11016
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 309 10975 11017 "Rust.ml" 309 10975 11025
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 306 10752 10762 "Rust.ml" 306 10752 10770
)
"Rust.ml" 309 10975 10981 "Rust.ml" 309 10975 11025
type(
  unit
)
"Rust.ml" 310 11027 11033 "Rust.ml" 310 11027 11035
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 310 11027 11036 "Rust.ml" 310 11027 11052
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 310 11027 11053 "Rust.ml" 310 11027 11062
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 310 11027 11033 "Rust.ml" 310 11027 11062
type(
  unit
)
"Rust.ml" 311 11064 11070 "Rust.ml" 311 11064 11072
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 311 11064 11073 "Rust.ml" 311 11064 11108
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 311 11064 11070 "Rust.ml" 311 11064 11108
type(
  unit
)
"Rust.ml" 312 11110 11116 "Rust.ml" 312 11110 11118
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 312 11110 11119 "Rust.ml" 312 11110 11162
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 312 11110 11116 "Rust.ml" 312 11110 11162
type(
  unit
)
"Rust.ml" 313 11164 11170 "Rust.ml" 313 11164 11172
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 313 11164 11173 "Rust.ml" 313 11164 11213
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 313 11164 11170 "Rust.ml" 313 11164 11213
type(
  unit
)
"Rust.ml" 318 11464 11470 "Rust.ml" 318 11464 11472
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 318 11464 11473 "Rust.ml" 318 11464 11513
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 318 11464 11514 "Rust.ml" 318 11464 11522
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 306 10752 10762 "Rust.ml" 306 10752 10770
)
"Rust.ml" 318 11464 11470 "Rust.ml" 318 11464 11522
type(
  unit
)
"Rust.ml" 319 11524 11530 "Rust.ml" 319 11524 11532
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 319 11524 11533 "Rust.ml" 319 11524 11597
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 320 11598 11606 "Rust.ml" 320 11598 11614
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 306 10752 10762 "Rust.ml" 306 10752 10770
)
"Rust.ml" 319 11524 11530 "Rust.ml" 320 11598 11614
type(
  unit
)
"Rust.ml" 322 11676 11682 "Rust.ml" 322 11676 11684
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 322 11676 11685 "Rust.ml" 322 11676 11719
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 322 11676 11720 "Rust.ml" 322 11676 11728
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 306 10752 10762 "Rust.ml" 306 10752 10770
)
"Rust.ml" 322 11676 11682 "Rust.ml" 322 11676 11728
type(
  unit
)
"Rust.ml" 323 11730 11736 "Rust.ml" 323 11730 11738
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 323 11730 11739 "Rust.ml" 323 11730 11773
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 323 11730 11774 "Rust.ml" 323 11730 11782
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 306 10752 10762 "Rust.ml" 306 10752 10770
)
"Rust.ml" 323 11730 11783 "Rust.ml" 323 11730 11791
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 306 10752 10762 "Rust.ml" 306 10752 10770
)
"Rust.ml" 323 11730 11736 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 322 11676 11682 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 319 11524 11530 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 318 11464 11470 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 313 11164 11170 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 312 11110 11116 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 311 11064 11070 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 310 11027 11033 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 309 10975 10981 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 306 10752 10758 "Rust.ml" 323 11730 11791
type(
  unit
)
"Rust.ml" 324 11792 11804 "Rust.ml" 324 11792 11805
type(
  string
)
type(
  string
)
"Rust.ml" 324 11792 11796 "Rust.ml" 324 11792 11805
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 324 11792 11823 "Rust.ml" 324 11792 11824
type(
  string
)
type(
  string
)
"Rust.ml" 324 11792 11808 "Rust.ml" 324 11792 11824
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 324 11792 11796 "Rust.ml" 324 11792 11824
type(
  API.arg
)
"Rust.ml" 325 11828 11838 "Rust.ml" 325 11828 11850
type(
  string
)
ident(
  def ffi_buf_name "Rust.ml" 328 11944 11950 "Rust.ml" 329 12020 12074
)
"Rust.ml" 325 11828 11852 "Rust.ml" 325 11828 11864
type(
  string
)
ident(
  def ffi_len_name "Rust.ml" 328 11944 11950 "Rust.ml" 329 12020 12074
)
"Rust.ml" 325 11828 11838 "Rust.ml" 325 11828 11864
type(
  string * string
)
"Rust.ml" 326 11867 11881 "Rust.ml" 326 11867 11890
type(
  string list
)
ident(
  int_ref ffi_names "Rust.ml" 274 9279 9285 "Rust.ml" 274 9279 9294
)
"Rust.ml" 326 11867 11898 "Rust.ml" 326 11867 11899
type(
  string
)
ident(
  def x "Rust.ml" 326 11867 11908 "Rust.ml" 326 11867 11914
)
"Rust.ml" 326 11867 11901 "Rust.ml" 326 11867 11902
type(
  string
)
ident(
  def y "Rust.ml" 326 11867 11908 "Rust.ml" 326 11867 11914
)
"Rust.ml" 326 11867 11896 "Rust.ml" 326 11867 11904
type(
  string list
)
type(
  string list
)
"Rust.ml" 326 11867 11909 "Rust.ml" 326 11867 11910
type(
  string
)
ident(
  int_ref x "Rust.ml" 326 11867 11898 "Rust.ml" 326 11867 11899
)
"Rust.ml" 326 11867 11912 "Rust.ml" 326 11867 11913
type(
  string
)
ident(
  int_ref y "Rust.ml" 326 11867 11901 "Rust.ml" 326 11867 11902
)
"Rust.ml" 326 11867 11908 "Rust.ml" 326 11867 11914
type(
  string * string
)
"Rust.ml" 326 11867 11917 "Rust.ml" 326 11867 11918
type(
  string list
)
type(
  string list
)
"Rust.ml" 326 11867 11929 "Rust.ml" 326 11867 11934
type(
  bool
)
"Rust.ml" 326 11867 11922 "Rust.ml" 326 11867 11934
type(
  string * string
)
"Rust.ml" 326 11867 11875 "Rust.ml" 326 11867 11934
type(
  string * string
)
"Rust.ml" 328 11944 11950 "Rust.ml" 328 11944 11952
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 328 11944 11953 "Rust.ml" 328 11944 11995
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 328 11944 11996 "Rust.ml" 328 11944 12008
type(
  string
)
ident(
  int_ref ffi_buf_name "Rust.ml" 325 11828 11838 "Rust.ml" 325 11828 11850
)
"Rust.ml" 328 11944 12009 "Rust.ml" 328 11944 12018
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 328 11944 11950 "Rust.ml" 328 11944 12018
type(
  unit
)
"Rust.ml" 329 12020 12026 "Rust.ml" 329 12020 12028
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 329 12020 12029 "Rust.ml" 329 12020 12051
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 329 12020 12052 "Rust.ml" 329 12020 12064
type(
  string
)
ident(
  int_ref ffi_len_name "Rust.ml" 325 11828 11852 "Rust.ml" 325 11828 11864
)
"Rust.ml" 329 12020 12065 "Rust.ml" 329 12020 12074
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 329 12020 12026 "Rust.ml" 329 12020 12074
type(
  unit
)
"Rust.ml" 328 11944 11950 "Rust.ml" 329 12020 12074
type(
  unit
)
"Rust.ml" 325 11828 11834 "Rust.ml" 329 12020 12074
type(
  unit
)
"Rust.ml" 330 12075 12088 "Rust.ml" 330 12075 12089
type(
  string
)
type(
  string
)
"Rust.ml" 330 12075 12079 "Rust.ml" 330 12075 12089
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 330 12075 12108 "Rust.ml" 330 12075 12109
type(
  string
)
type(
  string
)
"Rust.ml" 330 12075 12092 "Rust.ml" 330 12075 12109
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 330 12075 12079 "Rust.ml" 330 12075 12109
type(
  API.arg
)
"Rust.ml" 331 12113 12123 "Rust.ml" 331 12113 12135
type(
  string
)
ident(
  def ffi_buf_name "Rust.ml" 334 12229 12235 "Rust.ml" 335 12307 12361
)
"Rust.ml" 331 12113 12137 "Rust.ml" 331 12113 12149
type(
  string
)
ident(
  def ffi_len_name "Rust.ml" 334 12229 12235 "Rust.ml" 335 12307 12361
)
"Rust.ml" 331 12113 12123 "Rust.ml" 331 12113 12149
type(
  string * string
)
"Rust.ml" 332 12152 12166 "Rust.ml" 332 12152 12175
type(
  string list
)
ident(
  int_ref ffi_names "Rust.ml" 274 9279 9285 "Rust.ml" 274 9279 9294
)
"Rust.ml" 332 12152 12183 "Rust.ml" 332 12152 12184
type(
  string
)
ident(
  def x "Rust.ml" 332 12152 12193 "Rust.ml" 332 12152 12199
)
"Rust.ml" 332 12152 12186 "Rust.ml" 332 12152 12187
type(
  string
)
ident(
  def y "Rust.ml" 332 12152 12193 "Rust.ml" 332 12152 12199
)
"Rust.ml" 332 12152 12181 "Rust.ml" 332 12152 12189
type(
  string list
)
type(
  string list
)
"Rust.ml" 332 12152 12194 "Rust.ml" 332 12152 12195
type(
  string
)
ident(
  int_ref x "Rust.ml" 332 12152 12183 "Rust.ml" 332 12152 12184
)
"Rust.ml" 332 12152 12197 "Rust.ml" 332 12152 12198
type(
  string
)
ident(
  int_ref y "Rust.ml" 332 12152 12186 "Rust.ml" 332 12152 12187
)
"Rust.ml" 332 12152 12193 "Rust.ml" 332 12152 12199
type(
  string * string
)
"Rust.ml" 332 12152 12202 "Rust.ml" 332 12152 12203
type(
  string list
)
type(
  string list
)
"Rust.ml" 332 12152 12214 "Rust.ml" 332 12152 12219
type(
  bool
)
"Rust.ml" 332 12152 12207 "Rust.ml" 332 12152 12219
type(
  string * string
)
"Rust.ml" 332 12152 12160 "Rust.ml" 332 12152 12219
type(
  string * string
)
"Rust.ml" 334 12229 12235 "Rust.ml" 334 12229 12237
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 334 12229 12238 "Rust.ml" 334 12229 12282
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 334 12229 12283 "Rust.ml" 334 12229 12295
type(
  string
)
ident(
  int_ref ffi_buf_name "Rust.ml" 331 12113 12123 "Rust.ml" 331 12113 12135
)
"Rust.ml" 334 12229 12296 "Rust.ml" 334 12229 12305
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 334 12229 12235 "Rust.ml" 334 12229 12305
type(
  unit
)
"Rust.ml" 335 12307 12313 "Rust.ml" 335 12307 12315
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 335 12307 12316 "Rust.ml" 335 12307 12338
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 335 12307 12339 "Rust.ml" 335 12307 12351
type(
  string
)
ident(
  int_ref ffi_len_name "Rust.ml" 331 12113 12137 "Rust.ml" 331 12113 12149
)
"Rust.ml" 335 12307 12352 "Rust.ml" 335 12307 12361
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 335 12307 12313 "Rust.ml" 335 12307 12361
type(
  unit
)
"Rust.ml" 334 12229 12235 "Rust.ml" 335 12307 12361
type(
  unit
)
"Rust.ml" 331 12113 12119 "Rust.ml" 335 12307 12361
type(
  unit
)
"Rust.ml" 336 12362 12369 "Rust.ml" 336 12362 12370
type(
  string
)
"Rust.ml" 336 12362 12366 "Rust.ml" 336 12362 12370
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 337 12374 12384 "Rust.ml" 337 12374 12392
type(
  string
)
ident(
  def ffi_name "Rust.ml" 338 12450 12456 "Rust.ml" 338 12450 12506
)
"Rust.ml" 337 12374 12401 "Rust.ml" 337 12374 12410
type(
  string list
)
ident(
  int_ref ffi_names "Rust.ml" 274 9279 9285 "Rust.ml" 274 9279 9294
)
"Rust.ml" 337 12374 12418 "Rust.ml" 337 12374 12419
type(
  string
)
ident(
  def x "Rust.ml" 337 12374 12425 "Rust.ml" 337 12374 12426
)
"Rust.ml" 337 12374 12416 "Rust.ml" 337 12374 12421
type(
  string list
)
type(
  string list
)
"Rust.ml" 337 12374 12425 "Rust.ml" 337 12374 12426
type(
  string
)
ident(
  int_ref x "Rust.ml" 337 12374 12418 "Rust.ml" 337 12374 12419
)
"Rust.ml" 337 12374 12429 "Rust.ml" 337 12374 12430
type(
  string list
)
type(
  string list
)
"Rust.ml" 337 12374 12441 "Rust.ml" 337 12374 12446
type(
  bool
)
"Rust.ml" 337 12374 12434 "Rust.ml" 337 12374 12446
type(
  string
)
"Rust.ml" 337 12374 12395 "Rust.ml" 337 12374 12446
type(
  string
)
"Rust.ml" 338 12450 12456 "Rust.ml" 338 12450 12458
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 338 12450 12459 "Rust.ml" 338 12450 12487
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 338 12450 12488 "Rust.ml" 338 12450 12496
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 337 12374 12384 "Rust.ml" 337 12374 12392
)
"Rust.ml" 338 12450 12497 "Rust.ml" 338 12450 12506
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 338 12450 12456 "Rust.ml" 338 12450 12506
type(
  unit
)
"Rust.ml" 337 12374 12380 "Rust.ml" 338 12450 12506
type(
  unit
)
"Rust.ml" 339 12507 12519 "Rust.ml" 339 12507 12520
type(
  API.closure
)
"Rust.ml" 339 12507 12511 "Rust.ml" 339 12507 12520
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 340 12524 12534 "Rust.ml" 340 12524 12542
type(
  string
)
ident(
  def ffi_name "Rust.ml" 341 12600 12606 "Rust.ml" 342 12674 12701
)
"Rust.ml" 340 12524 12551 "Rust.ml" 340 12524 12560
type(
  string list
)
ident(
  int_ref ffi_names "Rust.ml" 274 9279 9285 "Rust.ml" 274 9279 9294
)
"Rust.ml" 340 12524 12568 "Rust.ml" 340 12524 12569
type(
  string
)
ident(
  def x "Rust.ml" 340 12524 12575 "Rust.ml" 340 12524 12576
)
"Rust.ml" 340 12524 12566 "Rust.ml" 340 12524 12571
type(
  string list
)
type(
  string list
)
"Rust.ml" 340 12524 12575 "Rust.ml" 340 12524 12576
type(
  string
)
ident(
  int_ref x "Rust.ml" 340 12524 12568 "Rust.ml" 340 12524 12569
)
"Rust.ml" 340 12524 12579 "Rust.ml" 340 12524 12580
type(
  string list
)
type(
  string list
)
"Rust.ml" 340 12524 12591 "Rust.ml" 340 12524 12596
type(
  bool
)
"Rust.ml" 340 12524 12584 "Rust.ml" 340 12524 12596
type(
  string
)
"Rust.ml" 340 12524 12545 "Rust.ml" 340 12524 12596
type(
  string
)
"Rust.ml" 341 12600 12606 "Rust.ml" 341 12600 12608
type(
  (string -> string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 341 12600 12609 "Rust.ml" 341 12600 12664
type(
  (string -> string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 341 12600 12665 "Rust.ml" 341 12600 12673
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 340 12524 12534 "Rust.ml" 340 12524 12542
)
"Rust.ml" 342 12674 12682 "Rust.ml" 342 12674 12691
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 342 12674 12692 "Rust.ml" 342 12674 12701
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 273 9240 9246 "Rust.ml" 273 9240 9255
)
"Rust.ml" 341 12600 12606 "Rust.ml" 342 12674 12701
type(
  unit
)
"Rust.ml" 340 12524 12530 "Rust.ml" 342 12674 12701
type(
  unit
)
"Rust.ml" 343 12702 12715 "Rust.ml" 343 12702 12716
type(
  string
)
"Rust.ml" 343 12702 12706 "Rust.ml" 343 12702 12716
type(
  API.arg
)
type(
  API.arg
)
"Rust.ml" 343 12702 12727 "Rust.ml" 343 12702 12732
type(
  bool
)
"Rust.ml" 343 12702 12720 "Rust.ml" 343 12702 12732
type(
  unit
)
"Rust.ml" 275 9318 9320 "Rust.ml" 343 12702 12732
type(
  unit
)
"Rust.ml" 274 9279 9281 "Rust.ml" 343 12702 12732
type(
  unit
)
"Rust.ml" 273 9240 9242 "Rust.ml" 343 12702 12732
type(
  unit
)
"Rust.ml" 346 12830 12834 "Rust.ml" 346 12830 12852
type(
  API.optarg -> unit
)
ident(
  def rust_optarg_to_ffi "Rust.ml" 369 13719 13719 "Rust.ml" 0 0 -1
)
"Rust.ml" 346 12830 12853 "Rust.ml" 346 12830 12856
type(
  API.optarg
)
ident(
  def arg "Rust.ml" 347 12859 12861 "Rust.ml" 363 13471 13489
)
"Rust.ml" 347 12859 12865 "Rust.ml" 347 12859 12874
type(
  string
)
ident(
  def rust_name "Rust.ml" 348 12901 12903 "Rust.ml" 363 13471 13489
)
"Rust.ml" 347 12859 12877 "Rust.ml" 347 12859 12893
type(
  API.optarg -> string
)
ident(
  int_ref rust_optarg_name "Rust.ml" 122 3625 3629 "Rust.ml" 122 3625 3645
)
"Rust.ml" 347 12859 12894 "Rust.ml" 347 12859 12897
type(
  API.optarg
)
ident(
  int_ref arg "Rust.ml" 346 12830 12853 "Rust.ml" 346 12830 12856
)
"Rust.ml" 347 12859 12877 "Rust.ml" 347 12859 12897
type(
  string
)
"Rust.ml" 348 12901 12907 "Rust.ml" 348 12901 12915
type(
  string
)
ident(
  def ffi_name "Rust.ml" 349 12941 12943 "Rust.ml" 363 13471 13489
)
"Rust.ml" 348 12901 12918 "Rust.ml" 348 12901 12933
type(
  API.optarg -> string
)
ident(
  int_ref ffi_optarg_name "Rust.ml" 210 6673 6677 "Rust.ml" 210 6673 6692
)
"Rust.ml" 348 12901 12934 "Rust.ml" 348 12901 12937
type(
  API.optarg
)
ident(
  int_ref arg "Rust.ml" 346 12830 12853 "Rust.ml" 346 12830 12856
)
"Rust.ml" 348 12901 12918 "Rust.ml" 348 12901 12937
type(
  string
)
"Rust.ml" 349 12941 12949 "Rust.ml" 349 12941 12952
type(
  API.optarg
)
ident(
  int_ref arg "Rust.ml" 346 12830 12853 "Rust.ml" 346 12830 12856
)
"Rust.ml" 350 12958 12973 "Rust.ml" 350 12958 12979
type(
  string
)
ident(
  def cbname "Rust.ml" 351 12985 12991 "Rust.ml" 359 13293 13308
)
"Rust.ml" 350 12958 12971 "Rust.ml" 350 12958 12981
type(
  API.closure
)
"Rust.ml" 350 12958 12962 "Rust.ml" 350 12958 12981
type(
  API.optarg
)
type(
  API.optarg
)
"Rust.ml" 351 12985 12991 "Rust.ml" 351 12985 12993
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 351 12985 12994 "Rust.ml" 351 12985 13017
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 351 12985 13018 "Rust.ml" 351 12985 13026
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 348 12901 12907 "Rust.ml" 348 12901 12915
)
"Rust.ml" 351 12985 13027 "Rust.ml" 351 12985 13036
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 347 12859 12865 "Rust.ml" 347 12859 12874
)
"Rust.ml" 351 12985 12991 "Rust.ml" 351 12985 13036
type(
  unit
)
"Rust.ml" 352 13038 13044 "Rust.ml" 352 13038 13046
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 352 13038 13047 "Rust.ml" 352 13038 13107
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 353 13108 13116 "Rust.ml" 353 13108 13125
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 347 12859 12865 "Rust.ml" 347 12859 12874
)
"Rust.ml" 352 13038 13044 "Rust.ml" 353 13108 13125
type(
  unit
)
"Rust.ml" 354 13127 13133 "Rust.ml" 354 13127 13135
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 354 13127 13136 "Rust.ml" 354 13127 13173
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 354 13127 13174 "Rust.ml" 354 13127 13180
type(
  string
)
ident(
  int_ref cbname "Rust.ml" 350 12958 12973 "Rust.ml" 350 12958 12979
)
"Rust.ml" 354 13127 13133 "Rust.ml" 354 13127 13180
type(
  unit
)
"Rust.ml" 355 13182 13188 "Rust.ml" 355 13182 13190
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 355 13182 13191 "Rust.ml" 355 13182 13209
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 355 13182 13188 "Rust.ml" 355 13182 13209
type(
  unit
)
"Rust.ml" 356 13211 13217 "Rust.ml" 356 13211 13219
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 356 13211 13220 "Rust.ml" 356 13211 13234
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 356 13211 13217 "Rust.ml" 356 13211 13234
type(
  unit
)
"Rust.ml" 357 13236 13242 "Rust.ml" 357 13236 13244
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 357 13236 13245 "Rust.ml" 357 13236 13274
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 357 13236 13242 "Rust.ml" 357 13236 13274
type(
  unit
)
"Rust.ml" 358 13276 13282 "Rust.ml" 358 13276 13284
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 358 13276 13285 "Rust.ml" 358 13276 13291
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 358 13276 13282 "Rust.ml" 358 13276 13291
type(
  unit
)
"Rust.ml" 359 13293 13299 "Rust.ml" 359 13293 13301
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 359 13293 13302 "Rust.ml" 359 13293 13308
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 359 13293 13299 "Rust.ml" 359 13293 13308
type(
  unit
)
"Rust.ml" 358 13276 13282 "Rust.ml" 359 13293 13308
type(
  unit
)
"Rust.ml" 357 13236 13242 "Rust.ml" 359 13293 13308
type(
  unit
)
"Rust.ml" 356 13211 13217 "Rust.ml" 359 13293 13308
type(
  unit
)
"Rust.ml" 355 13182 13188 "Rust.ml" 359 13293 13308
type(
  unit
)
"Rust.ml" 354 13127 13133 "Rust.ml" 359 13293 13308
type(
  unit
)
"Rust.ml" 352 13038 13044 "Rust.ml" 359 13293 13308
type(
  unit
)
"Rust.ml" 351 12985 12991 "Rust.ml" 359 13293 13308
type(
  unit
)
"Rust.ml" 360 13309 13321 "Rust.ml" 360 13309 13322
type(
  string
)
"Rust.ml" 360 13309 13326 "Rust.ml" 360 13309 13337
type(
  string
)
ident(
  def flag_prefix "Rust.ml" 361 13347 13353 "Rust.ml" 363 13471 13489
)
"Rust.ml" 360 13309 13324 "Rust.ml" 360 13309 13339
type(
  API.flags
)
"Rust.ml" 360 13309 13341 "Rust.ml" 360 13309 13342
type(
  string list option
)
"Rust.ml" 360 13309 13313 "Rust.ml" 360 13309 13343
type(
  API.optarg
)
type(
  API.optarg
)
"Rust.ml" 361 13347 13357 "Rust.ml" 361 13347 13367
type(
  string
)
ident(
  def flags_type "Rust.ml" 362 13396 13402 "Rust.ml" 363 13471 13489
)
"Rust.ml" 361 13347 13370 "Rust.ml" 361 13347 13380
type(
  string -> string
)
ident(
  int_ref Utils.camel_case "utils.mli" 81 2826 2826 "utils.mli" 81 2826 2859
)
"Rust.ml" 361 13347 13381 "Rust.ml" 361 13347 13392
type(
  string
)
ident(
  int_ref flag_prefix "Rust.ml" 360 13309 13326 "Rust.ml" 360 13309 13337
)
"Rust.ml" 361 13347 13370 "Rust.ml" 361 13347 13392
type(
  string
)
"Rust.ml" 362 13396 13402 "Rust.ml" 362 13396 13404
type(
  (string -> string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 362 13396 13405 "Rust.ml" 362 13396 13451
type(
  (string -> string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 362 13396 13452 "Rust.ml" 362 13396 13460
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 348 12901 12907 "Rust.ml" 348 12901 12915
)
"Rust.ml" 362 13396 13461 "Rust.ml" 362 13396 13470
type(
  string
)
ident(
  int_ref rust_name "Rust.ml" 347 12859 12865 "Rust.ml" 347 12859 12874
)
"Rust.ml" 363 13471 13479 "Rust.ml" 363 13471 13489
type(
  string
)
ident(
  int_ref flags_type "Rust.ml" 361 13347 13357 "Rust.ml" 361 13347 13367
)
"Rust.ml" 362 13396 13402 "Rust.ml" 363 13471 13489
type(
  unit
)
"Rust.ml" 361 13347 13353 "Rust.ml" 363 13471 13489
type(
  unit
)
"Rust.ml" 349 12941 12943 "Rust.ml" 363 13471 13489
type(
  unit
)
"Rust.ml" 348 12901 12903 "Rust.ml" 363 13471 13489
type(
  unit
)
"Rust.ml" 347 12859 12861 "Rust.ml" 363 13471 13489
type(
  unit
)
"Rust.ml" 369 13719 13723 "Rust.ml" 369 13719 13741
type(
  API.cbarg -> unit
)
ident(
  def ffi_cbargs_to_rust "Rust.ml" 403 15270 15270 "Rust.ml" 0 0 -1
)
"Rust.ml" 369 13719 13742 "Rust.ml" 369 13719 13747
type(
  API.cbarg
)
ident(
  def cbarg "Rust.ml" 370 13750 13752 "Rust.ml" 397 14982 14992
)
"Rust.ml" 370 13750 13756 "Rust.ml" 370 13750 13765
type(
  string list
)
ident(
  def ffi_names "Rust.ml" 371 13793 13795 "Rust.ml" 397 14982 14992
)
"Rust.ml" 370 13750 13768 "Rust.ml" 370 13750 13783
type(
  API.cbarg -> string list
)
ident(
  int_ref ffi_cbarg_names "Rust.ml" 217 7045 7049 "Rust.ml" 217 7045 7064
)
"Rust.ml" 370 13750 13784 "Rust.ml" 370 13750 13789
type(
  API.cbarg
)
ident(
  int_ref cbarg "Rust.ml" 369 13719 13742 "Rust.ml" 369 13719 13747
)
"Rust.ml" 370 13750 13768 "Rust.ml" 370 13750 13789
type(
  string list
)
"Rust.ml" 371 13793 13795 "Rust.ml" 371 13793 13797
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 371 13793 13798 "Rust.ml" 371 13793 13813
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 371 13793 13815 "Rust.ml" 371 13793 13830
type(
  API.cbarg -> string
)
ident(
  int_ref rust_cbarg_name "Rust.ml" 126 3776 3780 "Rust.ml" 126 3776 3795
)
"Rust.ml" 371 13793 13831 "Rust.ml" 371 13793 13836
type(
  API.cbarg
)
ident(
  int_ref cbarg "Rust.ml" 369 13719 13742 "Rust.ml" 369 13719 13747
)
"Rust.ml" 371 13793 13814 "Rust.ml" 371 13793 13837
type(
  string
)
"Rust.ml" 371 13793 13839 "Rust.ml" 371 13793 13854
type(
  API.cbarg -> string
)
ident(
  int_ref rust_cbarg_type "Rust.ml" 165 5216 5220 "Rust.ml" 165 5216 5235
)
"Rust.ml" 371 13793 13855 "Rust.ml" 371 13793 13860
type(
  API.cbarg
)
ident(
  int_ref cbarg "Rust.ml" 369 13719 13742 "Rust.ml" 369 13719 13747
)
"Rust.ml" 371 13793 13838 "Rust.ml" 371 13793 13861
type(
  string
)
"Rust.ml" 371 13793 13795 "Rust.ml" 371 13793 13861
type(
  unit
)
"Rust.ml" 372 13863 13873 "Rust.ml" 372 13863 13878
type(
  API.cbarg
)
ident(
  int_ref cbarg "Rust.ml" 369 13719 13742 "Rust.ml" 369 13719 13747
)
"Rust.ml" 372 13863 13880 "Rust.ml" 372 13863 13889
type(
  string list
)
ident(
  int_ref ffi_names "Rust.ml" 370 13750 13756 "Rust.ml" 370 13750 13765
)
"Rust.ml" 372 13863 13872 "Rust.ml" 372 13863 13890
type(
  API.cbarg * string list
)
"Rust.ml" 373 13896 13907 "Rust.ml" 373 13896 13908
type(
  string
)
"Rust.ml" 373 13896 13901 "Rust.ml" 373 13896 13908
type(
  API.cbarg
)
"Rust.ml" 373 13896 13918 "Rust.ml" 373 13896 13919
type(
  string
)
"Rust.ml" 373 13896 13911 "Rust.ml" 373 13896 13919
type(
  API.cbarg
)
"Rust.ml" 373 13896 13901 "Rust.ml" 373 13896 13919
type(
  API.cbarg
)
"Rust.ml" 373 13896 13930 "Rust.ml" 373 13896 13931
type(
  string
)
"Rust.ml" 373 13896 13922 "Rust.ml" 373 13896 13931
type(
  API.cbarg
)
"Rust.ml" 373 13896 13901 "Rust.ml" 373 13896 13931
type(
  API.cbarg
)
"Rust.ml" 373 13896 13943 "Rust.ml" 373 13896 13944
type(
  string
)
"Rust.ml" 373 13896 13934 "Rust.ml" 373 13896 13944
type(
  API.cbarg
)
"Rust.ml" 373 13896 13900 "Rust.ml" 373 13896 13945
type(
  API.cbarg
)
"Rust.ml" 373 13896 13949 "Rust.ml" 373 13896 13957
type(
  string
)
ident(
  def ffi_name "Rust.ml" 374 13963 13969 "Rust.ml" 374 13963 13985
)
"Rust.ml" 373 13896 13947 "Rust.ml" 373 13896 13959
type(
  string list
)
"Rust.ml" 373 13896 13900 "Rust.ml" 373 13896 13959
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 374 13963 13969 "Rust.ml" 374 13963 13971
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 374 13963 13972 "Rust.ml" 374 13963 13976
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 374 13963 13977 "Rust.ml" 374 13963 13985
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 373 13896 13949 "Rust.ml" 373 13896 13957
)
"Rust.ml" 374 13963 13969 "Rust.ml" 374 13963 13985
type(
  unit
)
"Rust.ml" 375 13986 13999 "Rust.ml" 375 13986 14000
type(
  string
)
"Rust.ml" 375 13986 13990 "Rust.ml" 375 13986 14000
type(
  API.cbarg
)
"Rust.ml" 375 13986 14004 "Rust.ml" 375 13986 14012
type(
  string
)
ident(
  def ffi_name "Rust.ml" 375 13986 14018 "Rust.ml" 375 13986 14061
)
"Rust.ml" 375 13986 14002 "Rust.ml" 375 13986 14014
type(
  string list
)
"Rust.ml" 375 13986 13990 "Rust.ml" 375 13986 14014
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 375 13986 14018 "Rust.ml" 375 13986 14020
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 375 13986 14021 "Rust.ml" 375 13986 14052
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 375 13986 14053 "Rust.ml" 375 13986 14061
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 375 13986 14004 "Rust.ml" 375 13986 14012
)
"Rust.ml" 375 13986 14018 "Rust.ml" 375 13986 14061
type(
  unit
)
"Rust.ml" 376 14062 14076 "Rust.ml" 376 14062 14077
type(
  string
)
type(
  string
)
"Rust.ml" 376 14062 14066 "Rust.ml" 376 14062 14077
type(
  API.cbarg
)
"Rust.ml" 376 14062 14081 "Rust.ml" 376 14062 14093
type(
  string
)
ident(
  def ffi_buf_name "Rust.ml" 377 14113 14119 "Rust.ml" 378 14180 14200
)
"Rust.ml" 376 14062 14095 "Rust.ml" 376 14062 14107
type(
  string
)
ident(
  def ffi_len_name "Rust.ml" 377 14113 14119 "Rust.ml" 378 14180 14200
)
"Rust.ml" 376 14062 14079 "Rust.ml" 376 14062 14109
type(
  string list
)
"Rust.ml" 376 14062 14066 "Rust.ml" 376 14062 14109
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 377 14113 14119 "Rust.ml" 377 14113 14121
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 377 14113 14122 "Rust.ml" 377 14113 14166
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 377 14113 14167 "Rust.ml" 377 14113 14179
type(
  string
)
ident(
  int_ref ffi_buf_name "Rust.ml" 376 14062 14081 "Rust.ml" 376 14062 14093
)
"Rust.ml" 378 14180 14188 "Rust.ml" 378 14180 14200
type(
  string
)
ident(
  int_ref ffi_len_name "Rust.ml" 376 14062 14095 "Rust.ml" 376 14062 14107
)
"Rust.ml" 377 14113 14119 "Rust.ml" 378 14180 14200
type(
  unit
)
"Rust.ml" 379 14201 14227 "Rust.ml" 379 14201 14228
type(
  string
)
"Rust.ml" 379 14201 14220 "Rust.ml" 379 14201 14228
type(
  API.arg
)
"Rust.ml" 379 14201 14230 "Rust.ml" 379 14201 14231
type(
  string
)
"Rust.ml" 379 14201 14205 "Rust.ml" 379 14201 14232
type(
  API.cbarg
)
"Rust.ml" 379 14201 14236 "Rust.ml" 379 14201 14248
type(
  string
)
ident(
  def ffi_arr_name "Rust.ml" 380 14268 14274 "Rust.ml" 380 14268 14334
)
"Rust.ml" 379 14201 14250 "Rust.ml" 379 14201 14262
type(
  string
)
ident(
  def ffi_len_name "Rust.ml" 380 14268 14274 "Rust.ml" 380 14268 14334
)
"Rust.ml" 379 14201 14234 "Rust.ml" 379 14201 14264
type(
  string list
)
"Rust.ml" 379 14201 14205 "Rust.ml" 379 14201 14264
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 380 14268 14274 "Rust.ml" 380 14268 14276
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 380 14268 14277 "Rust.ml" 380 14268 14308
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 380 14268 14309 "Rust.ml" 380 14268 14321
type(
  string
)
ident(
  int_ref ffi_arr_name "Rust.ml" 379 14201 14236 "Rust.ml" 379 14201 14248
)
"Rust.ml" 380 14268 14322 "Rust.ml" 380 14268 14334
type(
  string
)
ident(
  int_ref ffi_len_name "Rust.ml" 379 14201 14250 "Rust.ml" 379 14201 14262
)
"Rust.ml" 380 14268 14274 "Rust.ml" 380 14268 14334
type(
  unit
)
"Rust.ml" 381 14335 14363 "Rust.ml" 381 14335 14364
type(
  string
)
"Rust.ml" 381 14335 14354 "Rust.ml" 381 14335 14364
type(
  API.arg
)
"Rust.ml" 381 14335 14366 "Rust.ml" 381 14335 14367
type(
  string
)
"Rust.ml" 381 14335 14339 "Rust.ml" 381 14335 14368
type(
  API.cbarg
)
"Rust.ml" 381 14335 14372 "Rust.ml" 381 14335 14384
type(
  string
)
ident(
  def ffi_arr_name "Rust.ml" 382 14404 14410 "Rust.ml" 383 14465 14498
)
"Rust.ml" 381 14335 14386 "Rust.ml" 381 14335 14398
type(
  string
)
ident(
  def ffi_len_name "Rust.ml" 382 14404 14410 "Rust.ml" 383 14465 14498
)
"Rust.ml" 381 14335 14370 "Rust.ml" 381 14335 14400
type(
  string list
)
"Rust.ml" 381 14335 14339 "Rust.ml" 381 14335 14400
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 382 14404 14410 "Rust.ml" 382 14404 14412
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 382 14404 14413 "Rust.ml" 382 14404 14464
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 383 14465 14473 "Rust.ml" 383 14465 14485
type(
  string
)
ident(
  int_ref ffi_arr_name "Rust.ml" 381 14335 14372 "Rust.ml" 381 14335 14384
)
"Rust.ml" 383 14465 14486 "Rust.ml" 383 14465 14498
type(
  string
)
ident(
  int_ref ffi_len_name "Rust.ml" 381 14335 14386 "Rust.ml" 381 14335 14398
)
"Rust.ml" 382 14404 14410 "Rust.ml" 383 14465 14498
type(
  unit
)
"Rust.ml" 384 14499 14517 "Rust.ml" 384 14499 14518
type(
  string
)
type(
  API.arg
)
"Rust.ml" 384 14499 14503 "Rust.ml" 384 14499 14518
type(
  API.cbarg
)
"Rust.ml" 384 14499 14522 "Rust.ml" 384 14499 14523
type(
  string
)
"Rust.ml" 384 14499 14525 "Rust.ml" 384 14499 14526
type(
  string
)
"Rust.ml" 384 14499 14520 "Rust.ml" 384 14499 14528
type(
  string list
)
"Rust.ml" 384 14499 14503 "Rust.ml" 384 14499 14528
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 385 14532 14538 "Rust.ml" 385 14532 14546
type(
  string -> unit
)
ident(
  int_ref Stdlib.failwith "stdlib.mli" 41 1919 1919 "stdlib.mli" 41 1919 1946
)
"Rust.ml" 386 14547 14555 "Rust.ml" 387 14626 14644
type(
  string
)
"Rust.ml" 385 14532 14538 "Rust.ml" 387 14626 14644
type(
  unit
)
"Rust.ml" 388 14645 14664 "Rust.ml" 388 14645 14665
type(
  string
)
"Rust.ml" 388 14645 14659 "Rust.ml" 388 14645 14666
type(
  API.arg
)
"Rust.ml" 388 14645 14649 "Rust.ml" 388 14645 14666
type(
  API.cbarg
)
"Rust.ml" 388 14645 14670 "Rust.ml" 388 14645 14678
type(
  string
)
ident(
  def ffi_name "Rust.ml" 388 14645 14684 "Rust.ml" 388 14645 14718
)
"Rust.ml" 388 14645 14668 "Rust.ml" 388 14645 14680
type(
  string list
)
"Rust.ml" 388 14645 14649 "Rust.ml" 388 14645 14680
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 388 14645 14684 "Rust.ml" 388 14645 14686
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 388 14645 14687 "Rust.ml" 388 14645 14709
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 388 14645 14710 "Rust.ml" 388 14645 14718
type(
  string
)
ident(
  int_ref ffi_name "Rust.ml" 388 14645 14670 "Rust.ml" 388 14645 14678
)
"Rust.ml" 388 14645 14684 "Rust.ml" 388 14645 14718
type(
  unit
)
"Rust.ml" 389 14719 14733 "Rust.ml" 389 14719 14734
type(
  API.arg
)
"Rust.ml" 389 14719 14723 "Rust.ml" 389 14719 14734
type(
  API.cbarg
)
"Rust.ml" 389 14719 14738 "Rust.ml" 389 14719 14739
type(
  string
)
"Rust.ml" 389 14719 14736 "Rust.ml" 389 14719 14741
type(
  string list
)
"Rust.ml" 389 14719 14723 "Rust.ml" 389 14719 14741
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 390 14745 14751 "Rust.ml" 390 14745 14759
type(
  string -> unit
)
ident(
  int_ref Stdlib.failwith "stdlib.mli" 41 1919 1919 "stdlib.mli" 41 1919 1946
)
"Rust.ml" 391 14760 14768 "Rust.ml" 392 14833 14860
type(
  string
)
"Rust.ml" 390 14745 14751 "Rust.ml" 392 14833 14860
type(
  unit
)
"Rust.ml" 393 14861 14865 "Rust.ml" 393 14861 14866
type(
  API.cbarg
)
"Rust.ml" 393 14861 14868 "Rust.ml" 393 14861 14869
type(
  string list
)
"Rust.ml" 393 14861 14865 "Rust.ml" 393 14861 14869
type(
  API.cbarg * string list
)
type(
  API.cbarg * string list
)
"Rust.ml" 394 14873 14879 "Rust.ml" 394 14873 14887
type(
  string -> unit
)
ident(
  int_ref Stdlib.failwith "stdlib.mli" 41 1919 1919 "stdlib.mli" 41 1919 1946
)
"Rust.ml" 395 14888 14896 "Rust.ml" 396 14959 14979
type(
  string
)
"Rust.ml" 394 14873 14879 "Rust.ml" 396 14959 14979
type(
  unit
)
"Rust.ml" 372 13863 13865 "Rust.ml" 396 14959 14980
type(
  unit
)
"Rust.ml" 397 14982 14984 "Rust.ml" 397 14982 14986
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 397 14982 14987 "Rust.ml" 397 14982 14992
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 397 14982 14984 "Rust.ml" 397 14982 14992
type(
  unit
)
"Rust.ml" 372 13863 13865 "Rust.ml" 397 14982 14992
type(
  unit
)
"Rust.ml" 371 13793 13795 "Rust.ml" 397 14982 14992
type(
  unit
)
"Rust.ml" 370 13750 13752 "Rust.ml" 397 14982 14992
type(
  unit
)
"Rust.ml" 403 15270 15274 "Rust.ml" 403 15270 15289
type(
  API.call -> unit
)
ident(
  def ffi_ret_to_rust "Rust.ml" 448 17292 17292 "Rust.ml" 0 0 -1
)
"Rust.ml" 403 15270 15290 "Rust.ml" 403 15270 15294
type(
  API.call
)
ident(
  def call "Rust.ml" 404 15297 15299 "Rust.ml" 441 16901 16927
)
"Rust.ml" 404 15297 15303 "Rust.ml" 404 15297 15311
type(
  string
)
ident(
  def ret_type "Rust.ml" 405 15336 15338 "Rust.ml" 441 16901 16927
)
"Rust.ml" 404 15297 15314 "Rust.ml" 404 15297 15327
type(
  API.call -> string
)
ident(
  int_ref rust_ret_type "Rust.ml" 247 8339 8343 "Rust.ml" 247 8339 8356
)
"Rust.ml" 404 15297 15328 "Rust.ml" 404 15297 15332
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 403 15270 15290 "Rust.ml" 403 15270 15294
)
"Rust.ml" 404 15297 15314 "Rust.ml" 404 15297 15332
type(
  string
)
"Rust.ml" 405 15336 15342 "Rust.ml" 405 15336 15351
type(
  string
)
ident(
  def pure_expr "Rust.ml" 428 16331 16333 "Rust.ml" 441 16901 16927
)
"Rust.ml" 406 15354 15364 "Rust.ml" 406 15354 15368
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 403 15270 15290 "Rust.ml" 403 15270 15294
)
"Rust.ml" 406 15354 15364 "Rust.ml" 406 15354 15372
type(
  API.ret
)
"Rust.ml" 407 15378 15384 "Rust.ml" 407 15378 15389
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 407 15378 15393 "Rust.ml" 407 15378 15407
type(
  string
)
"Rust.ml" 408 15408 15414 "Rust.ml" 408 15408 15418
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 408 15408 15422 "Rust.ml" 408 15408 15426
type(
  string
)
"Rust.ml" 409 15427 15433 "Rust.ml" 409 15427 15437
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 409 15427 15441 "Rust.ml" 409 15427 15485
type(
  string
)
"Rust.ml" 410 15486 15492 "Rust.ml" 410 15486 15498
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 410 15486 15502 "Rust.ml" 410 15486 15546
type(
  string
)
"Rust.ml" 411 15547 15553 "Rust.ml" 411 15547 15559
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 411 15547 15563 "Rust.ml" 411 15547 15609
type(
  string
)
"Rust.ml" 412 15610 15616 "Rust.ml" 412 15610 15623
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 412 15610 15627 "Rust.ml" 412 15610 15664
type(
  string
)
"Rust.ml" 413 15665 15671 "Rust.ml" 413 15665 15674
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 413 15665 15678 "Rust.ml" 413 15665 15696
type(
  string
)
"Rust.ml" 414 15697 15703 "Rust.ml" 414 15697 15716
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 414 15697 15720 "Rust.ml" 414 15697 15767
type(
  string
)
"Rust.ml" 415 15768 15774 "Rust.ml" 415 15768 15781
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 416 15785 15793 "Rust.ml" 416 15785 15809
type(
  string
)
"Rust.ml" 417 15810 15818 "Rust.ml" 417 15810 15819
type(
  string -> string -> string
)
ident(
  int_ref Stdlib.( ^ ) "stdlib.mli" 699 26389 26389 "stdlib.mli" 699 26389 26427
)
"Rust.ml" 417 15810 15820 "Rust.ml" 417 15810 15885
type(
  string
)
"Rust.ml" 418 15886 15894 "Rust.ml" 418 15886 15895
type(
  string -> string -> string
)
ident(
  int_ref Stdlib.( ^ ) "stdlib.mli" 699 26389 26389 "stdlib.mli" 699 26389 26427
)
"Rust.ml" 418 15886 15896 "Rust.ml" 418 15886 15938
type(
  string
)
"Rust.ml" 418 15886 15939 "Rust.ml" 418 15886 15940
type(
  string -> string -> string
)
ident(
  int_ref Stdlib.( ^ ) "stdlib.mli" 699 26389 26389 "stdlib.mli" 699 26389 26427
)
"Rust.ml" 418 15886 15941 "Rust.ml" 418 15886 15948
type(
  string
)
"Rust.ml" 418 15886 15896 "Rust.ml" 418 15886 15948
type(
  string
)
"Rust.ml" 417 15810 15820 "Rust.ml" 418 15886 15948
type(
  string
)
"Rust.ml" 416 15785 15793 "Rust.ml" 418 15886 15948
type(
  string
)
"Rust.ml" 419 15949 15964 "Rust.ml" 419 15949 15975
type(
  string
)
ident(
  def flag_prefix "Rust.ml" 420 15981 15989 "Rust.ml" 420 15981 16039
)
"Rust.ml" 419 15949 15962 "Rust.ml" 419 15949 15977
type(
  API.flags
)
"Rust.ml" 419 15949 15955 "Rust.ml" 419 15949 15977
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 420 15981 15989 "Rust.ml" 420 15981 15996
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 420 15981 15997 "Rust.ml" 420 15981 16030
type(
  (string -> string, unit, string) format
)
"Rust.ml" 420 15981 16031 "Rust.ml" 420 15981 16039
type(
  string
)
ident(
  int_ref ret_type "Rust.ml" 404 15297 15303 "Rust.ml" 404 15297 15311
)
"Rust.ml" 420 15981 15989 "Rust.ml" 420 15981 16039
type(
  string
)
"Rust.ml" 421 16040 16046 "Rust.ml" 421 16040 16051
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 421 16040 16054 "Rust.ml" 421 16040 16062
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 421 16040 16046 "Rust.ml" 421 16040 16062
type(
  API.ret
)
"Rust.ml" 421 16040 16065 "Rust.ml" 421 16040 16072
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 421 16040 16046 "Rust.ml" 421 16040 16072
type(
  API.ret
)
"Rust.ml" 421 16040 16076 "Rust.ml" 421 16040 16083
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 421 16040 16084 "Rust.ml" 421 16040 16099
type(
  (string -> string, unit, string) format
)
"Rust.ml" 421 16040 16100 "Rust.ml" 421 16040 16108
type(
  string
)
ident(
  int_ref ret_type "Rust.ml" 404 15297 15303 "Rust.ml" 404 15297 15311
)
"Rust.ml" 421 16040 16076 "Rust.ml" 421 16040 16108
type(
  string
)
"Rust.ml" 422 16109 16121 "Rust.ml" 422 16109 16122
type(
  API.enum
)
"Rust.ml" 422 16109 16115 "Rust.ml" 422 16109 16122
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 425 16232 16240 "Rust.ml" 425 16232 16247
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 425 16232 16248 "Rust.ml" 425 16232 16306
type(
  (string -> string, unit, string) format
)
"Rust.ml" 426 16307 16317 "Rust.ml" 426 16307 16325
type(
  string
)
ident(
  int_ref ret_type "Rust.ml" 404 15297 15303 "Rust.ml" 404 15297 15311
)
"Rust.ml" 425 16232 16240 "Rust.ml" 426 16307 16325
type(
  string
)
"Rust.ml" 406 15354 15358 "Rust.ml" 426 16307 16325
type(
  string
)
"Rust.ml" 428 16331 16336 "Rust.ml" 428 16331 16340
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 403 15270 15290 "Rust.ml" 403 15270 15294
)
"Rust.ml" 428 16331 16336 "Rust.ml" 428 16331 16354
type(
  bool
)
"Rust.ml" 429 16362 16373 "Rust.ml" 429 16362 16377
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 403 15270 15290 "Rust.ml" 403 15270 15294
)
"Rust.ml" 429 16362 16373 "Rust.ml" 429 16362 16381
type(
  API.ret
)
"Rust.ml" 430 16387 16393 "Rust.ml" 430 16387 16398
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 430 16387 16401 "Rust.ml" 430 16387 16405
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 430 16387 16393 "Rust.ml" 430 16387 16405
type(
  API.ret
)
"Rust.ml" 430 16387 16408 "Rust.ml" 430 16387 16412
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 430 16387 16393 "Rust.ml" 430 16387 16412
type(
  API.ret
)
"Rust.ml" 430 16387 16415 "Rust.ml" 430 16387 16418
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 430 16387 16393 "Rust.ml" 430 16387 16418
type(
  API.ret
)
"Rust.ml" 430 16387 16421 "Rust.ml" 430 16387 16427
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 430 16387 16393 "Rust.ml" 430 16387 16427
type(
  API.ret
)
"Rust.ml" 430 16387 16430 "Rust.ml" 430 16387 16437
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 430 16387 16393 "Rust.ml" 430 16387 16437
type(
  API.ret
)
"Rust.ml" 430 16387 16440 "Rust.ml" 430 16387 16446
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 430 16387 16393 "Rust.ml" 430 16387 16446
type(
  API.ret
)
"Rust.ml" 431 16450 16458 "Rust.ml" 431 16450 16460
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 431 16450 16461 "Rust.ml" 431 16450 16481
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 431 16450 16458 "Rust.ml" 431 16450 16481
type(
  unit
)
"Rust.ml" 432 16483 16491 "Rust.ml" 432 16483 16493
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 432 16483 16494 "Rust.ml" 432 16483 16553
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 432 16483 16491 "Rust.ml" 432 16483 16553
type(
  unit
)
"Rust.ml" 433 16555 16563 "Rust.ml" 433 16555 16565
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 433 16555 16566 "Rust.ml" 433 16555 16571
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 433 16555 16563 "Rust.ml" 433 16555 16571
type(
  unit
)
"Rust.ml" 432 16483 16491 "Rust.ml" 433 16555 16571
type(
  unit
)
"Rust.ml" 431 16450 16458 "Rust.ml" 433 16555 16571
type(
  unit
)
"Rust.ml" 434 16572 16578 "Rust.ml" 434 16572 16591
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 434 16572 16594 "Rust.ml" 434 16572 16601
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 434 16572 16578 "Rust.ml" 434 16572 16601
type(
  API.ret
)
"Rust.ml" 435 16605 16613 "Rust.ml" 435 16605 16615
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 435 16605 16616 "Rust.ml" 435 16605 16642
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 435 16605 16613 "Rust.ml" 435 16605 16642
type(
  unit
)
"Rust.ml" 436 16644 16652 "Rust.ml" 436 16644 16654
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 436 16644 16655 "Rust.ml" 436 16644 16714
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 436 16644 16652 "Rust.ml" 436 16644 16714
type(
  unit
)
"Rust.ml" 437 16716 16724 "Rust.ml" 437 16716 16726
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 437 16716 16727 "Rust.ml" 437 16716 16732
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 437 16716 16724 "Rust.ml" 437 16716 16732
type(
  unit
)
"Rust.ml" 436 16644 16652 "Rust.ml" 437 16716 16732
type(
  unit
)
"Rust.ml" 435 16605 16613 "Rust.ml" 437 16716 16732
type(
  unit
)
"Rust.ml" 438 16733 16739 "Rust.ml" 438 16733 16744
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 438 16733 16747 "Rust.ml" 438 16733 16755
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 438 16733 16739 "Rust.ml" 438 16733 16755
type(
  API.ret
)
"Rust.ml" 438 16733 16758 "Rust.ml" 438 16733 16765
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 438 16733 16739 "Rust.ml" 438 16733 16765
type(
  API.ret
)
"Rust.ml" 438 16733 16774 "Rust.ml" 438 16733 16775
type(
  API.enum
)
"Rust.ml" 438 16733 16768 "Rust.ml" 438 16733 16775
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 438 16733 16739 "Rust.ml" 438 16733 16775
type(
  API.ret
)
"Rust.ml" 438 16733 16785 "Rust.ml" 438 16733 16786
type(
  API.flags
)
"Rust.ml" 438 16733 16778 "Rust.ml" 438 16733 16786
type(
  API.ret
)
type(
  API.ret
)
"Rust.ml" 438 16733 16739 "Rust.ml" 438 16733 16786
type(
  API.ret
)
"Rust.ml" 439 16790 16798 "Rust.ml" 439 16790 16806
type(
  string -> unit
)
ident(
  int_ref Stdlib.failwith "stdlib.mli" 41 1919 1919 "stdlib.mli" 41 1919 1946
)
"Rust.ml" 439 16790 16807 "Rust.ml" 439 16790 16860
type(
  string
)
"Rust.ml" 439 16790 16798 "Rust.ml" 439 16790 16860
type(
  unit
)
"Rust.ml" 429 16362 16366 "Rust.ml" 439 16790 16861
type(
  unit
)
"Rust.ml" 440 16863 16867 "Rust.ml" 440 16863 16869
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 440 16863 16870 "Rust.ml" 440 16863 16889
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 440 16863 16890 "Rust.ml" 440 16863 16899
type(
  string
)
ident(
  int_ref pure_expr "Rust.ml" 405 15336 15342 "Rust.ml" 405 15336 15351
)
"Rust.ml" 440 16863 16867 "Rust.ml" 440 16863 16899
type(
  unit
)
"Rust.ml" 428 16331 16360 "Rust.ml" 440 16863 16900
type(
  unit
)
"Rust.ml" 441 16901 16908 "Rust.ml" 441 16901 16910
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 441 16901 16911 "Rust.ml" 441 16901 16917
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 441 16901 16918 "Rust.ml" 441 16901 16927
type(
  string
)
ident(
  int_ref pure_expr "Rust.ml" 405 15336 15342 "Rust.ml" 405 15336 15351
)
"Rust.ml" 441 16901 16908 "Rust.ml" 441 16901 16927
type(
  unit
)
"Rust.ml" 428 16331 16333 "Rust.ml" 441 16901 16927
type(
  unit
)
"Rust.ml" 405 15336 15338 "Rust.ml" 441 16901 16927
type(
  unit
)
"Rust.ml" 404 15297 15299 "Rust.ml" 441 16901 16927
type(
  unit
)
"Rust.ml" 448 17292 17296 "Rust.ml" 448 17292 17324
type(
  API.closure -> unit
)
ident(
  def print_rust_closure_to_raw_fn "Rust.ml" 479 18615 18615 "Rust.ml" 0 0 -1
)
"Rust.ml" 448 17292 17327 "Rust.ml" 448 17292 17333
type(
  string
)
ident(
  def cbname "Rust.ml" 449 17346 17348 "Rust.ml" 476 18541 18550
)
"Rust.ml" 448 17292 17335 "Rust.ml" 448 17292 17341
type(
  API.cbarg list
)
ident(
  def cbargs "Rust.ml" 449 17346 17348 "Rust.ml" 476 18541 18550
)
"Rust.ml" 448 17292 17325 "Rust.ml" 448 17292 17343
type(
  API.closure
)
"Rust.ml" 449 17346 17352 "Rust.ml" 449 17346 17365
type(
  string
)
ident(
  def closure_trait "Rust.ml" 450 17412 17414 "Rust.ml" 476 18541 18550
)
"Rust.ml" 449 17346 17368 "Rust.ml" 449 17346 17386
type(
  ?lifetime:string option -> API.cbarg list -> string
)
ident(
  int_ref rust_closure_trait "Rust.ml" 157 4857 4861 "Rust.ml" 157 4857 4879
)
"Rust.ml" 449 17346 17387 "Rust.ml" 449 17346 17393
type(
  API.cbarg list
)
ident(
  int_ref cbargs "Rust.ml" 448 17292 17335 "Rust.ml" 448 17292 17341
)
"Rust.ml" 449 17346 17404 "Rust.ml" 449 17346 17408
type(
  string option
)
type(
  string option option
)
"Rust.ml" 449 17346 17368 "Rust.ml" 449 17346 17408
type(
  string
)
"Rust.ml" 450 17412 17418 "Rust.ml" 450 17412 17434
type(
  string list
)
ident(
  def ffi_cbargs_names "Rust.ml" 451 17487 17489 "Rust.ml" 476 18541 18550
)
"Rust.ml" 450 17412 17437 "Rust.ml" 450 17412 17449
type(
  string list list -> string list
)
ident(
  int_ref Stdlib.List.flatten "list.mli" 118 4456 4456 "list.mli" 118 4456 4493
)
"Rust.ml" 450 17412 17451 "Rust.ml" 450 17412 17459
type(
  (API.cbarg -> string list) -> API.cbarg list -> string list list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 450 17412 17460 "Rust.ml" 450 17412 17475
type(
  API.cbarg -> string list
)
ident(
  int_ref ffi_cbarg_names "Rust.ml" 217 7045 7049 "Rust.ml" 217 7045 7064
)
"Rust.ml" 450 17412 17476 "Rust.ml" 450 17412 17482
type(
  API.cbarg list
)
ident(
  int_ref cbargs "Rust.ml" 448 17292 17335 "Rust.ml" 448 17292 17341
)
"Rust.ml" 450 17412 17450 "Rust.ml" 450 17412 17483
type(
  string list list
)
"Rust.ml" 450 17412 17437 "Rust.ml" 450 17412 17483
type(
  string list
)
"Rust.ml" 451 17487 17493 "Rust.ml" 451 17487 17509
type(
  string list
)
ident(
  def ffi_cbargs_types "Rust.ml" 452 17562 17564 "Rust.ml" 476 18541 18550
)
"Rust.ml" 451 17487 17512 "Rust.ml" 451 17487 17524
type(
  string list list -> string list
)
ident(
  int_ref Stdlib.List.flatten "list.mli" 118 4456 4456 "list.mli" 118 4456 4493
)
"Rust.ml" 451 17487 17526 "Rust.ml" 451 17487 17534
type(
  (API.cbarg -> string list) -> API.cbarg list -> string list list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 451 17487 17535 "Rust.ml" 451 17487 17550
type(
  API.cbarg -> string list
)
ident(
  int_ref ffi_cbarg_types "Rust.ml" 227 7614 7618 "Rust.ml" 227 7614 7633
)
"Rust.ml" 451 17487 17551 "Rust.ml" 451 17487 17557
type(
  API.cbarg list
)
ident(
  int_ref cbargs "Rust.ml" 448 17292 17335 "Rust.ml" 448 17292 17341
)
"Rust.ml" 451 17487 17525 "Rust.ml" 451 17487 17558
type(
  string list list
)
"Rust.ml" 451 17487 17512 "Rust.ml" 451 17487 17558
type(
  string list
)
"Rust.ml" 452 17562 17568 "Rust.ml" 452 17562 17585
type(
  string list
)
ident(
  def rust_cbargs_names "Rust.ml" 453 17623 17625 "Rust.ml" 476 18541 18550
)
"Rust.ml" 452 17562 17588 "Rust.ml" 452 17562 17596
type(
  (API.cbarg -> string) -> API.cbarg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 452 17562 17597 "Rust.ml" 452 17562 17612
type(
  API.cbarg -> string
)
ident(
  int_ref rust_cbarg_name "Rust.ml" 126 3776 3780 "Rust.ml" 126 3776 3795
)
"Rust.ml" 452 17562 17613 "Rust.ml" 452 17562 17619
type(
  API.cbarg list
)
ident(
  int_ref cbargs "Rust.ml" 448 17292 17335 "Rust.ml" 448 17292 17341
)
"Rust.ml" 452 17562 17588 "Rust.ml" 452 17562 17619
type(
  string list
)
"Rust.ml" 453 17623 17625 "Rust.ml" 453 17623 17627
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 453 17623 17628 "Rust.ml" 453 17623 17695
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 454 17696 17700 "Rust.ml" 454 17696 17706
type(
  string
)
ident(
  int_ref cbname "Rust.ml" 448 17292 17327 "Rust.ml" 448 17292 17333
)
"Rust.ml" 454 17696 17707 "Rust.ml" 454 17696 17713
type(
  string
)
ident(
  int_ref cbname "Rust.ml" 448 17292 17327 "Rust.ml" 448 17292 17333
)
"Rust.ml" 453 17623 17625 "Rust.ml" 454 17696 17713
type(
  unit
)
"Rust.ml" 455 17715 17717 "Rust.ml" 455 17715 17719
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 455 17715 17720 "Rust.ml" 455 17715 17737
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 455 17715 17738 "Rust.ml" 455 17715 17751
type(
  string
)
ident(
  int_ref closure_trait "Rust.ml" 449 17346 17352 "Rust.ml" 449 17346 17365
)
"Rust.ml" 455 17715 17717 "Rust.ml" 455 17715 17751
type(
  unit
)
"Rust.ml" 456 17753 17755 "Rust.ml" 456 17753 17757
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 456 17753 17758 "Rust.ml" 456 17753 17763
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 456 17753 17755 "Rust.ml" 456 17753 17763
type(
  unit
)
"Rust.ml" 457 17765 17767 "Rust.ml" 457 17765 17769
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 458 17770 17774 "Rust.ml" 459 17846 17859
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 460 17860 17865 "Rust.ml" 460 17860 17878
type(
  string -> string list -> string
)
ident(
  int_ref Stdlib.String.concat "string.mli" 132 5016 5016 "string.mli" 132 5016 5060
)
"Rust.ml" 460 17860 17879 "Rust.ml" 460 17860 17883
type(
  string
)
"Rust.ml" 461 17884 17892 "Rust.ml" 461 17884 17901
type(
  (string -> string -> string) -> string list -> string list -> string list
)
ident(
  int_ref Stdlib.List.map2 "list.mli" 232 7967 7967 "list.mli" 232 7967 8027
)
"Rust.ml" 461 17884 17903 "Rust.ml" 461 17884 17910
type(
  (string -> string -> string, unit, string) format ->
  string -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 461 17884 17911 "Rust.ml" 461 17884 17919
type(
  (string -> string -> string, unit, string) format
)
"Rust.ml" 461 17884 17902 "Rust.ml" 461 17884 17920
type(
  string -> string -> string
)
"Rust.ml" 461 17884 17921 "Rust.ml" 461 17884 17937
type(
  string list
)
ident(
  int_ref ffi_cbargs_names "Rust.ml" 450 17412 17418 "Rust.ml" 450 17412 17434
)
"Rust.ml" 461 17884 17938 "Rust.ml" 461 17884 17954
type(
  string list
)
ident(
  int_ref ffi_cbargs_types "Rust.ml" 451 17487 17493 "Rust.ml" 451 17487 17509
)
"Rust.ml" 461 17884 17891 "Rust.ml" 461 17884 17955
type(
  string list
)
"Rust.ml" 460 17860 17864 "Rust.ml" 461 17884 17956
type(
  string
)
"Rust.ml" 457 17765 17767 "Rust.ml" 461 17884 17956
type(
  unit
)
"Rust.ml" 462 17958 17960 "Rust.ml" 462 17958 17962
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 462 17958 17963 "Rust.ml" 462 17958 17984
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 462 17958 17985 "Rust.ml" 462 17958 17998
type(
  string
)
ident(
  int_ref closure_trait "Rust.ml" 449 17346 17352 "Rust.ml" 449 17346 17365
)
"Rust.ml" 462 17958 17960 "Rust.ml" 462 17958 17998
type(
  unit
)
"Rust.ml" 463 18000 18002 "Rust.ml" 463 18000 18004
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 463 18000 18005 "Rust.ml" 463 18000 18014
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 463 18000 18002 "Rust.ml" 463 18000 18014
type(
  unit
)
"Rust.ml" 464 18016 18018 "Rust.ml" 464 18016 18020
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 464 18016 18021 "Rust.ml" 464 18016 18067
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 464 18016 18018 "Rust.ml" 464 18016 18067
type(
  unit
)
"Rust.ml" 465 18069 18071 "Rust.ml" 465 18069 18073
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 465 18069 18074 "Rust.ml" 465 18069 18120
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 465 18069 18071 "Rust.ml" 465 18069 18120
type(
  unit
)
"Rust.ml" 466 18122 18124 "Rust.ml" 466 18122 18133
type(
  (API.cbarg -> unit) -> API.cbarg list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 466 18122 18134 "Rust.ml" 466 18122 18152
type(
  API.cbarg -> unit
)
ident(
  int_ref ffi_cbargs_to_rust "Rust.ml" 369 13719 13723 "Rust.ml" 369 13719 13741
)
"Rust.ml" 466 18122 18153 "Rust.ml" 466 18122 18159
type(
  API.cbarg list
)
ident(
  int_ref cbargs "Rust.ml" 448 17292 17335 "Rust.ml" 448 17292 17341
)
"Rust.ml" 466 18122 18124 "Rust.ml" 466 18122 18159
type(
  unit
)
"Rust.ml" 467 18161 18163 "Rust.ml" 467 18161 18165
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 467 18161 18166 "Rust.ml" 467 18161 18190
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 467 18161 18192 "Rust.ml" 467 18161 18205
type(
  string -> string list -> string
)
ident(
  int_ref Stdlib.String.concat "string.mli" 132 5016 5016 "string.mli" 132 5016 5060
)
"Rust.ml" 467 18161 18206 "Rust.ml" 467 18161 18210
type(
  string
)
"Rust.ml" 467 18161 18211 "Rust.ml" 467 18161 18228
type(
  string list
)
ident(
  int_ref rust_cbargs_names "Rust.ml" 452 17562 17568 "Rust.ml" 452 17562 17585
)
"Rust.ml" 467 18161 18191 "Rust.ml" 467 18161 18229
type(
  string
)
"Rust.ml" 467 18161 18163 "Rust.ml" 467 18161 18229
type(
  unit
)
"Rust.ml" 468 18231 18233 "Rust.ml" 468 18231 18235
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 468 18231 18236 "Rust.ml" 468 18231 18245
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 468 18231 18233 "Rust.ml" 468 18231 18245
type(
  unit
)
"Rust.ml" 469 18247 18249 "Rust.ml" 469 18247 18251
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 469 18247 18252 "Rust.ml" 469 18247 18307
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 469 18247 18249 "Rust.ml" 469 18247 18307
type(
  unit
)
"Rust.ml" 470 18309 18311 "Rust.ml" 470 18309 18313
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 470 18309 18314 "Rust.ml" 470 18309 18344
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 470 18309 18345 "Rust.ml" 470 18309 18351
type(
  string
)
ident(
  int_ref cbname "Rust.ml" 448 17292 17327 "Rust.ml" 448 17292 17333
)
"Rust.ml" 470 18309 18311 "Rust.ml" 470 18309 18351
type(
  unit
)
"Rust.ml" 471 18353 18355 "Rust.ml" 471 18353 18357
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 471 18353 18358 "Rust.ml" 471 18353 18404
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 471 18353 18355 "Rust.ml" 471 18353 18404
type(
  unit
)
"Rust.ml" 472 18406 18408 "Rust.ml" 472 18406 18410
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 472 18406 18411 "Rust.ml" 472 18406 18458
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 472 18406 18408 "Rust.ml" 472 18406 18458
type(
  unit
)
"Rust.ml" 473 18460 18462 "Rust.ml" 473 18460 18464
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 473 18460 18465 "Rust.ml" 473 18460 18511
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 473 18460 18462 "Rust.ml" 473 18460 18511
type(
  unit
)
"Rust.ml" 474 18513 18515 "Rust.ml" 474 18513 18517
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 474 18513 18518 "Rust.ml" 474 18513 18527
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 474 18513 18515 "Rust.ml" 474 18513 18527
type(
  unit
)
"Rust.ml" 475 18529 18531 "Rust.ml" 475 18529 18533
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 475 18529 18534 "Rust.ml" 475 18529 18539
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 475 18529 18531 "Rust.ml" 475 18529 18539
type(
  unit
)
"Rust.ml" 476 18541 18543 "Rust.ml" 476 18541 18545
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 476 18541 18546 "Rust.ml" 476 18541 18550
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 476 18541 18543 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 475 18529 18531 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 474 18513 18515 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 473 18460 18462 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 472 18406 18408 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 471 18353 18355 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 470 18309 18311 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 469 18247 18249 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 468 18231 18233 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 467 18161 18163 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 466 18122 18124 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 465 18069 18071 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 464 18016 18018 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 463 18000 18002 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 462 17958 17960 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 457 17765 17767 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 456 17753 17755 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 455 17715 17717 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 453 17623 17625 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 452 17562 17564 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 451 17487 17489 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 450 17412 17414 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 449 17346 17348 "Rust.ml" 476 18541 18550
type(
  unit
)
"Rust.ml" 479 18615 18623 "Rust.ml" 479 18615 18653
type(
  string -> API.call -> unit
)
ident(
  def print_rust_handle_call_comment "Rust.ml" 479 18615 18615 "Rust.ml" 0 0 -1
)
"Rust.ml" 479 18615 18654 "Rust.ml" 479 18615 18658
type(
  string
)
ident(
  def name "Rust.ml" 479 18615 18659 "Rust.ml" 490 19086 19089
)
"Rust.ml" 479 18615 18659 "Rust.ml" 479 18615 18663
type(
  API.call
)
ident(
  def call "Rust.ml" 481 18690 18692 "Rust.ml" 490 19086 19089
)
"Rust.ml" 481 18690 18695 "Rust.ml" 481 18690 18699
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 479 18615 18659 "Rust.ml" 479 18615 18663
)
"Rust.ml" 481 18690 18695 "Rust.ml" 481 18690 18709
type(
  string
)
"Rust.ml" 481 18690 18710 "Rust.ml" 481 18690 18712
type(
  string -> string -> bool
)
ident(
  int_ref Stdlib.( <> ) "stdlib.mli" 130 5559 5559 "stdlib.mli" 130 5559 5607
)
"Rust.ml" 481 18690 18713 "Rust.ml" 481 18690 18715
type(
  string
)
"Rust.ml" 481 18690 18695 "Rust.ml" 481 18690 18715
type(
  bool
)
"Rust.ml" 482 18721 18725 "Rust.ml" 482 18721 18727
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 482 18721 18728 "Rust.ml" 482 18721 18738
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 483 18739 18746 "Rust.ml" 483 18739 18759
type(
  string -> string list -> string
)
ident(
  int_ref Stdlib.String.concat "string.mli" 132 5016 5016 "string.mli" 132 5016 5060
)
"Rust.ml" 483 18739 18760 "Rust.ml" 483 18739 18768
type(
  string
)
"Rust.ml" 483 18739 18770 "Rust.ml" 483 18739 18790
type(
  char -> string -> string list
)
ident(
  int_ref Stdlib.String.split_on_char "string.mli" 198 7175 7175 "string.mli" 198 7175 7224
)
"Rust.ml" 483 18739 18791 "Rust.ml" 483 18739 18795
type(
  char
)
"Rust.ml" 483 18739 18796 "Rust.ml" 483 18739 18800
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 479 18615 18659 "Rust.ml" 479 18615 18663
)
"Rust.ml" 483 18739 18796 "Rust.ml" 483 18739 18810
type(
  string
)
"Rust.ml" 483 18739 18769 "Rust.ml" 483 18739 18811
type(
  string list
)
"Rust.ml" 483 18739 18745 "Rust.ml" 483 18739 18812
type(
  string
)
"Rust.ml" 482 18721 18725 "Rust.ml" 483 18739 18812
type(
  unit
)
"Rust.ml" 481 18690 18692 "Rust.ml" 483 18739 18812
type(
  unit
)
"Rust.ml" 484 18814 18819 "Rust.ml" 484 18814 18823
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 479 18615 18659 "Rust.ml" 479 18615 18663
)
"Rust.ml" 484 18814 18819 "Rust.ml" 484 18814 18832
type(
  string
)
"Rust.ml" 484 18814 18833 "Rust.ml" 484 18814 18835
type(
  string -> string -> bool
)
ident(
  int_ref Stdlib.( <> ) "stdlib.mli" 130 5559 5559 "stdlib.mli" 130 5559 5607
)
"Rust.ml" 484 18814 18836 "Rust.ml" 484 18814 18838
type(
  string
)
"Rust.ml" 484 18814 18819 "Rust.ml" 484 18814 18838
type(
  bool
)
"Rust.ml" 487 18951 18958 "Rust.ml" 487 18951 18962
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 479 18615 18659 "Rust.ml" 479 18615 18663
)
"Rust.ml" 487 18951 18958 "Rust.ml" 487 18951 18972
type(
  string
)
"Rust.ml" 487 18951 18973 "Rust.ml" 487 18951 18975
type(
  string -> string -> bool
)
ident(
  int_ref Stdlib.( <> ) "stdlib.mli" 130 5559 5559 "stdlib.mli" 130 5559 5607
)
"Rust.ml" 487 18951 18976 "Rust.ml" 487 18951 18978
type(
  string
)
"Rust.ml" 487 18951 18958 "Rust.ml" 487 18951 18978
type(
  bool
)
"Rust.ml" 487 18951 18984 "Rust.ml" 487 18951 18986
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 487 18951 18987 "Rust.ml" 487 18951 18995
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 487 18951 18984 "Rust.ml" 487 18951 18995
type(
  unit
)
"Rust.ml" 487 18951 18955 "Rust.ml" 487 18951 18995
type(
  unit
)
"Rust.ml" 488 18997 19005 "Rust.ml" 488 18997 19007
type(
  string list
)
ident(
  def md "Rust.ml" 489 19053 19057 "Rust.ml" 489 19053 19085
)
"Rust.ml" 488 18997 19010 "Rust.ml" 488 18997 19030
type(
  string -> string -> string list
)
ident(
  int_ref longdesc_to_markdown "Rust.ml" 493 19130 19134 "Rust.ml" 493 19130 19154
)
"Rust.ml" 488 18997 19031 "Rust.ml" 488 18997 19035
type(
  string
)
ident(
  int_ref name "Rust.ml" 479 18615 18654 "Rust.ml" 479 18615 18658
)
"Rust.ml" 488 18997 19036 "Rust.ml" 488 18997 19040
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 479 18615 18659 "Rust.ml" 479 18615 18663
)
"Rust.ml" 488 18997 19036 "Rust.ml" 488 18997 19049
type(
  string
)
"Rust.ml" 488 18997 19010 "Rust.ml" 488 18997 19049
type(
  string list
)
"Rust.ml" 489 19053 19057 "Rust.ml" 489 19053 19066
type(
  (string -> unit) -> string list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 489 19053 19068 "Rust.ml" 489 19053 19070
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 489 19053 19071 "Rust.ml" 489 19053 19081
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 489 19053 19067 "Rust.ml" 489 19053 19082
type(
  string -> unit
)
"Rust.ml" 489 19053 19083 "Rust.ml" 489 19053 19085
type(
  string list
)
ident(
  int_ref md "Rust.ml" 488 18997 19005 "Rust.ml" 488 18997 19007
)
"Rust.ml" 489 19053 19057 "Rust.ml" 489 19053 19085
type(
  unit
)
"Rust.ml" 488 18997 19001 "Rust.ml" 489 19053 19085
type(
  unit
)
"Rust.ml" 484 18814 18844 "Rust.ml" 490 19086 19089
type(
  unit
)
"Rust.ml" 484 18814 18816 "Rust.ml" 490 19086 19089
type(
  unit
)
"Rust.ml" 481 18690 18692 "Rust.ml" 490 19086 19089
type(
  unit
)
"Rust.ml" 493 19130 19134 "Rust.ml" 493 19130 19154
type(
  string -> string -> string list
)
ident(
  def longdesc_to_markdown "Rust.ml" 479 18615 18615 "Rust.ml" 0 0 -1
)
"Rust.ml" 493 19130 19155 "Rust.ml" 493 19130 19159
type(
  string
)
ident(
  def name "Rust.ml" 493 19130 19160 "Rust.ml" 563 21892 21901
)
"Rust.ml" 493 19130 19160 "Rust.ml" 493 19130 19168
type(
  string
)
ident(
  def longdesc "Rust.ml" 495 19209 19211 "Rust.ml" 563 21892 21901
)
"Rust.ml" 495 19209 19215 "Rust.ml" 495 19209 19222
type(
  string
)
ident(
  def content "Rust.ml" 527 20570 20572 "Rust.ml" 563 21892 21901
)
"Rust.ml" 496 19225 19229 "Rust.ml" 496 19225 19250
type(
  Str.regexp -> (string -> string) -> string -> string
)
ident(
  int_ref Str.global_substitute "str.mli" 207 9372 9372 "str.mli" 207 9372 9444
)
"Rust.ml" 496 19225 19252 "Rust.ml" 496 19225 19262
type(
  string -> Str.regexp
)
ident(
  int_ref Str.regexp "str.mli" 26 1237 1237 "str.mli" 26 1237 1266
)
"Rust.ml" 496 19225 19263 "Rust.ml" 496 19225 19280
type(
  string
)
"Rust.ml" 496 19225 19251 "Rust.ml" 496 19225 19281
type(
  Str.regexp
)
"Rust.ml" 497 19282 19293 "Rust.ml" 497 19282 19294
type(
  string
)
ident(
  def s "Rust.ml" 498 19298 19306 "Rust.ml" 522 20414 20483
)
"Rust.ml" 498 19298 19310 "Rust.ml" 498 19298 19314
type(
  string
)
ident(
  def expr "Rust.ml" 499 19341 19349 "Rust.ml" 522 20414 20483
)
"Rust.ml" 498 19298 19317 "Rust.ml" 498 19298 19335
type(
  string -> string
)
ident(
  int_ref Str.matched_string "str.mli" 116 5415 5415 "str.mli" 116 5415 5452
)
"Rust.ml" 498 19298 19336 "Rust.ml" 498 19298 19337
type(
  string
)
ident(
  int_ref s "Rust.ml" 497 19282 19293 "Rust.ml" 497 19282 19294
)
"Rust.ml" 498 19298 19317 "Rust.ml" 498 19298 19337
type(
  string
)
"Rust.ml" 499 19341 19353 "Rust.ml" 499 19341 19356
type(
  int
)
ident(
  def len "Rust.ml" 500 19381 19389 "Rust.ml" 522 20414 20483
)
"Rust.ml" 499 19341 19359 "Rust.ml" 499 19341 19372
type(
  string -> int
)
ident(
  int_ref Stdlib.String.length "string.mli" 118 4569 4569 "string.mli" 118 4569 4619
)
"Rust.ml" 499 19341 19373 "Rust.ml" 499 19341 19377
type(
  string
)
ident(
  int_ref expr "Rust.ml" 498 19298 19310 "Rust.ml" 498 19298 19314
)
"Rust.ml" 499 19341 19359 "Rust.ml" 499 19341 19377
type(
  int
)
"Rust.ml" 500 19381 19393 "Rust.ml" 500 19381 19394
type(
  char
)
ident(
  def c "Rust.ml" 501 19449 19457 "Rust.ml" 522 20414 20483
)
"Rust.ml" 500 19381 19397 "Rust.ml" 500 19381 19401
type(
  string
)
ident(
  int_ref expr "Rust.ml" 498 19298 19310 "Rust.ml" 498 19298 19314
)
"Rust.ml" 500 19381 19403 "Rust.ml" 500 19381 19404
type(
  int
)
"Rust.ml" 500 19381 19397 "Rust.ml" 500 19381 19405
type(
  char
)
"Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
type(
  string
)
ident(
  def content "Rust.ml" 501 19449 19457 "Rust.ml" 522 20414 20483
)
"Rust.ml" 500 19381 19420 "Rust.ml" 500 19381 19430
type(
  string -> int -> int -> string
)
ident(
  int_ref Stdlib.String.sub "string.mli" 190 6894 6894 "string.mli" 190 6894 6934
)
"Rust.ml" 500 19381 19431 "Rust.ml" 500 19381 19435
type(
  string
)
ident(
  int_ref expr "Rust.ml" 498 19298 19310 "Rust.ml" 498 19298 19314
)
"Rust.ml" 500 19381 19436 "Rust.ml" 500 19381 19437
type(
  int
)
"Rust.ml" 500 19381 19439 "Rust.ml" 500 19381 19442
type(
  int
)
ident(
  int_ref len "Rust.ml" 499 19341 19353 "Rust.ml" 499 19341 19356
)
"Rust.ml" 500 19381 19442 "Rust.ml" 500 19381 19443
type(
  int -> int -> int
)
ident(
  int_ref Stdlib.( - ) "stdlib.mli" 352 13775 13775 "stdlib.mli" 352 13775 13821
)
"Rust.ml" 500 19381 19443 "Rust.ml" 500 19381 19444
type(
  int
)
"Rust.ml" 500 19381 19438 "Rust.ml" 500 19381 19445
type(
  int
)
"Rust.ml" 500 19381 19420 "Rust.ml" 500 19381 19445
type(
  string
)
"Rust.ml" 501 19449 19463 "Rust.ml" 501 19449 19464
type(
  char
)
ident(
  int_ref c "Rust.ml" 500 19381 19393 "Rust.ml" 500 19381 19394
)
"Rust.ml" 502 19470 19480 "Rust.ml" 502 19470 19483
type(
  char
)
type(
  char
)
"Rust.ml" 502 19470 19487 "Rust.ml" 502 19470 19494
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 502 19470 19495 "Rust.ml" 502 19470 19501
type(
  (string -> string, unit, string) format
)
"Rust.ml" 502 19470 19502 "Rust.ml" 502 19470 19509
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 502 19470 19487 "Rust.ml" 502 19470 19509
type(
  string
)
"Rust.ml" 503 19537 19547 "Rust.ml" 503 19537 19550
type(
  char
)
type(
  char
)
"Rust.ml" 503 19537 19554 "Rust.ml" 503 19537 19561
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 503 19537 19562 "Rust.ml" 503 19537 19573
type(
  (string -> string, unit, string) format
)
"Rust.ml" 503 19537 19574 "Rust.ml" 503 19537 19581
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 503 19537 19554 "Rust.ml" 503 19537 19581
type(
  string
)
"Rust.ml" 504 19582 19592 "Rust.ml" 504 19582 19595
type(
  char
)
type(
  char
)
"Rust.ml" 504 19582 19598 "Rust.ml" 504 19582 19601
type(
  char
)
type(
  char
)
"Rust.ml" 504 19582 19592 "Rust.ml" 504 19582 19601
type(
  char
)
"Rust.ml" 504 19582 19605 "Rust.ml" 504 19582 19612
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 504 19582 19613 "Rust.ml" 504 19582 19624
type(
  (string -> string, unit, string) format
)
"Rust.ml" 504 19582 19625 "Rust.ml" 504 19582 19632
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 504 19582 19605 "Rust.ml" 504 19582 19632
type(
  string
)
"Rust.ml" 505 19633 19643 "Rust.ml" 505 19633 19646
type(
  char
)
type(
  char
)
"Rust.ml" 505 19633 19650 "Rust.ml" 505 19633 19657
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 505 19633 19658 "Rust.ml" 505 19633 19664
type(
  (string -> string, unit, string) format
)
"Rust.ml" 505 19633 19665 "Rust.ml" 505 19633 19672
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 505 19633 19650 "Rust.ml" 505 19633 19672
type(
  string
)
"Rust.ml" 506 19673 19683 "Rust.ml" 506 19673 19686
type(
  char
)
type(
  char
)
"Rust.ml" 507 19690 19705 "Rust.ml" 507 19690 19708
type(
  int
)
ident(
  def len "Rust.ml" 508 19736 19747 "Rust.ml" 519 20285 20325
)
"Rust.ml" 507 19690 19711 "Rust.ml" 507 19690 19724
type(
  string -> int
)
ident(
  int_ref Stdlib.String.length "string.mli" 118 4569 4569 "string.mli" 118 4569 4619
)
"Rust.ml" 507 19690 19725 "Rust.ml" 507 19690 19732
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 507 19690 19711 "Rust.ml" 507 19690 19732
type(
  int
)
"Rust.ml" 508 19736 19750 "Rust.ml" 508 19736 19768
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 508 19736 19777 "Rust.ml" 508 19736 19783
type(
  string
)
"Rust.ml" 508 19736 19784 "Rust.ml" 508 19736 19791
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 508 19736 19750 "Rust.ml" 508 19736 19791
type(
  bool
)
"Rust.ml" 509 19799 19816 "Rust.ml" 509 19799 19817
type(
  string
)
ident(
  def n "Rust.ml" 510 19854 19867 "Rust.ml" 513 19992 20023
)
"Rust.ml" 509 19799 19820 "Rust.ml" 509 19799 19830
type(
  string -> int -> int -> string
)
ident(
  int_ref Stdlib.String.sub "string.mli" 190 6894 6894 "string.mli" 190 6894 6934
)
"Rust.ml" 509 19799 19831 "Rust.ml" 509 19799 19838
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 509 19799 19839 "Rust.ml" 509 19799 19840
type(
  int
)
"Rust.ml" 509 19799 19842 "Rust.ml" 509 19799 19845
type(
  int
)
ident(
  int_ref len "Rust.ml" 507 19690 19705 "Rust.ml" 507 19690 19708
)
"Rust.ml" 509 19799 19846 "Rust.ml" 509 19799 19847
type(
  int -> int -> int
)
ident(
  int_ref Stdlib.( - ) "stdlib.mli" 352 13775 13775 "stdlib.mli" 352 13775 13821
)
"Rust.ml" 509 19799 19848 "Rust.ml" 509 19799 19849
type(
  int
)
"Rust.ml" 509 19799 19841 "Rust.ml" 509 19799 19850
type(
  int
)
"Rust.ml" 509 19799 19820 "Rust.ml" 509 19799 19850
type(
  string
)
"Rust.ml" 510 19854 19870 "Rust.ml" 510 19854 19871
type(
  string
)
ident(
  int_ref n "Rust.ml" 509 19799 19816 "Rust.ml" 509 19799 19817
)
"Rust.ml" 510 19854 19872 "Rust.ml" 510 19854 19874
type(
  string -> string -> bool
)
ident(
  int_ref Stdlib.( <> ) "stdlib.mli" 130 5559 5559 "stdlib.mli" 130 5559 5607
)
"Rust.ml" 510 19854 19875 "Rust.ml" 510 19854 19886
type(
  string
)
"Rust.ml" 510 19854 19870 "Rust.ml" 510 19854 19886
type(
  bool
)
"Rust.ml" 510 19854 19887 "Rust.ml" 510 19854 19889
type(
  bool -> bool -> bool
)
ident(
  int_ref Stdlib.( && ) "stdlib.mli" 214 8960 8960 "stdlib.mli" 214 8960 9011
)
"Rust.ml" 510 19854 19890 "Rust.ml" 510 19854 19891
type(
  string
)
ident(
  int_ref n "Rust.ml" 509 19799 19816 "Rust.ml" 509 19799 19817
)
"Rust.ml" 510 19854 19892 "Rust.ml" 510 19854 19894
type(
  string -> string -> bool
)
ident(
  int_ref Stdlib.( <> ) "stdlib.mli" 130 5559 5559 "stdlib.mli" 130 5559 5607
)
"Rust.ml" 510 19854 19895 "Rust.ml" 510 19854 19906
type(
  string
)
"Rust.ml" 510 19854 19890 "Rust.ml" 510 19854 19906
type(
  bool
)
"Rust.ml" 510 19854 19907 "Rust.ml" 510 19854 19909
type(
  bool -> bool -> bool
)
ident(
  int_ref Stdlib.( && ) "stdlib.mli" 214 8960 8960 "stdlib.mli" 214 8960 9011
)
"Rust.ml" 510 19854 19910 "Rust.ml" 510 19854 19911
type(
  string
)
ident(
  int_ref n "Rust.ml" 509 19799 19816 "Rust.ml" 509 19799 19817
)
"Rust.ml" 510 19854 19912 "Rust.ml" 510 19854 19914
type(
  string -> string -> bool
)
ident(
  int_ref Stdlib.( <> ) "stdlib.mli" 130 5559 5559 "stdlib.mli" 130 5559 5607
)
"Rust.ml" 510 19854 19915 "Rust.ml" 510 19854 19922
type(
  string
)
"Rust.ml" 510 19854 19910 "Rust.ml" 510 19854 19922
type(
  bool
)
"Rust.ml" 510 19854 19890 "Rust.ml" 510 19854 19922
type(
  bool
)
"Rust.ml" 510 19854 19870 "Rust.ml" 510 19854 19922
type(
  bool
)
"Rust.ml" 511 19928 19943 "Rust.ml" 511 19928 19950
type(
  (string -> string -> string, unit, string) format ->
  string -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 511 19928 19951 "Rust.ml" 511 19928 19969
type(
  (string -> string -> string, unit, string) format
)
"Rust.ml" 511 19928 19970 "Rust.ml" 511 19928 19971
type(
  string
)
ident(
  int_ref n "Rust.ml" 509 19799 19816 "Rust.ml" 509 19799 19817
)
"Rust.ml" 511 19928 19972 "Rust.ml" 511 19928 19973
type(
  string
)
ident(
  int_ref n "Rust.ml" 509 19799 19816 "Rust.ml" 509 19799 19817
)
"Rust.ml" 511 19928 19943 "Rust.ml" 511 19928 19973
type(
  string
)
"Rust.ml" 513 19992 20007 "Rust.ml" 513 19992 20014
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 513 19992 20015 "Rust.ml" 513 19992 20021
type(
  (string -> string, unit, string) format
)
"Rust.ml" 513 19992 20022 "Rust.ml" 513 19992 20023
type(
  string
)
ident(
  int_ref n "Rust.ml" 509 19799 19816 "Rust.ml" 509 19799 19817
)
"Rust.ml" 513 19992 20007 "Rust.ml" 513 19992 20023
type(
  string
)
"Rust.ml" 510 19854 19867 "Rust.ml" 513 19992 20023
type(
  string
)
"Rust.ml" 508 19736 19797 "Rust.ml" 514 20024 20036
type(
  string
)
"Rust.ml" 515 20037 20056 "Rust.ml" 515 20037 20074
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 515 20037 20083 "Rust.ml" 515 20037 20092
type(
  string
)
"Rust.ml" 515 20037 20093 "Rust.ml" 515 20037 20100
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 515 20037 20056 "Rust.ml" 515 20037 20100
type(
  bool
)
"Rust.ml" 515 20037 20101 "Rust.ml" 515 20037 20103
type(
  bool -> bool -> bool
)
ident(
  int_ref Stdlib.( || ) "stdlib.mli" 227 9492 9492 "stdlib.mli" 227 9492 9542
)
"Rust.ml" 516 20104 20125 "Rust.ml" 516 20104 20143
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 516 20104 20152 "Rust.ml" 516 20104 20162
type(
  string
)
"Rust.ml" 516 20104 20163 "Rust.ml" 516 20104 20170
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 516 20104 20125 "Rust.ml" 516 20104 20170
type(
  bool
)
"Rust.ml" 515 20037 20056 "Rust.ml" 516 20104 20170
type(
  bool
)
"Rust.ml" 517 20176 20189 "Rust.ml" 517 20176 20196
type(
  (string -> string -> string, unit, string) format ->
  string -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 517 20176 20197 "Rust.ml" 517 20176 20207
type(
  (string -> string -> string, unit, string) format
)
"Rust.ml" 517 20176 20208 "Rust.ml" 517 20176 20215
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 517 20176 20216 "Rust.ml" 517 20176 20223
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 517 20176 20189 "Rust.ml" 517 20176 20223
type(
  string
)
"Rust.ml" 519 20285 20298 "Rust.ml" 519 20285 20305
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 519 20285 20306 "Rust.ml" 519 20285 20317
type(
  (string -> string, unit, string) format
)
"Rust.ml" 519 20285 20318 "Rust.ml" 519 20285 20325
type(
  string
)
ident(
  int_ref content "Rust.ml" 500 19381 19410 "Rust.ml" 500 19381 19417
)
"Rust.ml" 519 20285 20298 "Rust.ml" 519 20285 20325
type(
  string
)
"Rust.ml" 515 20037 20053 "Rust.ml" 519 20285 20325
type(
  string
)
"Rust.ml" 508 19736 19747 "Rust.ml" 519 20285 20325
type(
  string
)
"Rust.ml" 507 19690 19701 "Rust.ml" 519 20285 20325
type(
  string
)
"Rust.ml" 520 20326 20336 "Rust.ml" 520 20326 20337
type(
  char
)
type(
  char
)
"Rust.ml" 521 20341 20352 "Rust.ml" 521 20341 20361
type(
  (string -> string -> string, unit, string, string) format4 ->
  string -> string -> string
)
ident(
  int_ref Utils.failwithf "utils.mli" 34 1151 1151 "utils.mli" 34 1151 1203
)
"Rust.ml" 521 20341 20362 "Rust.ml" 522 20414 20473
type(
  (string -> string -> string, unit, string, string) format4
)
"Rust.ml" 522 20414 20474 "Rust.ml" 522 20414 20478
type(
  string
)
ident(
  int_ref name "Rust.ml" 493 19130 19155 "Rust.ml" 493 19130 19159
)
"Rust.ml" 522 20414 20479 "Rust.ml" 522 20414 20483
type(
  string
)
ident(
  int_ref expr "Rust.ml" 498 19298 19310 "Rust.ml" 498 19298 19314
)
"Rust.ml" 521 20341 20352 "Rust.ml" 522 20414 20483
type(
  string
)
"Rust.ml" 501 19449 19457 "Rust.ml" 522 20414 20483
type(
  string
)
"Rust.ml" 500 19381 19389 "Rust.ml" 522 20414 20483
type(
  string
)
"Rust.ml" 499 19341 19349 "Rust.ml" 522 20414 20483
type(
  string
)
"Rust.ml" 498 19298 19306 "Rust.ml" 522 20414 20483
type(
  string
)
"Rust.ml" 497 19282 19288 "Rust.ml" 523 20484 20491
type(
  string -> string
)
"Rust.ml" 524 20492 20498 "Rust.ml" 524 20492 20506
type(
  string
)
ident(
  int_ref longdesc "Rust.ml" 493 19130 19160 "Rust.ml" 493 19130 19168
)
"Rust.ml" 496 19225 19229 "Rust.ml" 524 20492 20506
type(
  string
)
"Rust.ml" 527 20570 20576 "Rust.ml" 527 20570 20581
type(
  string list
)
ident(
  def lines "Rust.ml" 530 20682 20684 "Rust.ml" 563 21892 21901
)
"Rust.ml" 527 20570 20584 "Rust.ml" 527 20570 20590
type(
  string -> string -> string list
)
ident(
  int_ref Utils.nsplit "utils.mli" 42 1495 1495 "utils.mli" 42 1495 1539
)
"Rust.ml" 527 20570 20591 "Rust.ml" 527 20570 20595
type(
  string
)
"Rust.ml" 527 20570 20596 "Rust.ml" 527 20570 20603
type(
  string
)
ident(
  int_ref content "Rust.ml" 495 19209 19215 "Rust.ml" 495 19209 19222
)
"Rust.ml" 527 20570 20584 "Rust.ml" 527 20570 20603
type(
  string list
)
"Rust.ml" 530 20682 20688 "Rust.ml" 530 20682 20693
type(
  (bool * string) list
)
ident(
  def lines "Rust.ml" 532 20774 20776 "Rust.ml" 563 21892 21901
)
"Rust.ml" 531 20696 20700 "Rust.ml" 531 20696 20708
type(
  (string -> bool * string) -> string list -> (bool * string) list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 531 20696 20714 "Rust.ml" 531 20696 20718
type(
  string
)
ident(
  def line "Rust.ml" 531 20696 20722 "Rust.ml" 531 20696 20763
)
"Rust.ml" 531 20696 20722 "Rust.ml" 531 20696 20740
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 531 20696 20749 "Rust.ml" 531 20696 20752
type(
  string
)
"Rust.ml" 531 20696 20753 "Rust.ml" 531 20696 20757
type(
  string
)
ident(
  int_ref line "Rust.ml" 531 20696 20714 "Rust.ml" 531 20696 20718
)
"Rust.ml" 531 20696 20722 "Rust.ml" 531 20696 20757
type(
  bool
)
"Rust.ml" 531 20696 20759 "Rust.ml" 531 20696 20763
type(
  string
)
ident(
  int_ref line "Rust.ml" 531 20696 20714 "Rust.ml" 531 20696 20718
)
"Rust.ml" 531 20696 20722 "Rust.ml" 531 20696 20763
type(
  bool * string
)
"Rust.ml" 531 20696 20709 "Rust.ml" 531 20696 20764
type(
  string -> bool * string
)
"Rust.ml" 531 20696 20765 "Rust.ml" 531 20696 20770
type(
  string list
)
ident(
  int_ref lines "Rust.ml" 527 20570 20576 "Rust.ml" 527 20570 20581
)
"Rust.ml" 531 20696 20700 "Rust.ml" 531 20696 20770
type(
  (bool * string) list
)
"Rust.ml" 532 20774 20781 "Rust.ml" 532 20774 20786
type(
  (bool * string list) list
)
type(
  (bool * string list) list
)
ident(
  def lines "Rust.ml" 533 20836 20838 "Rust.ml" 563 21892 21901
)
"Rust.ml" 532 20774 20818 "Rust.ml" 532 20774 20826
type(
  (bool * string) list -> (bool * string list) list
)
ident(
  int_ref Utils.group_by "utils.mli" 37 1262 1262 "utils.mli" 37 1262 1314
)
"Rust.ml" 532 20774 20827 "Rust.ml" 532 20774 20832
type(
  (bool * string) list
)
ident(
  int_ref lines "Rust.ml" 530 20682 20688 "Rust.ml" 530 20682 20693
)
"Rust.ml" 532 20774 20818 "Rust.ml" 532 20774 20832
type(
  (bool * string list) list
)
"Rust.ml" 533 20836 20842 "Rust.ml" 533 20836 20847
type(
  string list list
)
ident(
  def lines "Rust.ml" 538 20990 20992 "Rust.ml" 563 21892 21901
)
"Rust.ml" 534 20850 20854 "Rust.ml" 534 20850 20862
type(
  (bool * string list -> string list) ->
  (bool * string list) list -> string list list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 535 20873 20881 "Rust.ml" 535 20873 20885
type(
  bool
)
"Rust.ml" 535 20873 20902 "Rust.ml" 535 20873 20907
type(
  string list
)
ident(
  def lines "Rust.ml" 535 20873 20911 "Rust.ml" 535 20873 20944
)
"Rust.ml" 535 20873 20881 "Rust.ml" 535 20873 20907
type(
  bool * string list
)
"Rust.ml" 535 20873 20913 "Rust.ml" 535 20873 20922
type(
  string
)
"Rust.ml" 535 20873 20911 "Rust.ml" 535 20873 20924
type(
  string list
)
"Rust.ml" 535 20873 20925 "Rust.ml" 535 20873 20926
type(
  string list -> string list -> string list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 535 20873 20927 "Rust.ml" 535 20873 20932
type(
  string list
)
ident(
  int_ref lines "Rust.ml" 535 20873 20902 "Rust.ml" 535 20873 20907
)
"Rust.ml" 535 20873 20933 "Rust.ml" 535 20873 20934
type(
  string list -> string list -> string list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 535 20873 20937 "Rust.ml" 535 20873 20942
type(
  string
)
"Rust.ml" 535 20873 20935 "Rust.ml" 535 20873 20944
type(
  string list
)
"Rust.ml" 535 20873 20927 "Rust.ml" 535 20873 20944
type(
  string list
)
"Rust.ml" 535 20873 20911 "Rust.ml" 535 20873 20944
type(
  string list
)
"Rust.ml" 536 20945 20953 "Rust.ml" 536 20945 20958
type(
  bool
)
"Rust.ml" 536 20945 20960 "Rust.ml" 536 20945 20965
type(
  string list
)
ident(
  def lines "Rust.ml" 536 20945 20969 "Rust.ml" 536 20945 20974
)
"Rust.ml" 536 20945 20953 "Rust.ml" 536 20945 20965
type(
  bool * string list
)
"Rust.ml" 536 20945 20969 "Rust.ml" 536 20945 20974
type(
  string list
)
ident(
  int_ref lines "Rust.ml" 536 20945 20960 "Rust.ml" 536 20945 20965
)
"Rust.ml" 534 20850 20863 "Rust.ml" 537 20975 20980
type(
  bool * string list -> string list
)
"Rust.ml" 537 20975 20981 "Rust.ml" 537 20975 20986
type(
  (bool * string list) list
)
ident(
  int_ref lines "Rust.ml" 532 20774 20781 "Rust.ml" 532 20774 20786
)
"Rust.ml" 534 20850 20854 "Rust.ml" 537 20975 20986
type(
  string list list
)
"Rust.ml" 538 20990 20996 "Rust.ml" 538 20990 21001
type(
  string list
)
ident(
  def lines "Rust.ml" 541 21060 21062 "Rust.ml" 563 21892 21901
)
"Rust.ml" 538 20990 21004 "Rust.ml" 538 20990 21016
type(
  string list list -> string list
)
ident(
  int_ref Stdlib.List.flatten "list.mli" 118 4456 4456 "list.mli" 118 4456 4493
)
"Rust.ml" 538 20990 21017 "Rust.ml" 538 20990 21022
type(
  string list list
)
ident(
  int_ref lines "Rust.ml" 533 20836 20842 "Rust.ml" 533 20836 20847
)
"Rust.ml" 538 20990 21004 "Rust.ml" 538 20990 21022
type(
  string list
)
"Rust.ml" 541 21060 21062 "Rust.ml" 541 21060 21072
type(
  (string -> string option) -> string list -> string list
)
ident(
  int_ref Utils.filter_map "utils.mli" 36 1205 1205 "utils.mli" 36 1205 1261
)
"Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
type(
  string
)
ident(
  def s "Rust.ml" 544 21158 21164 "Rust.ml" 562 21877 21891
)
"Rust.ml" 544 21158 21167 "Rust.ml" 544 21158 21185
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 544 21158 21194 "Rust.ml" 544 21158 21201
type(
  string
)
"Rust.ml" 544 21158 21202 "Rust.ml" 544 21158 21203
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 544 21158 21167 "Rust.ml" 544 21158 21203
type(
  bool
)
"Rust.ml" 544 21158 21204 "Rust.ml" 544 21158 21206
type(
  bool -> bool -> bool
)
ident(
  int_ref Stdlib.( || ) "stdlib.mli" 227 9492 9492 "stdlib.mli" 227 9492 9542
)
"Rust.ml" 545 21207 21216 "Rust.ml" 545 21207 21234
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 545 21207 21243 "Rust.ml" 545 21207 21250
type(
  string
)
"Rust.ml" 545 21207 21251 "Rust.ml" 545 21207 21252
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 545 21207 21216 "Rust.ml" 545 21207 21252
type(
  bool
)
"Rust.ml" 544 21158 21167 "Rust.ml" 545 21207 21252
type(
  bool
)
"Rust.ml" 546 21258 21266 "Rust.ml" 546 21258 21270
type(
  string option
)
"Rust.ml" 547 21271 21285 "Rust.ml" 547 21271 21303
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 547 21271 21312 "Rust.ml" 547 21271 21319
type(
  string
)
"Rust.ml" 547 21271 21320 "Rust.ml" 547 21271 21321
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 547 21271 21285 "Rust.ml" 547 21271 21321
type(
  bool
)
"Rust.ml" 548 21329 21341 "Rust.ml" 548 21329 21344
type(
  int
)
ident(
  def len "Rust.ml" 549 21366 21374 "Rust.ml" 550 21409 21432
)
"Rust.ml" 548 21329 21347 "Rust.ml" 548 21329 21360
type(
  string -> int
)
ident(
  int_ref Stdlib.String.length "string.mli" 118 4569 4569 "string.mli" 118 4569 4619
)
"Rust.ml" 548 21329 21361 "Rust.ml" 548 21329 21362
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 548 21329 21347 "Rust.ml" 548 21329 21362
type(
  int
)
"Rust.ml" 549 21366 21378 "Rust.ml" 549 21366 21380
type(
  string
)
ident(
  def s' "Rust.ml" 550 21409 21417 "Rust.ml" 550 21409 21432
)
"Rust.ml" 549 21366 21383 "Rust.ml" 549 21366 21393
type(
  string -> int -> int -> string
)
ident(
  int_ref Stdlib.String.sub "string.mli" 190 6894 6894 "string.mli" 190 6894 6934
)
"Rust.ml" 549 21366 21394 "Rust.ml" 549 21366 21395
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 549 21366 21396 "Rust.ml" 549 21366 21397
type(
  int
)
"Rust.ml" 549 21366 21399 "Rust.ml" 549 21366 21402
type(
  int
)
ident(
  int_ref len "Rust.ml" 548 21329 21341 "Rust.ml" 548 21329 21344
)
"Rust.ml" 549 21366 21402 "Rust.ml" 549 21366 21403
type(
  int -> int -> int
)
ident(
  int_ref Stdlib.( - ) "stdlib.mli" 352 13775 13775 "stdlib.mli" 352 13775 13821
)
"Rust.ml" 549 21366 21403 "Rust.ml" 549 21366 21404
type(
  int
)
"Rust.ml" 549 21366 21398 "Rust.ml" 549 21366 21405
type(
  int
)
"Rust.ml" 549 21366 21383 "Rust.ml" 549 21366 21405
type(
  string
)
"Rust.ml" 550 21409 21423 "Rust.ml" 550 21409 21426
type(
  string
)
"Rust.ml" 550 21409 21427 "Rust.ml" 550 21409 21428
type(
  string -> string -> string
)
ident(
  int_ref Stdlib.( ^ ) "stdlib.mli" 699 26389 26389 "stdlib.mli" 699 26389 26427
)
"Rust.ml" 550 21409 21429 "Rust.ml" 550 21409 21431
type(
  string
)
ident(
  int_ref s' "Rust.ml" 549 21366 21378 "Rust.ml" 549 21366 21380
)
"Rust.ml" 550 21409 21422 "Rust.ml" 550 21409 21432
type(
  string
)
"Rust.ml" 550 21409 21417 "Rust.ml" 550 21409 21432
type(
  string option
)
"Rust.ml" 549 21366 21374 "Rust.ml" 550 21409 21432
type(
  string option
)
"Rust.ml" 547 21271 21327 "Rust.ml" 551 21433 21440
type(
  string option
)
"Rust.ml" 552 21441 21455 "Rust.ml" 552 21441 21473
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 552 21441 21482 "Rust.ml" 552 21441 21489
type(
  string
)
"Rust.ml" 552 21441 21490 "Rust.ml" 552 21441 21491
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 552 21441 21455 "Rust.ml" 552 21441 21491
type(
  bool
)
"Rust.ml" 553 21499 21511 "Rust.ml" 553 21499 21512
type(
  int
)
ident(
  def i "Rust.ml" 554 21554 21562 "Rust.ml" 556 21634 21671
)
"Rust.ml" 553 21499 21515 "Rust.ml" 553 21499 21528
type(
  string -> int
)
ident(
  int_ref Stdlib.int_of_string "stdlib.mli" 774 28807 28807 "stdlib.mli" 774 28807 28868
)
"Rust.ml" 553 21499 21530 "Rust.ml" 553 21499 21541
type(
  int -> char -> string
)
ident(
  int_ref Stdlib.String.make "string.mli" 85 3764 3764 "string.mli" 85 3764 3796
)
"Rust.ml" 553 21499 21542 "Rust.ml" 553 21499 21543
type(
  int
)
"Rust.ml" 553 21499 21544 "Rust.ml" 553 21499 21545
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 553 21499 21547 "Rust.ml" 553 21499 21548
type(
  int
)
"Rust.ml" 553 21499 21544 "Rust.ml" 553 21499 21549
type(
  char
)
"Rust.ml" 553 21499 21529 "Rust.ml" 553 21499 21550
type(
  string
)
"Rust.ml" 553 21499 21515 "Rust.ml" 553 21499 21550
type(
  int
)
"Rust.ml" 554 21554 21566 "Rust.ml" 554 21554 21569
type(
  int
)
ident(
  def len "Rust.ml" 555 21591 21599 "Rust.ml" 556 21634 21671
)
"Rust.ml" 554 21554 21572 "Rust.ml" 554 21554 21585
type(
  string -> int
)
ident(
  int_ref Stdlib.String.length "string.mli" 118 4569 4569 "string.mli" 118 4569 4619
)
"Rust.ml" 554 21554 21586 "Rust.ml" 554 21554 21587
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 554 21554 21572 "Rust.ml" 554 21554 21587
type(
  int
)
"Rust.ml" 555 21591 21603 "Rust.ml" 555 21591 21605
type(
  string
)
ident(
  def s' "Rust.ml" 556 21634 21642 "Rust.ml" 556 21634 21671
)
"Rust.ml" 555 21591 21608 "Rust.ml" 555 21591 21618
type(
  string -> int -> int -> string
)
ident(
  int_ref Stdlib.String.sub "string.mli" 190 6894 6894 "string.mli" 190 6894 6934
)
"Rust.ml" 555 21591 21619 "Rust.ml" 555 21591 21620
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 555 21591 21621 "Rust.ml" 555 21591 21622
type(
  int
)
"Rust.ml" 555 21591 21624 "Rust.ml" 555 21591 21627
type(
  int
)
ident(
  int_ref len "Rust.ml" 554 21554 21566 "Rust.ml" 554 21554 21569
)
"Rust.ml" 555 21591 21627 "Rust.ml" 555 21591 21628
type(
  int -> int -> int
)
ident(
  int_ref Stdlib.( - ) "stdlib.mli" 352 13775 13775 "stdlib.mli" 352 13775 13821
)
"Rust.ml" 555 21591 21628 "Rust.ml" 555 21591 21629
type(
  int
)
"Rust.ml" 555 21591 21623 "Rust.ml" 555 21591 21630
type(
  int
)
"Rust.ml" 555 21591 21608 "Rust.ml" 555 21591 21630
type(
  string
)
"Rust.ml" 556 21634 21648 "Rust.ml" 556 21634 21659
type(
  int -> char -> string
)
ident(
  int_ref Stdlib.String.make "string.mli" 85 3764 3764 "string.mli" 85 3764 3796
)
"Rust.ml" 556 21634 21660 "Rust.ml" 556 21634 21661
type(
  int
)
ident(
  int_ref i "Rust.ml" 553 21499 21511 "Rust.ml" 553 21499 21512
)
"Rust.ml" 556 21634 21662 "Rust.ml" 556 21634 21665
type(
  char
)
"Rust.ml" 556 21634 21648 "Rust.ml" 556 21634 21665
type(
  string
)
"Rust.ml" 556 21634 21666 "Rust.ml" 556 21634 21667
type(
  string -> string -> string
)
ident(
  int_ref Stdlib.( ^ ) "stdlib.mli" 699 26389 26389 "stdlib.mli" 699 26389 26427
)
"Rust.ml" 556 21634 21668 "Rust.ml" 556 21634 21670
type(
  string
)
ident(
  int_ref s' "Rust.ml" 555 21591 21603 "Rust.ml" 555 21591 21605
)
"Rust.ml" 556 21634 21647 "Rust.ml" 556 21634 21671
type(
  string
)
"Rust.ml" 556 21634 21642 "Rust.ml" 556 21634 21671
type(
  string option
)
"Rust.ml" 555 21591 21599 "Rust.ml" 556 21634 21671
type(
  string option
)
"Rust.ml" 554 21554 21562 "Rust.ml" 556 21634 21671
type(
  string option
)
"Rust.ml" 552 21441 21497 "Rust.ml" 557 21672 21679
type(
  string option
)
"Rust.ml" 558 21680 21694 "Rust.ml" 558 21680 21712
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 558 21680 21721 "Rust.ml" 558 21680 21724
type(
  string
)
"Rust.ml" 558 21680 21725 "Rust.ml" 558 21680 21726
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 558 21680 21694 "Rust.ml" 558 21680 21726
type(
  bool
)
"Rust.ml" 559 21732 21740 "Rust.ml" 559 21732 21749
type(
  (string -> string -> string option, unit, string, string option) format4 ->
  string -> string -> string option
)
ident(
  int_ref Utils.failwithf "utils.mli" 34 1151 1151 "utils.mli" 34 1151 1203
)
"Rust.ml" 559 21732 21750 "Rust.ml" 560 21802 21858
type(
  (string -> string -> string option, unit, string, string option) format4
)
"Rust.ml" 560 21802 21859 "Rust.ml" 560 21802 21863
type(
  string
)
ident(
  int_ref name "Rust.ml" 493 19130 19155 "Rust.ml" 493 19130 19159
)
"Rust.ml" 560 21802 21864 "Rust.ml" 560 21802 21865
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 559 21732 21740 "Rust.ml" 560 21802 21865
type(
  string option
)
"Rust.ml" 562 21877 21890 "Rust.ml" 562 21877 21891
type(
  string
)
ident(
  int_ref s "Rust.ml" 542 21075 21083 "Rust.ml" 542 21075 21084
)
"Rust.ml" 562 21877 21885 "Rust.ml" 562 21877 21891
type(
  string option
)
"Rust.ml" 558 21680 21691 "Rust.ml" 562 21877 21891
type(
  string option
)
"Rust.ml" 552 21441 21452 "Rust.ml" 562 21877 21891
type(
  string option
)
"Rust.ml" 547 21271 21282 "Rust.ml" 562 21877 21891
type(
  string option
)
"Rust.ml" 544 21158 21164 "Rust.ml" 562 21877 21891
type(
  string option
)
"Rust.ml" 541 21060 21073 "Rust.ml" 563 21892 21895
type(
  string -> string option
)
"Rust.ml" 563 21892 21896 "Rust.ml" 563 21892 21901
type(
  string list
)
ident(
  int_ref lines "Rust.ml" 538 20990 20996 "Rust.ml" 538 20990 21001
)
"Rust.ml" 541 21060 21062 "Rust.ml" 563 21892 21901
type(
  string list
)
"Rust.ml" 538 20990 20992 "Rust.ml" 563 21892 21901
type(
  string list
)
"Rust.ml" 533 20836 20838 "Rust.ml" 563 21892 21901
type(
  string list
)
"Rust.ml" 532 20774 20776 "Rust.ml" 563 21892 21901
type(
  string list
)
"Rust.ml" 530 20682 20684 "Rust.ml" 563 21892 21901
type(
  string list
)
"Rust.ml" 527 20570 20572 "Rust.ml" 563 21892 21901
type(
  string list
)
"Rust.ml" 495 19209 19211 "Rust.ml" 563 21892 21901
type(
  string list
)
"Rust.ml" 569 22197 22201 "Rust.ml" 569 22197 22215
type(
  string -> string -> API.call -> unit
)
ident(
  def print_ffi_call "Rust.ml" 590 22960 22960 "Rust.ml" 0 0 -1
)
"Rust.ml" 569 22197 22216 "Rust.ml" 569 22197 22220
type(
  string
)
ident(
  def name "Rust.ml" 569 22197 22221 "Rust.ml" 585 22772 22782
)
"Rust.ml" 569 22197 22221 "Rust.ml" 569 22197 22227
type(
  string
)
ident(
  def handle "Rust.ml" 569 22197 22228 "Rust.ml" 585 22772 22782
)
"Rust.ml" 569 22197 22228 "Rust.ml" 569 22197 22232
type(
  API.call
)
ident(
  def call "Rust.ml" 570 22235 22237 "Rust.ml" 585 22772 22782
)
"Rust.ml" 570 22235 22241 "Rust.ml" 570 22235 22255
type(
  string list
)
ident(
  def ffi_args_names "Rust.ml" 574 22359 22361 "Rust.ml" 585 22772 22782
)
"Rust.ml" 571 22258 22262 "Rust.ml" 571 22258 22274
type(
  string list list -> string list
)
ident(
  int_ref Stdlib.List.flatten "list.mli" 118 4456 4456 "list.mli" 118 4456 4493
)
"Rust.ml" 571 22258 22276 "Rust.ml" 571 22258 22284
type(
  (API.arg -> string list) -> API.arg list -> string list list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 571 22258 22285 "Rust.ml" 571 22258 22298
type(
  API.arg -> string list
)
ident(
  int_ref ffi_arg_names "Rust.ml" 185 6159 6163 "Rust.ml" 185 6159 6176
)
"Rust.ml" 571 22258 22299 "Rust.ml" 571 22258 22303
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 569 22197 22228 "Rust.ml" 569 22197 22232
)
"Rust.ml" 571 22258 22299 "Rust.ml" 571 22258 22308
type(
  API.arg list
)
"Rust.ml" 571 22258 22275 "Rust.ml" 571 22258 22309
type(
  string list list
)
"Rust.ml" 571 22258 22262 "Rust.ml" 571 22258 22309
type(
  string list
)
"Rust.ml" 572 22310 22314 "Rust.ml" 572 22310 22315
type(
  string list -> string list -> string list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 572 22310 22316 "Rust.ml" 572 22310 22324
type(
  (API.optarg -> string) -> API.optarg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 572 22310 22325 "Rust.ml" 572 22310 22340
type(
  API.optarg -> string
)
ident(
  int_ref ffi_optarg_name "Rust.ml" 210 6673 6677 "Rust.ml" 210 6673 6692
)
"Rust.ml" 572 22310 22341 "Rust.ml" 572 22310 22345
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 569 22197 22228 "Rust.ml" 569 22197 22232
)
"Rust.ml" 572 22310 22341 "Rust.ml" 572 22310 22353
type(
  API.optarg list
)
"Rust.ml" 572 22310 22316 "Rust.ml" 572 22310 22353
type(
  string list
)
"Rust.ml" 571 22258 22262 "Rust.ml" 572 22310 22353
type(
  string list
)
"Rust.ml" 574 22359 22361 "Rust.ml" 574 22359 22363
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 574 22359 22364 "Rust.ml" 574 22359 22369
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 574 22359 22361 "Rust.ml" 574 22359 22369
type(
  unit
)
"Rust.ml" 575 22371 22373 "Rust.ml" 575 22371 22375
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 575 22371 22376 "Rust.ml" 575 22371 22427
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 575 22371 22373 "Rust.ml" 575 22371 22427
type(
  unit
)
"Rust.ml" 576 22429 22431 "Rust.ml" 576 22429 22440
type(
  (API.arg -> unit) -> API.arg list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 576 22429 22441 "Rust.ml" 576 22429 22456
type(
  API.arg -> unit
)
ident(
  int_ref rust_arg_to_ffi "Rust.ml" 272 9214 9218 "Rust.ml" 272 9214 9233
)
"Rust.ml" 576 22429 22457 "Rust.ml" 576 22429 22461
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 569 22197 22228 "Rust.ml" 569 22197 22232
)
"Rust.ml" 576 22429 22457 "Rust.ml" 576 22429 22466
type(
  API.arg list
)
"Rust.ml" 576 22429 22431 "Rust.ml" 576 22429 22466
type(
  unit
)
"Rust.ml" 577 22468 22470 "Rust.ml" 577 22468 22479
type(
  (API.optarg -> unit) -> API.optarg list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 577 22468 22480 "Rust.ml" 577 22468 22498
type(
  API.optarg -> unit
)
ident(
  int_ref rust_optarg_to_ffi "Rust.ml" 346 12830 12834 "Rust.ml" 346 12830 12852
)
"Rust.ml" 577 22468 22499 "Rust.ml" 577 22468 22503
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 569 22197 22228 "Rust.ml" 569 22197 22232
)
"Rust.ml" 577 22468 22499 "Rust.ml" 577 22468 22511
type(
  API.optarg list
)
"Rust.ml" 577 22468 22470 "Rust.ml" 577 22468 22511
type(
  unit
)
"Rust.ml" 578 22513 22515 "Rust.ml" 578 22513 22517
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 578 22513 22518 "Rust.ml" 578 22513 22522
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 578 22513 22515 "Rust.ml" 578 22513 22522
type(
  unit
)
"Rust.ml" 579 22524 22526 "Rust.ml" 579 22524 22528
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 579 22524 22529 "Rust.ml" 579 22524 22562
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 579 22524 22526 "Rust.ml" 579 22524 22562
type(
  unit
)
"Rust.ml" 580 22564 22566 "Rust.ml" 580 22564 22568
type(
  (string -> string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 580 22564 22569 "Rust.ml" 580 22564 22622
type(
  (string -> string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 580 22564 22623 "Rust.ml" 580 22564 22627
type(
  string
)
ident(
  int_ref name "Rust.ml" 569 22197 22216 "Rust.ml" 569 22197 22220
)
"Rust.ml" 580 22564 22628 "Rust.ml" 580 22564 22634
type(
  string
)
ident(
  int_ref handle "Rust.ml" 569 22197 22221 "Rust.ml" 569 22197 22227
)
"Rust.ml" 581 22635 22640 "Rust.ml" 581 22635 22653
type(
  string -> string list -> string
)
ident(
  int_ref Stdlib.String.concat "string.mli" 132 5016 5016 "string.mli" 132 5016 5060
)
"Rust.ml" 581 22635 22654 "Rust.ml" 581 22635 22658
type(
  string
)
"Rust.ml" 581 22635 22659 "Rust.ml" 581 22635 22673
type(
  string list
)
ident(
  int_ref ffi_args_names "Rust.ml" 570 22235 22241 "Rust.ml" 570 22235 22255
)
"Rust.ml" 581 22635 22639 "Rust.ml" 581 22635 22674
type(
  string
)
"Rust.ml" 580 22564 22566 "Rust.ml" 581 22635 22674
type(
  unit
)
"Rust.ml" 582 22676 22678 "Rust.ml" 582 22676 22680
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 582 22676 22681 "Rust.ml" 582 22676 22685
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 582 22676 22678 "Rust.ml" 582 22676 22685
type(
  unit
)
"Rust.ml" 583 22687 22689 "Rust.ml" 583 22687 22691
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 583 22687 22692 "Rust.ml" 583 22687 22746
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 583 22687 22689 "Rust.ml" 583 22687 22746
type(
  unit
)
"Rust.ml" 584 22748 22750 "Rust.ml" 584 22748 22765
type(
  API.call -> unit
)
ident(
  int_ref ffi_ret_to_rust "Rust.ml" 403 15270 15274 "Rust.ml" 403 15270 15289
)
"Rust.ml" 584 22748 22766 "Rust.ml" 584 22748 22770
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 569 22197 22228 "Rust.ml" 569 22197 22232
)
"Rust.ml" 584 22748 22750 "Rust.ml" 584 22748 22770
type(
  unit
)
"Rust.ml" 585 22772 22774 "Rust.ml" 585 22772 22776
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 585 22772 22777 "Rust.ml" 585 22772 22782
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 585 22772 22774 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 584 22748 22750 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 583 22687 22689 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 582 22676 22678 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 580 22564 22566 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 579 22524 22526 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 578 22513 22515 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 577 22468 22470 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 576 22429 22431 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 575 22371 22373 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 574 22359 22361 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 570 22235 22237 "Rust.ml" 585 22772 22782
type(
  unit
)
"Rust.ml" 590 22960 22964 "Rust.ml" 590 22960 22988
type(
  NameSet.elt * API.call -> unit
)
ident(
  def print_rust_handle_method "Rust.ml" 612 23786 23786 "Rust.ml" 0 0 -1
)
"Rust.ml" 590 22960 22990 "Rust.ml" 590 22960 22994
type(
  NameSet.elt
)
ident(
  def name "Rust.ml" 591 23004 23006 "Rust.ml" 610 23775 23784
)
"Rust.ml" 590 22960 22996 "Rust.ml" 590 22960 23000
type(
  API.call
)
ident(
  def call "Rust.ml" 591 23004 23006 "Rust.ml" 610 23775 23784
)
"Rust.ml" 590 22960 22989 "Rust.ml" 590 22960 23001
type(
  NameSet.elt * API.call
)
"Rust.ml" 591 23004 23010 "Rust.ml" 591 23004 23025
type(
  string list
)
ident(
  def rust_args_names "Rust.ml" 596 23213 23215 "Rust.ml" 610 23775 23784
)
"Rust.ml" 592 23028 23032 "Rust.ml" 592 23028 23040
type(
  (API.arg -> string) -> API.arg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 592 23028 23041 "Rust.ml" 592 23028 23054
type(
  API.arg -> string
)
ident(
  int_ref rust_arg_name "Rust.ml" 97 3181 3185 "Rust.ml" 97 3181 3198
)
"Rust.ml" 592 23028 23055 "Rust.ml" 592 23028 23059
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 590 22960 22996 "Rust.ml" 590 22960 23000
)
"Rust.ml" 592 23028 23055 "Rust.ml" 592 23028 23064
type(
  API.arg list
)
"Rust.ml" 592 23028 23032 "Rust.ml" 592 23028 23064
type(
  string list
)
"Rust.ml" 592 23028 23065 "Rust.ml" 592 23028 23066
type(
  string list -> string list -> string list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 592 23028 23067 "Rust.ml" 592 23028 23075
type(
  (API.optarg -> string) -> API.optarg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 592 23028 23076 "Rust.ml" 592 23028 23092
type(
  API.optarg -> string
)
ident(
  int_ref rust_optarg_name "Rust.ml" 122 3625 3629 "Rust.ml" 122 3625 3645
)
"Rust.ml" 592 23028 23093 "Rust.ml" 592 23028 23097
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 590 22960 22996 "Rust.ml" 590 22960 23000
)
"Rust.ml" 592 23028 23093 "Rust.ml" 592 23028 23105
type(
  API.optarg list
)
"Rust.ml" 592 23028 23067 "Rust.ml" 592 23028 23105
type(
  string list
)
"Rust.ml" 592 23028 23032 "Rust.ml" 592 23028 23105
type(
  string list
)
"Rust.ml" 593 23106 23112 "Rust.ml" 593 23106 23127
type(
  string list
)
ident(
  def rust_args_types "Rust.ml" 596 23213 23215 "Rust.ml" 610 23775 23784
)
"Rust.ml" 594 23130 23134 "Rust.ml" 594 23130 23142
type(
  (API.arg -> string) -> API.arg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 594 23130 23143 "Rust.ml" 594 23130 23156
type(
  API.arg -> string
)
ident(
  int_ref rust_arg_type "Rust.ml" 133 4026 4034 "Rust.ml" 133 4026 4047
)
"Rust.ml" 594 23130 23157 "Rust.ml" 594 23130 23161
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 590 22960 22996 "Rust.ml" 590 22960 23000
)
"Rust.ml" 594 23130 23157 "Rust.ml" 594 23130 23166
type(
  API.arg list
)
"Rust.ml" 594 23130 23134 "Rust.ml" 594 23130 23166
type(
  string list
)
"Rust.ml" 594 23130 23167 "Rust.ml" 594 23130 23168
type(
  string list -> string list -> string list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 594 23130 23169 "Rust.ml" 594 23130 23177
type(
  (API.optarg -> string) -> API.optarg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 594 23130 23178 "Rust.ml" 594 23130 23194
type(
  API.optarg -> string
)
ident(
  int_ref rust_optarg_type "Rust.ml" 176 5671 5675 "Rust.ml" 176 5671 5691
)
"Rust.ml" 594 23130 23195 "Rust.ml" 594 23130 23199
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 590 22960 22996 "Rust.ml" 590 22960 23000
)
"Rust.ml" 594 23130 23195 "Rust.ml" 594 23130 23207
type(
  API.optarg list
)
"Rust.ml" 594 23130 23169 "Rust.ml" 594 23130 23207
type(
  string list
)
"Rust.ml" 594 23130 23134 "Rust.ml" 594 23130 23207
type(
  string list
)
"Rust.ml" 596 23213 23219 "Rust.ml" 596 23213 23228
type(
  string
)
ident(
  def rust_args "Rust.ml" 600 23328 23330 "Rust.ml" 610 23775 23784
)
"Rust.ml" 597 23231 23235 "Rust.ml" 597 23231 23248
type(
  string -> string list -> string
)
ident(
  int_ref Stdlib.String.concat "string.mli" 132 5016 5016 "string.mli" 132 5016 5060
)
"Rust.ml" 597 23231 23249 "Rust.ml" 597 23231 23253
type(
  string
)
"Rust.ml" 598 23254 23261 "Rust.ml" 598 23254 23270
type(
  (string -> string -> string) -> string list -> string list -> string list
)
ident(
  int_ref Stdlib.List.map2 "list.mli" 232 7967 7967 "list.mli" 232 7967 8027
)
"Rust.ml" 598 23254 23272 "Rust.ml" 598 23254 23279
type(
  (string -> string -> string, unit, string) format ->
  string -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 598 23254 23280 "Rust.ml" 598 23254 23288
type(
  (string -> string -> string, unit, string) format
)
"Rust.ml" 598 23254 23271 "Rust.ml" 598 23254 23289
type(
  string -> string -> string
)
"Rust.ml" 598 23254 23290 "Rust.ml" 598 23254 23305
type(
  string list
)
ident(
  int_ref rust_args_names "Rust.ml" 591 23004 23010 "Rust.ml" 591 23004 23025
)
"Rust.ml" 598 23254 23306 "Rust.ml" 598 23254 23321
type(
  string list
)
ident(
  int_ref rust_args_types "Rust.ml" 593 23106 23112 "Rust.ml" 593 23106 23127
)
"Rust.ml" 598 23254 23260 "Rust.ml" 598 23254 23322
type(
  string list
)
"Rust.ml" 597 23231 23235 "Rust.ml" 598 23254 23322
type(
  string
)
"Rust.ml" 600 23328 23330 "Rust.ml" 600 23328 23360
type(
  NameSet.elt -> API.call -> unit
)
ident(
  int_ref print_rust_handle_call_comment "Rust.ml" 479 18615 18623 "Rust.ml" 479 18615 18653
)
"Rust.ml" 600 23328 23361 "Rust.ml" 600 23328 23365
type(
  NameSet.elt
)
ident(
  int_ref name "Rust.ml" 590 22960 22990 "Rust.ml" 590 22960 22994
)
"Rust.ml" 600 23328 23366 "Rust.ml" 600 23328 23370
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 590 22960 22996 "Rust.ml" 590 22960 23000
)
"Rust.ml" 600 23328 23330 "Rust.ml" 600 23328 23370
type(
  unit
)
"Rust.ml" 602 23407 23412 "Rust.ml" 602 23407 23423
type(
  NameSet.elt -> NameSet.t -> bool
)
ident(
  int_ref NameSet.mem "set.mli" 80 3035 3039 "set.mli" 80 3035 3064
)
"Rust.ml" 602 23407 23424 "Rust.ml" 602 23407 23428
type(
  NameSet.elt
)
ident(
  int_ref name "Rust.ml" 590 22960 22990 "Rust.ml" 590 22960 22994
)
"Rust.ml" 602 23407 23429 "Rust.ml" 602 23407 23448
type(
  NameSet.t
)
ident(
  int_ref hidden_handle_calls "Rust.ml" 32 1193 1197 "Rust.ml" 32 1193 1216
)
"Rust.ml" 602 23407 23412 "Rust.ml" 602 23407 23448
type(
  bool
)
"Rust.ml" 605 23595 23599 "Rust.ml" 605 23595 23601
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 605 23595 23602 "Rust.ml" 605 23595 23622
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 605 23595 23599 "Rust.ml" 605 23595 23622
type(
  unit
)
"Rust.ml" 606 23624 23628 "Rust.ml" 606 23624 23630
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 606 23624 23631 "Rust.ml" 606 23624 23644
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 606 23624 23628 "Rust.ml" 606 23624 23644
type(
  unit
)
"Rust.ml" 602 23407 23454 "Rust.ml" 606 23624 23645
type(
  unit
)
"Rust.ml" 607 23646 23653 "Rust.ml" 607 23646 23655
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 607 23646 23656 "Rust.ml" 607 23646 23662
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 607 23646 23653 "Rust.ml" 607 23646 23662
type(
  unit
)
"Rust.ml" 602 23407 23409 "Rust.ml" 607 23646 23662
type(
  unit
)
"Rust.ml" 608 23664 23666 "Rust.ml" 608 23664 23668
type(
  (NameSet.elt -> string -> string -> unit, unit, string, unit) format4 ->
  NameSet.elt -> string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 608 23664 23669 "Rust.ml" 608 23664 23695
type(
  (NameSet.elt -> string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 608 23664 23696 "Rust.ml" 608 23664 23700
type(
  NameSet.elt
)
ident(
  int_ref name "Rust.ml" 590 22960 22990 "Rust.ml" 590 22960 22994
)
"Rust.ml" 608 23664 23701 "Rust.ml" 608 23664 23710
type(
  string
)
ident(
  int_ref rust_args "Rust.ml" 596 23213 23219 "Rust.ml" 596 23213 23228
)
"Rust.ml" 608 23664 23712 "Rust.ml" 608 23664 23725
type(
  API.call -> string
)
ident(
  int_ref rust_ret_type "Rust.ml" 247 8339 8343 "Rust.ml" 247 8339 8356
)
"Rust.ml" 608 23664 23726 "Rust.ml" 608 23664 23730
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 590 22960 22996 "Rust.ml" 590 22960 23000
)
"Rust.ml" 608 23664 23711 "Rust.ml" 608 23664 23731
type(
  string
)
"Rust.ml" 608 23664 23666 "Rust.ml" 608 23664 23731
type(
  unit
)
"Rust.ml" 609 23733 23735 "Rust.ml" 609 23733 23749
type(
  NameSet.elt -> string -> API.call -> unit
)
ident(
  int_ref print_ffi_call "Rust.ml" 569 22197 22201 "Rust.ml" 569 22197 22215
)
"Rust.ml" 609 23733 23750 "Rust.ml" 609 23733 23754
type(
  NameSet.elt
)
ident(
  int_ref name "Rust.ml" 590 22960 22990 "Rust.ml" 590 22960 22994
)
"Rust.ml" 609 23733 23755 "Rust.ml" 609 23733 23768
type(
  string
)
"Rust.ml" 609 23733 23769 "Rust.ml" 609 23733 23773
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 590 22960 22996 "Rust.ml" 590 22960 23000
)
"Rust.ml" 609 23733 23735 "Rust.ml" 609 23733 23773
type(
  unit
)
"Rust.ml" 610 23775 23777 "Rust.ml" 610 23775 23779
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 610 23775 23780 "Rust.ml" 610 23775 23784
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 610 23775 23777 "Rust.ml" 610 23775 23784
type(
  unit
)
"Rust.ml" 609 23733 23735 "Rust.ml" 610 23775 23784
type(
  unit
)
"Rust.ml" 608 23664 23666 "Rust.ml" 610 23775 23784
type(
  unit
)
"Rust.ml" 602 23407 23409 "Rust.ml" 610 23775 23784
type(
  unit
)
"Rust.ml" 600 23328 23330 "Rust.ml" 610 23775 23784
type(
  unit
)
"Rust.ml" 596 23213 23215 "Rust.ml" 610 23775 23784
type(
  unit
)
"Rust.ml" 591 23004 23006 "Rust.ml" 610 23775 23784
type(
  unit
)
"Rust.ml" 612 23786 23790 "Rust.ml" 612 23786 23808
type(
  unit -> unit
)
ident(
  def print_rust_imports "Rust.ml" 627 24242 24242 "Rust.ml" 0 0 -1
)
"Rust.ml" 612 23786 23809 "Rust.ml" 612 23786 23811
type(
  unit
)
"Rust.ml" 613 23814 23816 "Rust.ml" 613 23814 23818
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 613 23814 23819 "Rust.ml" 613 23814 23846
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 613 23814 23816 "Rust.ml" 613 23814 23846
type(
  unit
)
"Rust.ml" 614 23848 23850 "Rust.ml" 614 23848 23852
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 614 23848 23853 "Rust.ml" 614 23848 23882
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 614 23848 23850 "Rust.ml" 614 23848 23882
type(
  unit
)
"Rust.ml" 615 23884 23886 "Rust.ml" 615 23884 23888
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 615 23884 23889 "Rust.ml" 615 23884 23925
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 615 23884 23886 "Rust.ml" 615 23884 23925
type(
  unit
)
"Rust.ml" 616 23927 23929 "Rust.ml" 616 23927 23931
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 616 23927 23932 "Rust.ml" 616 23927 23952
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 616 23927 23929 "Rust.ml" 616 23927 23952
type(
  unit
)
"Rust.ml" 617 23954 23956 "Rust.ml" 617 23954 23958
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 617 23954 23959 "Rust.ml" 617 23954 23976
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 617 23954 23956 "Rust.ml" 617 23954 23976
type(
  unit
)
"Rust.ml" 618 23978 23980 "Rust.ml" 618 23978 23982
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 618 23978 23983 "Rust.ml" 618 23978 24012
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 618 23978 23980 "Rust.ml" 618 23978 24012
type(
  unit
)
"Rust.ml" 619 24014 24016 "Rust.ml" 619 24014 24018
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 619 24014 24019 "Rust.ml" 619 24014 24066
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 619 24014 24016 "Rust.ml" 619 24014 24066
type(
  unit
)
"Rust.ml" 620 24068 24070 "Rust.ml" 620 24068 24072
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 620 24068 24073 "Rust.ml" 620 24068 24107
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 620 24068 24070 "Rust.ml" 620 24068 24107
type(
  unit
)
"Rust.ml" 621 24109 24111 "Rust.ml" 621 24109 24113
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 621 24109 24114 "Rust.ml" 621 24109 24141
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 621 24109 24111 "Rust.ml" 621 24109 24141
type(
  unit
)
"Rust.ml" 622 24143 24145 "Rust.ml" 622 24143 24147
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 622 24143 24148 "Rust.ml" 622 24143 24165
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 622 24143 24145 "Rust.ml" 622 24143 24165
type(
  unit
)
"Rust.ml" 623 24167 24169 "Rust.ml" 623 24167 24171
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 623 24167 24172 "Rust.ml" 623 24167 24191
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 623 24167 24169 "Rust.ml" 623 24167 24191
type(
  unit
)
"Rust.ml" 624 24193 24195 "Rust.ml" 624 24193 24197
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 624 24193 24198 "Rust.ml" 624 24193 24229
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 624 24193 24195 "Rust.ml" 624 24193 24229
type(
  unit
)
"Rust.ml" 625 24231 24233 "Rust.ml" 625 24231 24235
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 625 24231 24236 "Rust.ml" 625 24231 24240
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 625 24231 24233 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 624 24193 24195 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 623 24167 24169 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 622 24143 24145 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 621 24109 24111 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 620 24068 24070 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 619 24014 24016 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 618 23978 23980 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 617 23954 23956 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 616 23927 23929 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 615 23884 23886 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 614 23848 23850 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 613 23814 23816 "Rust.ml" 625 24231 24240
type(
  unit
)
"Rust.ml" 627 24242 24246 "Rust.ml" 627 24242 24268
type(
  unit -> unit
)
ident(
  def generate_rust_bindings "Rust.ml" 648 25060 25060 "Rust.ml" 0 0 -1
)
"Rust.ml" 627 24242 24269 "Rust.ml" 627 24242 24271
type(
  unit
)
"Rust.ml" 628 24274 24276 "Rust.ml" 628 24274 24291
type(
  ?extra_sources:string list ->
  ?copyright:string -> Utils.comment_style -> unit
)
ident(
  int_ref Utils.generate_header "utils.mli" 54 1958 1958 "utils.mli" 55 1980 2054
)
"Rust.ml" 628 24274 24292 "Rust.ml" 628 24274 24298
type(
  Utils.comment_style
)
"Rust.ml" 628 24274 24310 "Rust.ml" 628 24274 24326
type(
  string
)
type(
  string option
)
"Rust.ml" 628 24274 24276 "Rust.ml" 628 24274 24326
type(
  unit
)
"Rust.ml" 629 24328 24330 "Rust.ml" 629 24328 24332
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 629 24328 24333 "Rust.ml" 629 24328 24337
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 629 24328 24330 "Rust.ml" 629 24328 24337
type(
  unit
)
"Rust.ml" 630 24339 24341 "Rust.ml" 630 24339 24359
type(
  unit -> unit
)
ident(
  int_ref print_rust_imports "Rust.ml" 612 23786 23790 "Rust.ml" 612 23786 23808
)
"Rust.ml" 630 24339 24360 "Rust.ml" 630 24339 24362
type(
  unit
)
"Rust.ml" 630 24339 24341 "Rust.ml" 630 24339 24362
type(
  unit
)
"Rust.ml" 631 24364 24366 "Rust.ml" 631 24364 24375
type(
  (string * int -> unit) -> (string * int) list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 631 24364 24376 "Rust.ml" 631 24364 24395
type(
  string * int -> unit
)
ident(
  int_ref print_rust_constant "Rust.ml" 36 1329 1333 "Rust.ml" 36 1329 1352
)
"Rust.ml" 631 24364 24396 "Rust.ml" 631 24364 24405
type(
  (string * int) list
)
ident(
  int_ref API.constants "API.mli" 160 8322 8322 "API.mli" 160 8322 8357
)
"Rust.ml" 631 24364 24366 "Rust.ml" 631 24364 24405
type(
  unit
)
"Rust.ml" 632 24407 24409 "Rust.ml" 632 24407 24411
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 632 24407 24412 "Rust.ml" 632 24407 24416
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 632 24407 24409 "Rust.ml" 632 24407 24416
type(
  unit
)
"Rust.ml" 633 24418 24420 "Rust.ml" 633 24418 24429
type(
  (API.enum -> unit) -> API.enum list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 633 24418 24430 "Rust.ml" 633 24418 24445
type(
  API.enum -> unit
)
ident(
  int_ref print_rust_enum "Rust.ml" 39 1414 1418 "Rust.ml" 39 1414 1433
)
"Rust.ml" 633 24418 24446 "Rust.ml" 633 24418 24455
type(
  API.enum list
)
ident(
  int_ref API.all_enums "API.mli" 157 8221 8221 "API.mli" 157 8221 8246
)
"Rust.ml" 633 24418 24420 "Rust.ml" 633 24418 24455
type(
  unit
)
"Rust.ml" 634 24457 24459 "Rust.ml" 634 24457 24468
type(
  (API.flags -> unit) -> API.flags list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 634 24457 24469 "Rust.ml" 634 24457 24485
type(
  API.flags -> unit
)
ident(
  int_ref print_rust_flags "Rust.ml" 49 1734 1738 "Rust.ml" 49 1734 1754
)
"Rust.ml" 634 24457 24486 "Rust.ml" 634 24457 24495
type(
  API.flags list
)
ident(
  int_ref API.all_flags "API.mli" 158 8247 8247 "API.mli" 158 8247 8273
)
"Rust.ml" 634 24457 24459 "Rust.ml" 634 24457 24495
type(
  unit
)
"Rust.ml" 635 24497 24499 "Rust.ml" 635 24497 24508
type(
  (string * (string * (string * int) list) list -> unit) ->
  (string * (string * (string * int) list) list) list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 635 24497 24509 "Rust.ml" 635 24497 24533
type(
  string * (string * (string * int) list) list -> unit
)
ident(
  int_ref print_metadata_namespace "Rust.ml" 83 2662 2666 "Rust.ml" 83 2662 2690
)
"Rust.ml" 635 24497 24534 "Rust.ml" 635 24497 24553
type(
  (string * (string * (string * int) list) list) list
)
ident(
  int_ref API.metadata_namespaces "API.mli" 161 8358 8358 "API.mli" 161 8358 8435
)
"Rust.ml" 635 24497 24499 "Rust.ml" 635 24497 24553
type(
  unit
)
"Rust.ml" 636 24555 24557 "Rust.ml" 636 24555 24566
type(
  (API.closure -> unit) -> API.closure list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 636 24555 24567 "Rust.ml" 636 24555 24595
type(
  API.closure -> unit
)
ident(
  int_ref print_rust_closure_to_raw_fn "Rust.ml" 448 17292 17296 "Rust.ml" 448 17292 17324
)
"Rust.ml" 636 24555 24596 "Rust.ml" 636 24555 24608
type(
  API.closure list
)
ident(
  int_ref API.all_closures "API.mli" 156 8189 8189 "API.mli" 156 8189 8220
)
"Rust.ml" 636 24555 24557 "Rust.ml" 636 24555 24608
type(
  unit
)
"Rust.ml" 637 24610 24612 "Rust.ml" 637 24610 24614
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 637 24610 24615 "Rust.ml" 637 24610 24632
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 637 24610 24612 "Rust.ml" 637 24610 24632
type(
  unit
)
"Rust.ml" 638 24634 24636 "Rust.ml" 638 24634 24645
type(
  (NameSet.elt * API.call -> unit) -> (NameSet.elt * API.call) list -> unit
)
ident(
  int_ref Stdlib.List.iter "list.mli" 159 5701 5701 "list.mli" 159 5701 5743
)
"Rust.ml" 638 24634 24646 "Rust.ml" 638 24634 24670
type(
  NameSet.elt * API.call -> unit
)
ident(
  int_ref print_rust_handle_method "Rust.ml" 590 22960 22964 "Rust.ml" 590 22960 22988
)
"Rust.ml" 638 24634 24671 "Rust.ml" 638 24634 24683
type(
  (NameSet.elt * API.call) list
)
ident(
  int_ref API.handle_calls "API.mli" 148 7854 7854 "API.mli" 148 7854 7893
)
"Rust.ml" 638 24634 24636 "Rust.ml" 638 24634 24683
type(
  unit
)
"Rust.ml" 639 24685 24687 "Rust.ml" 639 24685 24689
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 639 24685 24690 "Rust.ml" 639 24685 24697
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 639 24685 24687 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 638 24634 24636 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 637 24610 24612 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 636 24555 24557 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 635 24497 24499 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 634 24457 24459 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 633 24418 24420 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 632 24407 24409 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 631 24364 24366 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 630 24339 24341 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 629 24328 24330 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 628 24274 24276 "Rust.ml" 639 24685 24697
type(
  unit
)
"Rust.ml" 648 25060 25064 "Rust.ml" 648 25060 25085
type(
  NameSet.t
)
ident(
  def excluded_handle_calls "Rust.ml" 663 25438 25438 "Rust.ml" 0 0 -1
)
"Rust.ml" 649 25100 25102 "Rust.ml" 649 25100 25117
type(
  NameSet.elt list -> NameSet.t
)
ident(
  int_ref NameSet.of_list "set.mli" 280 10641 10645 "set.mli" 280 10641 10671
)
"Rust.ml" 651 25125 25132 "Rust.ml" 651 25125 25144
type(
  NameSet.elt
)
"Rust.ml" 652 25146 25153 "Rust.ml" 652 25146 25172
type(
  NameSet.elt
)
"Rust.ml" 653 25174 25181 "Rust.ml" 653 25174 25203
type(
  NameSet.elt
)
"Rust.ml" 654 25205 25212 "Rust.ml" 654 25205 25223
type(
  NameSet.elt
)
"Rust.ml" 655 25225 25232 "Rust.ml" 655 25225 25243
type(
  NameSet.elt
)
"Rust.ml" 656 25245 25252 "Rust.ml" 656 25245 25272
type(
  NameSet.elt
)
"Rust.ml" 650 25118 25123 "Rust.ml" 657 25274 25280
type(
  NameSet.elt list
)
"Rust.ml" 658 25281 25283 "Rust.ml" 658 25281 25284
type(
  NameSet.elt list -> NameSet.elt list -> NameSet.elt list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 658 25281 25286 "Rust.ml" 658 25281 25298
type(
  (NameSet.elt * API.call) list
)
ident(
  int_ref API.handle_calls "API.mli" 148 7854 7854 "API.mli" 148 7854 7893
)
"Rust.ml" 659 25299 25306 "Rust.ml" 659 25299 25317
type(
  (NameSet.elt * API.call -> bool) ->
  (NameSet.elt * API.call) list -> (NameSet.elt * API.call) list
)
ident(
  int_ref Stdlib.List.filter "list.mli" 327 10954 10954 "list.mli" 327 10954 11001
)
"Rust.ml" 659 25299 25324 "Rust.ml" 659 25299 25325
type(
  NameSet.elt
)
"Rust.ml" 659 25299 25329 "Rust.ml" 659 25299 25340
type(
  bool
)
ident(
  def modifies_fd "Rust.ml" 659 25299 25347 "Rust.ml" 659 25299 25358
)
"Rust.ml" 659 25299 25327 "Rust.ml" 659 25299 25342
type(
  API.call
)
"Rust.ml" 659 25299 25323 "Rust.ml" 659 25299 25343
type(
  NameSet.elt * API.call
)
"Rust.ml" 659 25299 25347 "Rust.ml" 659 25299 25358
type(
  bool
)
ident(
  int_ref modifies_fd "Rust.ml" 659 25299 25329 "Rust.ml" 659 25299 25340
)
"Rust.ml" 659 25299 25318 "Rust.ml" 659 25299 25359
type(
  NameSet.elt * API.call -> bool
)
"Rust.ml" 659 25299 25306 "Rust.ml" 659 25299 25359
type(
  (NameSet.elt * API.call) list -> (NameSet.elt * API.call) list
)
"Rust.ml" 658 25281 25286 "Rust.ml" 659 25299 25359
type(
  (NameSet.elt * API.call) list
)
"Rust.ml" 660 25360 25367 "Rust.ml" 660 25360 25375
type(
  (NameSet.elt * API.call -> NameSet.elt) ->
  (NameSet.elt * API.call) list -> NameSet.elt list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 660 25360 25382 "Rust.ml" 660 25360 25386
type(
  NameSet.elt
)
ident(
  def name "Rust.ml" 660 25360 25394 "Rust.ml" 660 25360 25398
)
"Rust.ml" 660 25360 25388 "Rust.ml" 660 25360 25389
type(
  API.call
)
"Rust.ml" 660 25360 25381 "Rust.ml" 660 25360 25390
type(
  NameSet.elt * API.call
)
"Rust.ml" 660 25360 25394 "Rust.ml" 660 25360 25398
type(
  NameSet.elt
)
ident(
  int_ref name "Rust.ml" 660 25360 25382 "Rust.ml" 660 25360 25386
)
"Rust.ml" 660 25360 25376 "Rust.ml" 660 25360 25399
type(
  NameSet.elt * API.call -> NameSet.elt
)
"Rust.ml" 660 25360 25367 "Rust.ml" 660 25360 25399
type(
  (NameSet.elt * API.call) list -> NameSet.elt list
)
"Rust.ml" 658 25281 25285 "Rust.ml" 660 25360 25400
type(
  NameSet.elt list
)
"Rust.ml" 650 25118 25123 "Rust.ml" 660 25360 25400
type(
  NameSet.elt list
)
"Rust.ml" 649 25100 25102 "Rust.ml" 660 25360 25400
type(
  NameSet.t
)
"Rust.ml" 663 25438 25445 "Rust.ml" 663 25438 25452
ident(
  def NameMap "Rust.ml" 663 25438 25472 "Rust.ml" 0 0 -1
)
"Rust.ml" 666 25525 25529 "Rust.ml" 666 25525 25538
type(
  string -> string
)
ident(
  def strip_aio "Rust.ml" 674 25905 25905 "Rust.ml" 0 0 -1
)
"Rust.ml" 666 25525 25539 "Rust.ml" 666 25525 25543
type(
  string
)
ident(
  def name "Rust.ml" 667 25555 25557 "Rust.ml" 669 25651 25716
)
"Rust.ml" 667 25555 25560 "Rust.ml" 667 25555 25578
type(
  prefix:string -> string -> bool
)
ident(
  int_ref Utils.string_starts_with "utils.mli" 46 1649 1649 "utils.mli" 46 1649 1705
)
"Rust.ml" 667 25555 25587 "Rust.ml" 667 25555 25593
type(
  string
)
"Rust.ml" 667 25555 25594 "Rust.ml" 667 25555 25598
type(
  string
)
ident(
  int_ref name "Rust.ml" 666 25525 25539 "Rust.ml" 666 25525 25543
)
"Rust.ml" 667 25555 25560 "Rust.ml" 667 25555 25598
type(
  bool
)
"Rust.ml" 668 25604 25608 "Rust.ml" 668 25604 25618
type(
  string -> int -> int -> string
)
ident(
  int_ref Stdlib.String.sub "string.mli" 190 6894 6894 "string.mli" 190 6894 6934
)
"Rust.ml" 668 25604 25619 "Rust.ml" 668 25604 25623
type(
  string
)
ident(
  int_ref name "Rust.ml" 666 25525 25539 "Rust.ml" 666 25525 25543
)
"Rust.ml" 668 25604 25624 "Rust.ml" 668 25604 25625
type(
  int
)
"Rust.ml" 668 25604 25627 "Rust.ml" 668 25604 25640
type(
  string -> int
)
ident(
  int_ref Stdlib.String.length "string.mli" 118 4569 4569 "string.mli" 118 4569 4619
)
"Rust.ml" 668 25604 25641 "Rust.ml" 668 25604 25645
type(
  string
)
ident(
  int_ref name "Rust.ml" 666 25525 25539 "Rust.ml" 666 25525 25543
)
"Rust.ml" 668 25604 25627 "Rust.ml" 668 25604 25645
type(
  int
)
"Rust.ml" 668 25604 25646 "Rust.ml" 668 25604 25647
type(
  int -> int -> int
)
ident(
  int_ref Stdlib.( - ) "stdlib.mli" 352 13775 13775 "stdlib.mli" 352 13775 13821
)
"Rust.ml" 668 25604 25648 "Rust.ml" 668 25604 25649
type(
  int
)
"Rust.ml" 668 25604 25626 "Rust.ml" 668 25604 25650
type(
  int
)
"Rust.ml" 668 25604 25608 "Rust.ml" 668 25604 25650
type(
  string
)
"Rust.ml" 669 25651 25658 "Rust.ml" 669 25651 25667
type(
  (string -> string, unit, string, string) format4 -> string -> string
)
ident(
  int_ref Utils.failwithf "utils.mli" 34 1151 1151 "utils.mli" 34 1151 1203
)
"Rust.ml" 669 25651 25668 "Rust.ml" 669 25651 25711
type(
  (string -> string, unit, string, string) format4
)
"Rust.ml" 669 25651 25712 "Rust.ml" 669 25651 25716
type(
  string
)
ident(
  int_ref name "Rust.ml" 666 25525 25539 "Rust.ml" 666 25525 25543
)
"Rust.ml" 669 25651 25658 "Rust.ml" 669 25651 25716
type(
  string
)
"Rust.ml" 667 25555 25557 "Rust.ml" 669 25651 25716
type(
  string
)
"Rust.ml" 674 25905 25909 "Rust.ml" 674 25905 25927
type(
  (string * API.call * API.async_kind) NameMap.t
)
ident(
  def async_handle_calls "Rust.ml" 687 26575 26575 "Rust.ml" 0 0 -1
)
"Rust.ml" 675 25971 25973 "Rust.ml" 675 25971 25985
type(
  (NameSet.elt * API.call) list
)
ident(
  int_ref API.handle_calls "API.mli" 148 7854 7854 "API.mli" 148 7854 7893
)
"Rust.ml" 676 25986 25991 "Rust.ml" 676 25986 26002
type(
  (NameSet.elt * API.call -> bool) ->
  (NameSet.elt * API.call) list -> (NameSet.elt * API.call) list
)
ident(
  int_ref Stdlib.List.filter "list.mli" 327 10954 10954 "list.mli" 327 10954 11001
)
"Rust.ml" 676 25986 26009 "Rust.ml" 676 25986 26010
type(
  NameSet.elt
)
ident(
  def n "Rust.ml" 676 25986 26018 "Rust.ml" 676 25986 26059
)
"Rust.ml" 676 25986 26012 "Rust.ml" 676 25986 26013
type(
  API.call
)
"Rust.ml" 676 25986 26008 "Rust.ml" 676 25986 26014
type(
  NameSet.elt * API.call
)
"Rust.ml" 676 25986 26018 "Rust.ml" 676 25986 26021
type(
  bool -> bool
)
ident(
  int_ref Stdlib.not "stdlib.mli" 211 8889 8889 "stdlib.mli" 211 8889 8929
)
"Rust.ml" 676 25986 26023 "Rust.ml" 676 25986 26034
type(
  NameSet.elt -> NameSet.t -> bool
)
ident(
  int_ref NameSet.mem "set.mli" 80 3035 3039 "set.mli" 80 3035 3064
)
"Rust.ml" 676 25986 26035 "Rust.ml" 676 25986 26036
type(
  NameSet.elt
)
ident(
  int_ref n "Rust.ml" 676 25986 26009 "Rust.ml" 676 25986 26010
)
"Rust.ml" 676 25986 26037 "Rust.ml" 676 25986 26058
type(
  NameSet.t
)
ident(
  int_ref excluded_handle_calls "Rust.ml" 648 25060 25064 "Rust.ml" 648 25060 25085
)
"Rust.ml" 676 25986 26022 "Rust.ml" 676 25986 26059
type(
  bool
)
"Rust.ml" 676 25986 26018 "Rust.ml" 676 25986 26059
type(
  bool
)
"Rust.ml" 676 25986 26003 "Rust.ml" 676 25986 26060
type(
  NameSet.elt * API.call -> bool
)
"Rust.ml" 676 25986 25991 "Rust.ml" 676 25986 26060
type(
  (NameSet.elt * API.call) list -> (NameSet.elt * API.call) list
)
"Rust.ml" 675 25971 25973 "Rust.ml" 676 25986 26060
type(
  (NameSet.elt * API.call) list
)
"Rust.ml" 677 26061 26066 "Rust.ml" 677 26061 26076
type(
  (NameSet.elt * API.call ->
   (NameMap.key * (NameSet.elt * API.call * API.async_kind)) option) ->
  (NameSet.elt * API.call) list ->
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) list
)
ident(
  int_ref Utils.filter_map "utils.mli" 36 1205 1205 "utils.mli" 36 1205 1261
)
"Rust.ml" 677 26061 26083 "Rust.ml" 677 26061 26087
type(
  NameSet.elt
)
ident(
  def name "Rust.ml" 678 26098 26107 "Rust.ml" 680 26165 26224
)
"Rust.ml" 677 26061 26089 "Rust.ml" 677 26061 26093
type(
  API.call
)
ident(
  def call "Rust.ml" 678 26098 26107 "Rust.ml" 680 26165 26224
)
"Rust.ml" 677 26061 26082 "Rust.ml" 677 26061 26094
type(
  NameSet.elt * API.call
)
"Rust.ml" 678 26098 26107 "Rust.ml" 678 26098 26111
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 677 26061 26089 "Rust.ml" 677 26061 26093
)
"Rust.ml" 678 26098 26107 "Rust.ml" 678 26098 26122
type(
  API.async_kind option
)
"Rust.ml" 679 26123 26135 "Rust.ml" 679 26123 26145
type(
  (API.async_kind -> NameMap.key * (NameSet.elt * API.call * API.async_kind)) ->
  API.async_kind option ->
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) option
)
ident(
  int_ref Utils.option_map "utils.mli" 48 1770 1770 "utils.mli" 48 1770 1823
)
"Rust.ml" 679 26123 26151 "Rust.ml" 679 26123 26161
type(
  API.async_kind
)
ident(
  def async_kind "Rust.ml" 680 26165 26181 "Rust.ml" 680 26165 26223
)
"Rust.ml" 680 26165 26182 "Rust.ml" 680 26165 26191
type(
  NameSet.elt -> NameMap.key
)
ident(
  int_ref strip_aio "Rust.ml" 666 25525 25529 "Rust.ml" 666 25525 25538
)
"Rust.ml" 680 26165 26192 "Rust.ml" 680 26165 26196
type(
  NameSet.elt
)
ident(
  int_ref name "Rust.ml" 677 26061 26083 "Rust.ml" 677 26061 26087
)
"Rust.ml" 680 26165 26182 "Rust.ml" 680 26165 26196
type(
  NameMap.key
)
"Rust.ml" 680 26165 26199 "Rust.ml" 680 26165 26203
type(
  NameSet.elt
)
ident(
  int_ref name "Rust.ml" 677 26061 26083 "Rust.ml" 677 26061 26087
)
"Rust.ml" 680 26165 26205 "Rust.ml" 680 26165 26209
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 677 26061 26089 "Rust.ml" 677 26061 26093
)
"Rust.ml" 680 26165 26211 "Rust.ml" 680 26165 26221
type(
  API.async_kind
)
ident(
  int_ref async_kind "Rust.ml" 679 26123 26151 "Rust.ml" 679 26123 26161
)
"Rust.ml" 680 26165 26198 "Rust.ml" 680 26165 26222
type(
  NameSet.elt * API.call * API.async_kind
)
"Rust.ml" 680 26165 26181 "Rust.ml" 680 26165 26223
type(
  NameMap.key * (NameSet.elt * API.call * API.async_kind)
)
"Rust.ml" 679 26123 26146 "Rust.ml" 680 26165 26224
type(
  API.async_kind -> NameMap.key * (NameSet.elt * API.call * API.async_kind)
)
"Rust.ml" 679 26123 26135 "Rust.ml" 680 26165 26224
type(
  API.async_kind option ->
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) option
)
"Rust.ml" 678 26098 26107 "Rust.ml" 680 26165 26224
type(
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) option
)
"Rust.ml" 677 26061 26077 "Rust.ml" 680 26165 26225
type(
  NameSet.elt * API.call ->
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) option
)
"Rust.ml" 677 26061 26066 "Rust.ml" 680 26165 26225
type(
  (NameSet.elt * API.call) list ->
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) list
)
"Rust.ml" 675 25971 25973 "Rust.ml" 680 26165 26225
type(
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) list
)
"Rust.ml" 681 26226 26231 "Rust.ml" 681 26226 26245
type(
  ((NameSet.elt * API.call * API.async_kind) NameMap.t ->
   NameMap.key * (NameSet.elt * API.call * API.async_kind) ->
   (NameSet.elt * API.call * API.async_kind) NameMap.t) ->
  (NameSet.elt * API.call * API.async_kind) NameMap.t ->
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) list ->
  (NameSet.elt * API.call * API.async_kind) NameMap.t
)
ident(
  int_ref Stdlib.List.fold_left "list.mli" 211 7387 7387 "list.mli" 211 7387 7442
)
"Rust.ml" 681 26226 26251 "Rust.ml" 681 26226 26252
type(
  (NameSet.elt * API.call * API.async_kind) NameMap.t
)
ident(
  def m "Rust.ml" 681 26226 26253 "Rust.ml" 681 26226 26280
)
"Rust.ml" 681 26226 26254 "Rust.ml" 681 26226 26255
type(
  NameMap.key
)
ident(
  def k "Rust.ml" 681 26226 26263 "Rust.ml" 681 26226 26280
)
"Rust.ml" 681 26226 26257 "Rust.ml" 681 26226 26258
type(
  NameSet.elt * API.call * API.async_kind
)
ident(
  def v "Rust.ml" 681 26226 26263 "Rust.ml" 681 26226 26280
)
"Rust.ml" 681 26226 26253 "Rust.ml" 681 26226 26259
type(
  NameMap.key * (NameSet.elt * API.call * API.async_kind)
)
"Rust.ml" 681 26226 26263 "Rust.ml" 681 26226 26274
type(
  NameMap.key ->
  NameSet.elt * API.call * API.async_kind ->
  (NameSet.elt * API.call * API.async_kind) NameMap.t ->
  (NameSet.elt * API.call * API.async_kind) NameMap.t
)
ident(
  int_ref NameMap.add "map.mli" 83 3211 3215 "map.mli" 83 3211 3249
)
"Rust.ml" 681 26226 26275 "Rust.ml" 681 26226 26276
type(
  NameMap.key
)
ident(
  int_ref k "Rust.ml" 681 26226 26254 "Rust.ml" 681 26226 26255
)
"Rust.ml" 681 26226 26277 "Rust.ml" 681 26226 26278
type(
  NameSet.elt * API.call * API.async_kind
)
ident(
  int_ref v "Rust.ml" 681 26226 26257 "Rust.ml" 681 26226 26258
)
"Rust.ml" 681 26226 26279 "Rust.ml" 681 26226 26280
type(
  (NameSet.elt * API.call * API.async_kind) NameMap.t
)
ident(
  int_ref m "Rust.ml" 681 26226 26251 "Rust.ml" 681 26226 26252
)
"Rust.ml" 681 26226 26263 "Rust.ml" 681 26226 26280
type(
  (NameSet.elt * API.call * API.async_kind) NameMap.t
)
"Rust.ml" 681 26226 26246 "Rust.ml" 681 26226 26281
type(
  (NameSet.elt * API.call * API.async_kind) NameMap.t ->
  NameMap.key * (NameSet.elt * API.call * API.async_kind) ->
  (NameSet.elt * API.call * API.async_kind) NameMap.t
)
"Rust.ml" 681 26226 26282 "Rust.ml" 681 26226 26295
type(
  (NameSet.elt * API.call * API.async_kind) NameMap.t
)
ident(
  int_ref NameMap.empty "map.mli" 73 2950 2954 "map.mli" 73 2950 2969
)
"Rust.ml" 681 26226 26231 "Rust.ml" 681 26226 26295
type(
  (NameMap.key * (NameSet.elt * API.call * API.async_kind)) list ->
  (NameSet.elt * API.call * API.async_kind) NameMap.t
)
"Rust.ml" 675 25971 25973 "Rust.ml" 681 26226 26295
type(
  (string * API.call * API.async_kind) NameMap.t
)
"Rust.ml" 687 26575 26579 "Rust.ml" 687 26575 26596
type(
  API.call NameMap.t
)
ident(
  def sync_handle_calls "Rust.ml" 695 26978 26978 "Rust.ml" 0 0 -1
)
"Rust.ml" 688 26616 26618 "Rust.ml" 688 26616 26630
type(
  (NameMap.key * API.call) list
)
ident(
  int_ref API.handle_calls "API.mli" 148 7854 7854 "API.mli" 148 7854 7893
)
"Rust.ml" 689 26631 26636 "Rust.ml" 689 26631 26647
type(
  (NameMap.key * API.call -> bool) ->
  (NameMap.key * API.call) list -> (NameMap.key * API.call) list
)
ident(
  int_ref Stdlib.List.filter "list.mli" 327 10954 10954 "list.mli" 327 10954 11001
)
"Rust.ml" 689 26631 26654 "Rust.ml" 689 26631 26655
type(
  NameSet.elt
)
ident(
  def n "Rust.ml" 689 26631 26663 "Rust.ml" 689 26631 26704
)
"Rust.ml" 689 26631 26657 "Rust.ml" 689 26631 26658
type(
  API.call
)
"Rust.ml" 689 26631 26653 "Rust.ml" 689 26631 26659
type(
  NameSet.elt * API.call
)
"Rust.ml" 689 26631 26663 "Rust.ml" 689 26631 26666
type(
  bool -> bool
)
ident(
  int_ref Stdlib.not "stdlib.mli" 211 8889 8889 "stdlib.mli" 211 8889 8929
)
"Rust.ml" 689 26631 26668 "Rust.ml" 689 26631 26679
type(
  NameSet.elt -> NameSet.t -> bool
)
ident(
  int_ref NameSet.mem "set.mli" 80 3035 3039 "set.mli" 80 3035 3064
)
"Rust.ml" 689 26631 26680 "Rust.ml" 689 26631 26681
type(
  NameSet.elt
)
ident(
  int_ref n "Rust.ml" 689 26631 26654 "Rust.ml" 689 26631 26655
)
"Rust.ml" 689 26631 26682 "Rust.ml" 689 26631 26703
type(
  NameSet.t
)
ident(
  int_ref excluded_handle_calls "Rust.ml" 648 25060 25064 "Rust.ml" 648 25060 25085
)
"Rust.ml" 689 26631 26667 "Rust.ml" 689 26631 26704
type(
  bool
)
"Rust.ml" 689 26631 26663 "Rust.ml" 689 26631 26704
type(
  bool
)
"Rust.ml" 689 26631 26648 "Rust.ml" 689 26631 26705
type(
  NameMap.key * API.call -> bool
)
"Rust.ml" 689 26631 26636 "Rust.ml" 689 26631 26705
type(
  (NameMap.key * API.call) list -> (NameMap.key * API.call) list
)
"Rust.ml" 688 26616 26618 "Rust.ml" 689 26631 26705
type(
  (NameMap.key * API.call) list
)
"Rust.ml" 690 26706 26711 "Rust.ml" 690 26706 26722
type(
  (NameMap.key * API.call -> bool) ->
  (NameMap.key * API.call) list -> (NameMap.key * API.call) list
)
ident(
  int_ref Stdlib.List.filter "list.mli" 327 10954 10954 "list.mli" 327 10954 11001
)
"Rust.ml" 690 26706 26729 "Rust.ml" 690 26706 26730
type(
  NameMap.key
)
ident(
  def n "Rust.ml" 690 26706 26738 "Rust.ml" 690 26706 26776
)
"Rust.ml" 690 26706 26732 "Rust.ml" 690 26706 26733
type(
  API.call
)
"Rust.ml" 690 26706 26728 "Rust.ml" 690 26706 26734
type(
  NameMap.key * API.call
)
"Rust.ml" 690 26706 26738 "Rust.ml" 690 26706 26741
type(
  bool -> bool
)
ident(
  int_ref Stdlib.not "stdlib.mli" 211 8889 8889 "stdlib.mli" 211 8889 8929
)
"Rust.ml" 690 26706 26743 "Rust.ml" 690 26706 26754
type(
  NameMap.key -> (string * API.call * API.async_kind) NameMap.t -> bool
)
ident(
  int_ref NameMap.mem "map.mli" 79 3076 3080 "map.mli" 79 3076 3108
)
"Rust.ml" 690 26706 26755 "Rust.ml" 690 26706 26756
type(
  NameMap.key
)
ident(
  int_ref n "Rust.ml" 690 26706 26729 "Rust.ml" 690 26706 26730
)
"Rust.ml" 690 26706 26757 "Rust.ml" 690 26706 26775
type(
  (string * API.call * API.async_kind) NameMap.t
)
ident(
  int_ref async_handle_calls "Rust.ml" 674 25905 25909 "Rust.ml" 674 25905 25927
)
"Rust.ml" 690 26706 26742 "Rust.ml" 690 26706 26776
type(
  bool
)
"Rust.ml" 690 26706 26738 "Rust.ml" 690 26706 26776
type(
  bool
)
"Rust.ml" 690 26706 26723 "Rust.ml" 690 26706 26777
type(
  NameMap.key * API.call -> bool
)
"Rust.ml" 690 26706 26711 "Rust.ml" 690 26706 26777
type(
  (NameMap.key * API.call) list -> (NameMap.key * API.call) list
)
"Rust.ml" 688 26616 26618 "Rust.ml" 690 26706 26777
type(
  (NameMap.key * API.call) list
)
"Rust.ml" 691 26778 26783 "Rust.ml" 691 26778 26797
type(
  (API.call NameMap.t -> NameMap.key * API.call -> API.call NameMap.t) ->
  API.call NameMap.t -> (NameMap.key * API.call) list -> API.call NameMap.t
)
ident(
  int_ref Stdlib.List.fold_left "list.mli" 211 7387 7387 "list.mli" 211 7387 7442
)
"Rust.ml" 691 26778 26803 "Rust.ml" 691 26778 26804
type(
  API.call NameMap.t
)
ident(
  def m "Rust.ml" 691 26778 26805 "Rust.ml" 691 26778 26832
)
"Rust.ml" 691 26778 26806 "Rust.ml" 691 26778 26807
type(
  NameMap.key
)
ident(
  def k "Rust.ml" 691 26778 26815 "Rust.ml" 691 26778 26832
)
"Rust.ml" 691 26778 26809 "Rust.ml" 691 26778 26810
type(
  API.call
)
ident(
  def v "Rust.ml" 691 26778 26815 "Rust.ml" 691 26778 26832
)
"Rust.ml" 691 26778 26805 "Rust.ml" 691 26778 26811
type(
  NameMap.key * API.call
)
"Rust.ml" 691 26778 26815 "Rust.ml" 691 26778 26826
type(
  NameMap.key -> API.call -> API.call NameMap.t -> API.call NameMap.t
)
ident(
  int_ref NameMap.add "map.mli" 83 3211 3215 "map.mli" 83 3211 3249
)
"Rust.ml" 691 26778 26827 "Rust.ml" 691 26778 26828
type(
  NameMap.key
)
ident(
  int_ref k "Rust.ml" 691 26778 26806 "Rust.ml" 691 26778 26807
)
"Rust.ml" 691 26778 26829 "Rust.ml" 691 26778 26830
type(
  API.call
)
ident(
  int_ref v "Rust.ml" 691 26778 26809 "Rust.ml" 691 26778 26810
)
"Rust.ml" 691 26778 26831 "Rust.ml" 691 26778 26832
type(
  API.call NameMap.t
)
ident(
  int_ref m "Rust.ml" 691 26778 26803 "Rust.ml" 691 26778 26804
)
"Rust.ml" 691 26778 26815 "Rust.ml" 691 26778 26832
type(
  API.call NameMap.t
)
"Rust.ml" 691 26778 26798 "Rust.ml" 691 26778 26833
type(
  API.call NameMap.t -> NameMap.key * API.call -> API.call NameMap.t
)
"Rust.ml" 691 26778 26834 "Rust.ml" 691 26778 26847
type(
  API.call NameMap.t
)
ident(
  int_ref NameMap.empty "map.mli" 73 2950 2954 "map.mli" 73 2950 2969
)
"Rust.ml" 691 26778 26783 "Rust.ml" 691 26778 26847
type(
  (NameMap.key * API.call) list -> API.call NameMap.t
)
"Rust.ml" 688 26616 26618 "Rust.ml" 691 26778 26847
type(
  API.call NameMap.t
)
"Rust.ml" 695 26978 26982 "Rust.ml" 695 26978 27001
type(
  API.arg -> string
)
ident(
  def rust_async_arg_type "Rust.ml" 702 27266 27266 "Rust.ml" 0 0 -1
)
"Rust.ml" 696 27029 27048 "Rust.ml" 696 27029 27049
type(
  string
)
type(
  string
)
"Rust.ml" 696 27029 27033 "Rust.ml" 696 27029 27049
type(
  API.arg
)
"Rust.ml" 696 27029 27053 "Rust.ml" 696 27029 27060
type(
  string
)
"Rust.ml" 697 27061 27081 "Rust.ml" 697 27061 27082
type(
  string
)
type(
  string
)
"Rust.ml" 697 27061 27065 "Rust.ml" 697 27061 27082
type(
  API.arg
)
"Rust.ml" 697 27061 27086 "Rust.ml" 697 27061 27097
type(
  string
)
"Rust.ml" 698 27098 27102 "Rust.ml" 698 27098 27103
type(
  API.arg
)
ident(
  def x "Rust.ml" 698 27098 27107 "Rust.ml" 698 27098 27122
)
"Rust.ml" 698 27098 27107 "Rust.ml" 698 27098 27120
type(
  API.arg -> string
)
ident(
  int_ref rust_arg_type "Rust.ml" 133 4026 4034 "Rust.ml" 133 4026 4047
)
"Rust.ml" 698 27098 27121 "Rust.ml" 698 27098 27122
type(
  API.arg
)
ident(
  int_ref x "Rust.ml" 698 27098 27102 "Rust.ml" 698 27098 27103
)
"Rust.ml" 698 27098 27107 "Rust.ml" 698 27098 27122
type(
  string
)
"Rust.ml" 695 26978 27020 "Rust.ml" 698 27098 27122
type(
  API.arg -> string
)
"Rust.ml" 702 27266 27270 "Rust.ml" 702 27266 27292
type(
  API.optarg -> string
)
ident(
  def rust_async_optarg_type "Rust.ml" 708 27536 27536 "Rust.ml" 0 0 -1
)
"Rust.ml" 703 27323 27336 "Rust.ml" 703 27323 27337
type(
  API.closure
)
ident(
  def x "Rust.ml" 703 27323 27341 "Rust.ml" 703 27323 27395
)
"Rust.ml" 703 27323 27327 "Rust.ml" 703 27323 27337
type(
  API.optarg
)
"Rust.ml" 703 27323 27341 "Rust.ml" 703 27323 27348
type(
  (string -> string, unit, string) format -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 703 27323 27349 "Rust.ml" 703 27323 27361
type(
  (string -> string, unit, string) format
)
"Rust.ml" 703 27323 27363 "Rust.ml" 703 27323 27382
type(
  API.arg -> string
)
ident(
  int_ref rust_async_arg_type "Rust.ml" 695 26978 26982 "Rust.ml" 695 26978 27001
)
"Rust.ml" 703 27323 27392 "Rust.ml" 703 27323 27393
type(
  API.closure
)
ident(
  int_ref x "Rust.ml" 703 27323 27336 "Rust.ml" 703 27323 27337
)
"Rust.ml" 703 27323 27383 "Rust.ml" 703 27323 27394
type(
  API.arg
)
"Rust.ml" 703 27323 27362 "Rust.ml" 703 27323 27395
type(
  string
)
"Rust.ml" 703 27323 27341 "Rust.ml" 703 27323 27395
type(
  string
)
"Rust.ml" 704 27396 27400 "Rust.ml" 704 27396 27401
type(
  API.optarg
)
ident(
  def x "Rust.ml" 704 27396 27405 "Rust.ml" 704 27396 27423
)
"Rust.ml" 704 27396 27405 "Rust.ml" 704 27396 27421
type(
  API.optarg -> string
)
ident(
  int_ref rust_optarg_type "Rust.ml" 176 5671 5675 "Rust.ml" 176 5671 5691
)
"Rust.ml" 704 27396 27422 "Rust.ml" 704 27396 27423
type(
  API.optarg
)
ident(
  int_ref x "Rust.ml" 704 27396 27400 "Rust.ml" 704 27396 27401
)
"Rust.ml" 704 27396 27405 "Rust.ml" 704 27396 27423
type(
  string
)
"Rust.ml" 702 27266 27314 "Rust.ml" 704 27396 27423
type(
  API.optarg -> string
)
"Rust.ml" 708 27536 27540 "Rust.ml" 708 27536 27567
type(
  API.call -> string
)
ident(
  def rust_async_handle_call_args "Rust.ml" 719 27952 27952 "Rust.ml" 0 0 -1
)
"Rust.ml" 708 27536 27570 "Rust.ml" 708 27536 27574
type(
  API.arg list
)
ident(
  def args "Rust.ml" 709 27597 27599 "Rust.ml" 716 27823 27889
)
"Rust.ml" 708 27536 27576 "Rust.ml" 708 27536 27583
type(
  API.optarg list
)
ident(
  def optargs "Rust.ml" 709 27597 27599 "Rust.ml" 716 27823 27889
)
"Rust.ml" 708 27536 27568 "Rust.ml" 708 27536 27585
type(
  API.call
)
"Rust.ml" 709 27597 27603 "Rust.ml" 709 27597 27618
type(
  string list
)
ident(
  def rust_args_names "Rust.ml" 715 27802 27804 "Rust.ml" 716 27823 27889
)
"Rust.ml" 710 27621 27625 "Rust.ml" 710 27621 27633
type(
  (API.arg -> string) -> API.arg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 710 27621 27634 "Rust.ml" 710 27621 27647
type(
  API.arg -> string
)
ident(
  int_ref rust_arg_name "Rust.ml" 97 3181 3185 "Rust.ml" 97 3181 3198
)
"Rust.ml" 710 27621 27648 "Rust.ml" 710 27621 27652
type(
  API.arg list
)
ident(
  int_ref args "Rust.ml" 708 27536 27570 "Rust.ml" 708 27536 27574
)
"Rust.ml" 710 27621 27625 "Rust.ml" 710 27621 27652
type(
  string list
)
"Rust.ml" 710 27621 27653 "Rust.ml" 710 27621 27654
type(
  string list -> string list -> string list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 710 27621 27655 "Rust.ml" 710 27621 27663
type(
  (API.optarg -> string) -> API.optarg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 710 27621 27664 "Rust.ml" 710 27621 27680
type(
  API.optarg -> string
)
ident(
  int_ref rust_optarg_name "Rust.ml" 122 3625 3629 "Rust.ml" 122 3625 3645
)
"Rust.ml" 710 27621 27681 "Rust.ml" 710 27621 27688
type(
  API.optarg list
)
ident(
  int_ref optargs "Rust.ml" 708 27536 27576 "Rust.ml" 708 27536 27583
)
"Rust.ml" 710 27621 27655 "Rust.ml" 710 27621 27688
type(
  string list
)
"Rust.ml" 710 27621 27625 "Rust.ml" 710 27621 27688
type(
  string list
)
"Rust.ml" 711 27689 27695 "Rust.ml" 711 27689 27710
type(
  string list
)
ident(
  def rust_args_types "Rust.ml" 715 27802 27804 "Rust.ml" 716 27823 27889
)
"Rust.ml" 712 27713 27717 "Rust.ml" 712 27713 27725
type(
  (API.arg -> string) -> API.arg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 712 27713 27726 "Rust.ml" 712 27713 27745
type(
  API.arg -> string
)
ident(
  int_ref rust_async_arg_type "Rust.ml" 695 26978 26982 "Rust.ml" 695 26978 27001
)
"Rust.ml" 712 27713 27746 "Rust.ml" 712 27713 27750
type(
  API.arg list
)
ident(
  int_ref args "Rust.ml" 708 27536 27570 "Rust.ml" 708 27536 27574
)
"Rust.ml" 712 27713 27717 "Rust.ml" 712 27713 27750
type(
  string list
)
"Rust.ml" 713 27751 27755 "Rust.ml" 713 27751 27756
type(
  string list -> string list -> string list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 713 27751 27757 "Rust.ml" 713 27751 27765
type(
  (API.optarg -> string) -> API.optarg list -> string list
)
ident(
  int_ref Stdlib.List.map "list.mli" 172 6124 6124 "list.mli" 172 6124 6166
)
"Rust.ml" 713 27751 27766 "Rust.ml" 713 27751 27788
type(
  API.optarg -> string
)
ident(
  int_ref rust_async_optarg_type "Rust.ml" 702 27266 27270 "Rust.ml" 702 27266 27292
)
"Rust.ml" 713 27751 27789 "Rust.ml" 713 27751 27796
type(
  API.optarg list
)
ident(
  int_ref optargs "Rust.ml" 708 27536 27576 "Rust.ml" 708 27536 27583
)
"Rust.ml" 713 27751 27757 "Rust.ml" 713 27751 27796
type(
  string list
)
"Rust.ml" 712 27713 27717 "Rust.ml" 713 27751 27796
type(
  string list
)
"Rust.ml" 715 27802 27804 "Rust.ml" 715 27802 27817
type(
  string -> string list -> string
)
ident(
  int_ref Stdlib.String.concat "string.mli" 132 5016 5016 "string.mli" 132 5016 5060
)
"Rust.ml" 715 27802 27818 "Rust.ml" 715 27802 27822
type(
  string
)
"Rust.ml" 716 27823 27828 "Rust.ml" 716 27823 27837
type(
  (string -> string -> string) -> string list -> string list -> string list
)
ident(
  int_ref Stdlib.List.map2 "list.mli" 232 7967 7967 "list.mli" 232 7967 8027
)
"Rust.ml" 716 27823 27839 "Rust.ml" 716 27823 27846
type(
  (string -> string -> string, unit, string) format ->
  string -> string -> string
)
ident(
  int_ref Stdlib.Printf.sprintf "printf.mli" 135 7108 7108 "printf.mli" 135 7108 7153
)
"Rust.ml" 716 27823 27847 "Rust.ml" 716 27823 27855
type(
  (string -> string -> string, unit, string) format
)
"Rust.ml" 716 27823 27838 "Rust.ml" 716 27823 27856
type(
  string -> string -> string
)
"Rust.ml" 716 27823 27857 "Rust.ml" 716 27823 27872
type(
  string list
)
ident(
  int_ref rust_args_names "Rust.ml" 709 27597 27603 "Rust.ml" 709 27597 27618
)
"Rust.ml" 716 27823 27873 "Rust.ml" 716 27823 27888
type(
  string list
)
ident(
  int_ref rust_args_types "Rust.ml" 711 27689 27695 "Rust.ml" 711 27689 27710
)
"Rust.ml" 716 27823 27827 "Rust.ml" 716 27823 27889
type(
  string list
)
"Rust.ml" 715 27802 27804 "Rust.ml" 716 27823 27889
type(
  string
)
"Rust.ml" 709 27597 27599 "Rust.ml" 716 27823 27889
type(
  string
)
"Rust.ml" 719 27952 27956 "Rust.ml" 719 27952 27983
type(
  string -> API.call -> unit
)
ident(
  def print_rust_sync_handle_call "Rust.ml" 730 28383 28383 "Rust.ml" 0 0 -1
)
"Rust.ml" 719 27952 27984 "Rust.ml" 719 27952 27988
type(
  string
)
ident(
  def name "Rust.ml" 719 27952 27989 "Rust.ml" 725 28200 28209
)
"Rust.ml" 719 27952 27989 "Rust.ml" 719 27952 27993
type(
  API.call
)
ident(
  def call "Rust.ml" 720 27996 27998 "Rust.ml" 725 28200 28209
)
"Rust.ml" 720 27996 27998 "Rust.ml" 720 27996 28028
type(
  string -> API.call -> unit
)
ident(
  int_ref print_rust_handle_call_comment "Rust.ml" 479 18615 18623 "Rust.ml" 479 18615 18653
)
"Rust.ml" 720 27996 28029 "Rust.ml" 720 27996 28033
type(
  string
)
ident(
  int_ref name "Rust.ml" 719 27952 27984 "Rust.ml" 719 27952 27988
)
"Rust.ml" 720 27996 28034 "Rust.ml" 720 27996 28038
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 719 27952 27989 "Rust.ml" 719 27952 27993
)
"Rust.ml" 720 27996 27998 "Rust.ml" 720 27996 28038
type(
  unit
)
"Rust.ml" 721 28040 28042 "Rust.ml" 721 28040 28044
type(
  (string -> string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 721 28040 28045 "Rust.ml" 721 28040 28075
type(
  (string -> string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 721 28040 28076 "Rust.ml" 721 28040 28080
type(
  string
)
ident(
  int_ref name "Rust.ml" 719 27952 27984 "Rust.ml" 719 27952 27988
)
"Rust.ml" 722 28081 28086 "Rust.ml" 722 28081 28113
type(
  API.call -> string
)
ident(
  int_ref rust_async_handle_call_args "Rust.ml" 708 27536 27540 "Rust.ml" 708 27536 27567
)
"Rust.ml" 722 28081 28114 "Rust.ml" 722 28081 28118
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 719 27952 27989 "Rust.ml" 719 27952 27993
)
"Rust.ml" 722 28081 28085 "Rust.ml" 722 28081 28119
type(
  string
)
"Rust.ml" 723 28120 28125 "Rust.ml" 723 28120 28138
type(
  API.call -> string
)
ident(
  int_ref rust_ret_type "Rust.ml" 247 8339 8343 "Rust.ml" 247 8339 8356
)
"Rust.ml" 723 28120 28139 "Rust.ml" 723 28120 28143
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 719 27952 27989 "Rust.ml" 719 27952 27993
)
"Rust.ml" 723 28120 28124 "Rust.ml" 723 28120 28144
type(
  string
)
"Rust.ml" 721 28040 28042 "Rust.ml" 723 28120 28144
type(
  unit
)
"Rust.ml" 724 28146 28148 "Rust.ml" 724 28146 28162
type(
  string -> string -> API.call -> unit
)
ident(
  int_ref print_ffi_call "Rust.ml" 569 22197 22201 "Rust.ml" 569 22197 22215
)
"Rust.ml" 724 28146 28163 "Rust.ml" 724 28146 28167
type(
  string
)
ident(
  int_ref name "Rust.ml" 719 27952 27984 "Rust.ml" 719 27952 27988
)
"Rust.ml" 724 28146 28168 "Rust.ml" 724 28146 28193
type(
  string
)
"Rust.ml" 724 28146 28194 "Rust.ml" 724 28146 28198
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 719 27952 27989 "Rust.ml" 719 27952 27993
)
"Rust.ml" 724 28146 28148 "Rust.ml" 724 28146 28198
type(
  unit
)
"Rust.ml" 725 28200 28202 "Rust.ml" 725 28200 28204
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 725 28200 28205 "Rust.ml" 725 28200 28209
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 725 28200 28202 "Rust.ml" 725 28200 28209
type(
  unit
)
"Rust.ml" 724 28146 28148 "Rust.ml" 725 28200 28209
type(
  unit
)
"Rust.ml" 721 28040 28042 "Rust.ml" 725 28200 28209
type(
  unit
)
"Rust.ml" 720 27996 27998 "Rust.ml" 725 28200 28209
type(
  unit
)
"Rust.ml" 730 28383 28387 "Rust.ml" 730 28383 28434
type(
  string -> string -> API.call -> unit
)
ident(
  def print_rust_async_handle_call_with_completion_cb "Rust.ml" 811 31671 31671 "Rust.ml" 0 0 -1
)
"Rust.ml" 730 28383 28435 "Rust.ml" 730 28383 28439
type(
  string
)
ident(
  def name "Rust.ml" 730 28383 28440 "Rust.ml" 805 31426 31438
)
"Rust.ml" 730 28383 28440 "Rust.ml" 730 28383 28448
type(
  string
)
ident(
  def aio_name "Rust.ml" 730 28383 28449 "Rust.ml" 805 31426 31438
)
"Rust.ml" 730 28383 28449 "Rust.ml" 730 28383 28453
type(
  API.call
)
ident(
  def call "Rust.ml" 733 28579 28581 "Rust.ml" 805 31426 31438
)
"Rust.ml" 733 28579 28585 "Rust.ml" 733 28579 28592
type(
  API.optarg array
)
ident(
  def optargs "Rust.ml" 735 28683 28685 "Rust.ml" 805 31426 31438
)
"Rust.ml" 733 28579 28595 "Rust.ml" 733 28579 28608
type(
  API.optarg list -> API.optarg array
)
ident(
  int_ref Stdlib.Array.of_list "array.mli" 153 6321 6321 "array.mli" 153 6321 6354
)
"Rust.ml" 733 28579 28609 "Rust.ml" 733 28579 28613
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 730 28383 28449 "Rust.ml" 730 28383 28453
)
"Rust.ml" 733 28579 28609 "Rust.ml" 733 28579 28621
type(
  API.optarg list
)
"Rust.ml" 733 28579 28595 "Rust.ml" 733 28579 28621
type(
  API.optarg array
)
"Rust.ml" 735 28683 28689 "Rust.ml" 735 28683 28708
type(
  int option
)
ident(
  def completion_cb_index "Rust.ml" 744 28947 28949 "Rust.ml" 805 31426 31438
)
"Rust.ml" 736 28711 28715 "Rust.ml" 736 28711 28729
type(
  (int * API.optarg -> int option) -> (int * API.optarg) array -> int option
)
ident(
  int_ref Utils.array_find_map "utils.mli" 47 1706 1706 "utils.mli" 47 1706 1769
)
"Rust.ml" 737 28730 28742 "Rust.ml" 737 28730 28743
type(
  int
)
ident(
  def i "Rust.ml" 738 28756 28764 "Rust.ml" 741 28874 28893
)
"Rust.ml" 737 28730 28745 "Rust.ml" 737 28730 28751
type(
  API.optarg
)
ident(
  def optarg "Rust.ml" 738 28756 28764 "Rust.ml" 741 28874 28893
)
"Rust.ml" 737 28730 28741 "Rust.ml" 737 28730 28752
type(
  int * API.optarg
)
"Rust.ml" 738 28756 28770 "Rust.ml" 738 28756 28776
type(
  API.optarg
)
ident(
  int_ref optarg "Rust.ml" 737 28730 28745 "Rust.ml" 737 28730 28751
)
"Rust.ml" 739 28782 28803 "Rust.ml" 739 28782 28809
type(
  string
)
ident(
  def cbname "Rust.ml" 740 28815 28827 "Rust.ml" 740 28815 28873
)
"Rust.ml" 739 28782 28801 "Rust.ml" 739 28782 28811
type(
  API.closure
)
"Rust.ml" 739 28782 28792 "Rust.ml" 739 28782 28811
type(
  API.optarg
)
type(
  API.optarg
)
"Rust.ml" 740 28815 28830 "Rust.ml" 740 28815 28836
type(
  string
)
ident(
  int_ref cbname "Rust.ml" 739 28782 28803 "Rust.ml" 739 28782 28809
)
"Rust.ml" 740 28815 28837 "Rust.ml" 740 28815 28838
type(
  string -> string -> bool
)
ident(
  int_ref Stdlib.( = ) "stdlib.mli" 121 5051 5051 "stdlib.mli" 121 5051 5095
)
"Rust.ml" 740 28815 28839 "Rust.ml" 740 28815 28851
type(
  string
)
"Rust.ml" 740 28815 28830 "Rust.ml" 740 28815 28851
type(
  bool
)
"Rust.ml" 740 28815 28862 "Rust.ml" 740 28815 28863
type(
  int
)
ident(
  int_ref i "Rust.ml" 737 28730 28742 "Rust.ml" 737 28730 28743
)
"Rust.ml" 740 28815 28857 "Rust.ml" 740 28815 28863
type(
  int option
)
"Rust.ml" 740 28815 28869 "Rust.ml" 740 28815 28873
type(
  int option
)
"Rust.ml" 740 28815 28827 "Rust.ml" 740 28815 28873
type(
  int option
)
"Rust.ml" 741 28874 28884 "Rust.ml" 741 28874 28885
type(
  API.optarg
)
type(
  API.optarg
)
"Rust.ml" 741 28874 28889 "Rust.ml" 741 28874 28893
type(
  int option
)
"Rust.ml" 738 28756 28764 "Rust.ml" 741 28874 28893
type(
  int option
)
"Rust.ml" 737 28730 28736 "Rust.ml" 741 28874 28894
type(
  int * API.optarg -> int option
)
"Rust.ml" 742 28895 28902 "Rust.ml" 742 28895 28912
type(
  (int -> API.optarg -> int * API.optarg) ->
  API.optarg array -> (int * API.optarg) array
)
ident(
  int_ref Stdlib.Array.mapi "array.mli" 177 7166 7166 "array.mli" 177 7166 7218
)
"Rust.ml" 742 28895 28918 "Rust.ml" 742 28895 28919
type(
  int
)
ident(
  def x "Rust.ml" 742 28895 28920 "Rust.ml" 742 28895 28931
)
"Rust.ml" 742 28895 28920 "Rust.ml" 742 28895 28921
type(
  API.optarg
)
ident(
  def y "Rust.ml" 742 28895 28925 "Rust.ml" 742 28895 28931
)
"Rust.ml" 742 28895 28926 "Rust.ml" 742 28895 28927
type(
  int
)
ident(
  int_ref x "Rust.ml" 742 28895 28918 "Rust.ml" 742 28895 28919
)
"Rust.ml" 742 28895 28929 "Rust.ml" 742 28895 28930
type(
  API.optarg
)
ident(
  int_ref y "Rust.ml" 742 28895 28920 "Rust.ml" 742 28895 28921
)
"Rust.ml" 742 28895 28925 "Rust.ml" 742 28895 28931
type(
  int * API.optarg
)
"Rust.ml" 742 28895 28913 "Rust.ml" 742 28895 28932
type(
  int -> API.optarg -> int * API.optarg
)
"Rust.ml" 742 28895 28933 "Rust.ml" 742 28895 28940
type(
  API.optarg array
)
ident(
  int_ref optargs "Rust.ml" 733 28579 28585 "Rust.ml" 733 28579 28592
)
"Rust.ml" 742 28895 28901 "Rust.ml" 742 28895 28941
type(
  (int * API.optarg) array
)
"Rust.ml" 736 28711 28715 "Rust.ml" 742 28895 28941
type(
  int option
)
"Rust.ml" 744 28947 28953 "Rust.ml" 744 28947 28972
type(
  int
)
ident(
  def completion_cb_index "Rust.ml" 754 29275 29277 "Rust.ml" 805 31426 31438
)
"Rust.ml" 745 28975 28985 "Rust.ml" 745 28975 29004
type(
  int option
)
ident(
  int_ref completion_cb_index "Rust.ml" 735 28683 28689 "Rust.ml" 735 28683 28708
)
"Rust.ml" 746 29010 29021 "Rust.ml" 746 29010 29022
type(
  int
)
ident(
  def x "Rust.ml" 746 29010 29026 "Rust.ml" 746 29010 29027
)
"Rust.ml" 746 29010 29016 "Rust.ml" 746 29010 29022
type(
  int option
)
type(
  int option
)
"Rust.ml" 746 29010 29026 "Rust.ml" 746 29010 29027
type(
  int
)
ident(
  int_ref x "Rust.ml" 746 29010 29021 "Rust.ml" 746 29010 29022
)
"Rust.ml" 747 29028 29034 "Rust.ml" 747 29028 29038
type(
  int option
)
type(
  int option
)
"Rust.ml" 748 29042 29050 "Rust.ml" 748 29042 29059
type(
  (string -> int, unit, string, int) format4 -> string -> int
)
ident(
  int_ref Utils.failwithf "utils.mli" 34 1151 1151 "utils.mli" 34 1151 1203
)
"Rust.ml" 749 29060 29070 "Rust.ml" 751 29218 29250
type(
  (string -> int, unit, string, int) format4
)
"Rust.ml" 752 29251 29261 "Rust.ml" 752 29251 29269
type(
  string
)
ident(
  int_ref aio_name "Rust.ml" 730 28383 28440 "Rust.ml" 730 28383 28448
)
"Rust.ml" 748 29042 29050 "Rust.ml" 752 29251 29269
type(
  int
)
"Rust.ml" 745 28975 28979 "Rust.ml" 752 29251 29269
type(
  int
)
"Rust.ml" 754 29275 29281 "Rust.ml" 754 29275 29309
type(
  API.optarg list
)
ident(
  def optargs_before_completion_cb "Rust.ml" 762 29609 29611 "Rust.ml" 805 31426 31438
)
"Rust.ml" 755 29312 29316 "Rust.ml" 755 29312 29329
type(
  API.optarg array -> API.optarg list
)
ident(
  int_ref Stdlib.Array.to_list "array.mli" 150 6222 6222 "array.mli" 150 6222 6255
)
"Rust.ml" 755 29312 29331 "Rust.ml" 755 29312 29340
type(
  API.optarg array -> int -> int -> API.optarg array
)
ident(
  int_ref Stdlib.Array.sub "array.mli" 117 4949 4949 "array.mli" 117 4949 4993
)
"Rust.ml" 755 29312 29341 "Rust.ml" 755 29312 29348
type(
  API.optarg array
)
ident(
  int_ref optargs "Rust.ml" 733 28579 28585 "Rust.ml" 733 28579 28592
)
"Rust.ml" 755 29312 29349 "Rust.ml" 755 29312 29350
type(
  int
)
"Rust.ml" 755 29312 29351 "Rust.ml" 755 29312 29370
type(
  int
)
ident(
  int_ref completion_cb_index "Rust.ml" 744 28947 28953 "Rust.ml" 744 28947 28972
)
"Rust.ml" 755 29312 29330 "Rust.ml" 755 29312 29371
type(
  API.optarg array
)
"Rust.ml" 755 29312 29316 "Rust.ml" 755 29312 29371
type(
  API.optarg list
)
"Rust.ml" 756 29372 29378 "Rust.ml" 756 29372 29405
type(
  API.optarg list
)
ident(
  def optargs_after_completion_cb "Rust.ml" 762 29609 29611 "Rust.ml" 805 31426 31438
)
"Rust.ml" 757 29408 29412 "Rust.ml" 757 29408 29425
type(
  API.optarg array -> API.optarg list
)
ident(
  int_ref Stdlib.Array.to_list "array.mli" 150 6222 6222 "array.mli" 150 6222 6255
)
"Rust.ml" 758 29426 29433 "Rust.ml" 758 29426 29442
type(
  API.optarg array -> int -> int -> API.optarg array
)
ident(
  int_ref Stdlib.Array.sub "array.mli" 117 4949 4949 "array.mli" 117 4949 4993
)
"Rust.ml" 758 29426 29443 "Rust.ml" 758 29426 29450
type(
  API.optarg array
)
ident(
  int_ref optargs "Rust.ml" 733 28579 28585 "Rust.ml" 733 28579 28592
)
"Rust.ml" 758 29426 29452 "Rust.ml" 758 29426 29471
type(
  int
)
ident(
  int_ref completion_cb_index "Rust.ml" 744 28947 28953 "Rust.ml" 744 28947 28972
)
"Rust.ml" 758 29426 29472 "Rust.ml" 758 29426 29473
type(
  int -> int -> int
)
ident(
  int_ref Stdlib.( + ) "stdlib.mli" 347 13626 13626 "stdlib.mli" 347 13626 13672
)
"Rust.ml" 758 29426 29474 "Rust.ml" 758 29426 29475
type(
  int
)
"Rust.ml" 758 29426 29451 "Rust.ml" 758 29426 29476
type(
  int
)
"Rust.ml" 759 29477 29487 "Rust.ml" 759 29477 29499
type(
  API.optarg array -> int
)
ident(
  int_ref Stdlib.Array.length "array.mli" 33 1475 1475 "array.mli" 33 1475 1526
)
"Rust.ml" 759 29477 29500 "Rust.ml" 759 29477 29507
type(
  API.optarg array
)
ident(
  int_ref optargs "Rust.ml" 733 28579 28585 "Rust.ml" 733 28579 28592
)
"Rust.ml" 759 29477 29487 "Rust.ml" 759 29477 29507
type(
  int
)
"Rust.ml" 759 29477 29508 "Rust.ml" 759 29477 29509
type(
  int -> int -> int
)
ident(
  int_ref Stdlib.( - ) "stdlib.mli" 352 13775 13775 "stdlib.mli" 352 13775 13821
)
"Rust.ml" 759 29477 29511 "Rust.ml" 759 29477 29530
type(
  int
)
ident(
  int_ref completion_cb_index "Rust.ml" 744 28947 28953 "Rust.ml" 744 28947 28972
)
"Rust.ml" 759 29477 29531 "Rust.ml" 759 29477 29532
type(
  int -> int -> int
)
ident(
  int_ref Stdlib.( + ) "stdlib.mli" 347 13626 13626 "stdlib.mli" 347 13626 13672
)
"Rust.ml" 759 29477 29533 "Rust.ml" 759 29477 29534
type(
  int
)
"Rust.ml" 759 29477 29510 "Rust.ml" 759 29477 29535
type(
  int
)
"Rust.ml" 759 29477 29486 "Rust.ml" 759 29477 29536
type(
  int
)
"Rust.ml" 758 29426 29432 "Rust.ml" 759 29477 29537
type(
  API.optarg array
)
"Rust.ml" 757 29408 29412 "Rust.ml" 759 29477 29537
type(
  API.optarg list
)
"Rust.ml" 762 29609 29615 "Rust.ml" 762 29609 29644
type(
  API.optarg list
)
ident(
  def optargs_without_completion_cb "Rust.ml" 765 29715 29717 "Rust.ml" 805 31426 31438
)
"Rust.ml" 763 29647 29651 "Rust.ml" 763 29647 29679
type(
  API.optarg list
)
ident(
  int_ref optargs_before_completion_cb "Rust.ml" 754 29275 29281 "Rust.ml" 754 29275 29309
)
"Rust.ml" 763 29647 29680 "Rust.ml" 763 29647 29681
type(
  API.optarg list -> API.optarg list -> API.optarg list
)
ident(
  int_ref Stdlib.( @ ) "stdlib.mli" 823 30483 30483 "stdlib.mli" 823 30483 30524
)
"Rust.ml" 763 29647 29682 "Rust.ml" 763 29647 29709
type(
  API.optarg list
)
ident(
  int_ref optargs_after_completion_cb "Rust.ml" 756 29372 29378 "Rust.ml" 756 29372 29405
)
"Rust.ml" 763 29647 29651 "Rust.ml" 763 29647 29709
type(
  API.optarg list
)
"Rust.ml" 765 29715 29717 "Rust.ml" 765 29715 29747
type(
  string -> API.call -> unit
)
ident(
  int_ref print_rust_handle_call_comment "Rust.ml" 479 18615 18623 "Rust.ml" 479 18615 18653
)
"Rust.ml" 765 29715 29748 "Rust.ml" 765 29715 29752
type(
  string
)
ident(
  int_ref name "Rust.ml" 730 28383 28435 "Rust.ml" 730 28383 28439
)
"Rust.ml" 765 29715 29753 "Rust.ml" 765 29715 29757
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 730 28383 28449 "Rust.ml" 730 28383 28453
)
"Rust.ml" 765 29715 29717 "Rust.ml" 765 29715 29757
type(
  unit
)
"Rust.ml" 766 29759 29761 "Rust.ml" 766 29759 29763
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 766 29759 29764 "Rust.ml" 766 29759 29816
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 766 29759 29817 "Rust.ml" 766 29759 29821
type(
  string
)
ident(
  int_ref name "Rust.ml" 730 28383 28435 "Rust.ml" 730 28383 28439
)
"Rust.ml" 767 29822 29827 "Rust.ml" 767 29822 29854
type(
  API.call -> string
)
ident(
  int_ref rust_async_handle_call_args "Rust.ml" 708 27536 27540 "Rust.ml" 708 27536 27567
)
"Rust.ml" 768 29855 29864 "Rust.ml" 768 29855 29868
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 730 28383 28449 "Rust.ml" 730 28383 28453
)
"Rust.ml" 768 29855 29884 "Rust.ml" 768 29855 29913
type(
  API.optarg list
)
ident(
  int_ref optargs_without_completion_cb "Rust.ml" 762 29609 29615 "Rust.ml" 762 29609 29644
)
"Rust.ml" 768 29855 29862 "Rust.ml" 768 29855 29915
type(
  API.call
)
"Rust.ml" 767 29822 29826 "Rust.ml" 768 29855 29916
type(
  string
)
"Rust.ml" 766 29759 29761 "Rust.ml" 768 29855 29916
type(
  unit
)
"Rust.ml" 769 29918 29920 "Rust.ml" 769 29918 29922
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 769 29918 29923 "Rust.ml" 769 29918 29989
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 769 29918 29920 "Rust.ml" 769 29918 29989
type(
  unit
)
"Rust.ml" 770 29991 29993 "Rust.ml" 770 29991 29995
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 770 29991 29996 "Rust.ml" 770 29991 30066
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 770 29991 29993 "Rust.ml" 770 29991 30066
type(
  unit
)
"Rust.ml" 771 30068 30070 "Rust.ml" 771 30068 30072
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 771 30068 30073 "Rust.ml" 771 30068 30136
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 771 30068 30070 "Rust.ml" 771 30068 30136
type(
  unit
)
"Rust.ml" 773 30167 30169 "Rust.ml" 773 30167 30171
type(
  (string -> unit, unit, string, unit) format4 -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 773 30167 30172 "Rust.ml" 773 30167 30236
type(
  (string -> unit, unit, string, unit) format4
)
"Rust.ml" 774 30237 30242 "Rust.ml" 774 30237 30258
type(
  API.optarg -> string
)
ident(
  int_ref rust_optarg_name "Rust.ml" 122 3625 3629 "Rust.ml" 122 3625 3645
)
"Rust.ml" 774 30237 30260 "Rust.ml" 774 30237 30269
type(
  API.optarg array -> int -> API.optarg
)
ident(
  int_ref Stdlib.Array.get "array.mli" 36 1594 1594 "array.mli" 36 1594 1650
)
"Rust.ml" 774 30237 30270 "Rust.ml" 774 30237 30277
type(
  API.optarg array
)
ident(
  int_ref optargs "Rust.ml" 733 28579 28585 "Rust.ml" 733 28579 28592
)
"Rust.ml" 774 30237 30278 "Rust.ml" 774 30237 30297
type(
  int
)
ident(
  int_ref completion_cb_index "Rust.ml" 744 28947 28953 "Rust.ml" 744 28947 28972
)
"Rust.ml" 774 30237 30259 "Rust.ml" 774 30237 30298
type(
  API.optarg
)
"Rust.ml" 774 30237 30241 "Rust.ml" 774 30237 30299
type(
  string
)
"Rust.ml" 773 30167 30169 "Rust.ml" 774 30237 30299
type(
  unit
)
"Rust.ml" 775 30301 30303 "Rust.ml" 775 30301 30305
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 775 30301 30306 "Rust.ml" 775 30301 30339
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 775 30301 30303 "Rust.ml" 775 30301 30339
type(
  unit
)
"Rust.ml" 776 30341 30343 "Rust.ml" 776 30341 30345
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 776 30341 30346 "Rust.ml" 776 30341 30357
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 776 30341 30343 "Rust.ml" 776 30341 30357
type(
  unit
)
"Rust.ml" 777 30359 30361 "Rust.ml" 777 30359 30363
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 777 30359 30364 "Rust.ml" 777 30359 30376
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 777 30359 30361 "Rust.ml" 777 30359 30376
type(
  unit
)
"Rust.ml" 779 30414 30416 "Rust.ml" 779 30414 30430
type(
  string -> string -> API.call -> unit
)
ident(
  int_ref print_ffi_call "Rust.ml" 569 22197 22201 "Rust.ml" 569 22197 22215
)
"Rust.ml" 779 30414 30431 "Rust.ml" 779 30414 30439
type(
  string
)
ident(
  int_ref aio_name "Rust.ml" 730 28383 28440 "Rust.ml" 730 28383 28448
)
"Rust.ml" 779 30414 30440 "Rust.ml" 779 30414 30465
type(
  string
)
"Rust.ml" 779 30414 30466 "Rust.ml" 779 30414 30470
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 730 28383 28449 "Rust.ml" 730 28383 28453
)
"Rust.ml" 779 30414 30416 "Rust.ml" 779 30414 30470
type(
  unit
)
"Rust.ml" 780 30472 30474 "Rust.ml" 780 30472 30476
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 780 30472 30477 "Rust.ml" 780 30472 30483
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 780 30472 30474 "Rust.ml" 780 30472 30483
type(
  unit
)
"Rust.ml" 781 30485 30487 "Rust.ml" 781 30485 30489
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 781 30485 30490 "Rust.ml" 781 30485 30528
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 781 30485 30487 "Rust.ml" 781 30485 30528
type(
  unit
)
"Rust.ml" 782 30530 30532 "Rust.ml" 782 30530 30534
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 782 30530 30535 "Rust.ml" 782 30530 30570
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 782 30530 30532 "Rust.ml" 782 30530 30570
type(
  unit
)
"Rust.ml" 783 30572 30574 "Rust.ml" 783 30572 30576
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 783 30572 30577 "Rust.ml" 783 30572 30635
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 783 30572 30574 "Rust.ml" 783 30572 30635
type(
  unit
)
"Rust.ml" 784 30637 30639 "Rust.ml" 784 30637 30641
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 784 30637 30642 "Rust.ml" 784 30637 30673
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 784 30637 30639 "Rust.ml" 784 30637 30673
type(
  unit
)
"Rust.ml" 785 30675 30677 "Rust.ml" 785 30675 30679
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 785 30675 30680 "Rust.ml" 785 30675 30730
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 785 30675 30677 "Rust.ml" 785 30675 30730
type(
  unit
)
"Rust.ml" 786 30732 30734 "Rust.ml" 786 30732 30736
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 786 30732 30737 "Rust.ml" 786 30732 30755
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 786 30732 30734 "Rust.ml" 786 30732 30755
type(
  unit
)
"Rust.ml" 787 30757 30759 "Rust.ml" 787 30757 30761
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 787 30757 30762 "Rust.ml" 787 30757 30833
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 787 30757 30759 "Rust.ml" 787 30757 30833
type(
  unit
)
"Rust.ml" 788 30835 30837 "Rust.ml" 788 30835 30839
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 788 30835 30840 "Rust.ml" 788 30835 30869
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 788 30835 30837 "Rust.ml" 788 30835 30869
type(
  unit
)
"Rust.ml" 789 30871 30873 "Rust.ml" 789 30871 30875
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 789 30871 30876 "Rust.ml" 789 30871 30898
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 789 30871 30873 "Rust.ml" 789 30871 30898
type(
  unit
)
"Rust.ml" 790 30900 30902 "Rust.ml" 790 30900 30904
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 790 30900 30905 "Rust.ml" 790 30900 30927
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 790 30900 30902 "Rust.ml" 790 30900 30927
type(
  unit
)
"Rust.ml" 791 30929 30931 "Rust.ml" 791 30929 30933
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 791 30929 30934 "Rust.ml" 791 30929 30971
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 791 30929 30931 "Rust.ml" 791 30929 30971
type(
  unit
)
"Rust.ml" 792 30973 30975 "Rust.ml" 792 30973 30977
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 792 30973 30978 "Rust.ml" 792 30973 31010
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 792 30973 30975 "Rust.ml" 792 30973 31010
type(
  unit
)
"Rust.ml" 793 31012 31014 "Rust.ml" 793 31012 31016
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 793 31012 31017 "Rust.ml" 793 31012 31041
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 793 31012 31014 "Rust.ml" 793 31012 31041
type(
  unit
)
"Rust.ml" 794 31043 31045 "Rust.ml" 794 31043 31047
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 794 31043 31048 "Rust.ml" 794 31043 31077
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 794 31043 31045 "Rust.ml" 794 31043 31077
type(
  unit
)
"Rust.ml" 795 31079 31081 "Rust.ml" 795 31079 31083
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 795 31079 31084 "Rust.ml" 795 31079 31154
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 795 31079 31081 "Rust.ml" 795 31079 31154
type(
  unit
)
"Rust.ml" 796 31156 31158 "Rust.ml" 796 31156 31160
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 796 31156 31161 "Rust.ml" 796 31156 31178
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 796 31156 31158 "Rust.ml" 796 31156 31178
type(
  unit
)
"Rust.ml" 797 31180 31182 "Rust.ml" 797 31180 31184
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 797 31180 31185 "Rust.ml" 797 31180 31200
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 797 31180 31182 "Rust.ml" 797 31180 31200
type(
  unit
)
"Rust.ml" 798 31202 31204 "Rust.ml" 798 31202 31206
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 798 31202 31207 "Rust.ml" 798 31202 31221
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 798 31202 31204 "Rust.ml" 798 31202 31221
type(
  unit
)
"Rust.ml" 799 31223 31225 "Rust.ml" 799 31223 31227
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 799 31223 31228 "Rust.ml" 799 31223 31240
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 799 31223 31225 "Rust.ml" 799 31223 31240
type(
  unit
)
"Rust.ml" 800 31242 31244 "Rust.ml" 800 31242 31246
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 800 31242 31247 "Rust.ml" 800 31242 31295
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 800 31242 31244 "Rust.ml" 800 31242 31295
type(
  unit
)
"Rust.ml" 801 31297 31299 "Rust.ml" 801 31297 31301
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 801 31297 31302 "Rust.ml" 801 31297 31316
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 801 31297 31299 "Rust.ml" 801 31297 31316
type(
  unit
)
"Rust.ml" 802 31318 31320 "Rust.ml" 802 31318 31322
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 802 31318 31323 "Rust.ml" 802 31318 31333
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 802 31318 31320 "Rust.ml" 802 31318 31333
type(
  unit
)
"Rust.ml" 803 31335 31337 "Rust.ml" 803 31335 31339
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 803 31335 31340 "Rust.ml" 803 31335 31388
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 803 31335 31337 "Rust.ml" 803 31335 31388
type(
  unit
)
"Rust.ml" 804 31390 31392 "Rust.ml" 804 31390 31394
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 804 31390 31395 "Rust.ml" 804 31390 31424
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 804 31390 31392 "Rust.ml" 804 31390 31424
type(
  unit
)
"Rust.ml" 805 31426 31428 "Rust.ml" 805 31426 31430
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 805 31426 31431 "Rust.ml" 805 31426 31438
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 805 31426 31428 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 804 31390 31392 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 803 31335 31337 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 802 31318 31320 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 801 31297 31299 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 800 31242 31244 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 799 31223 31225 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 798 31202 31204 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 797 31180 31182 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 796 31156 31158 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 795 31079 31081 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 794 31043 31045 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 793 31012 31014 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 792 30973 30975 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 791 30929 30931 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 790 30900 30902 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 789 30871 30873 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 788 30835 30837 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 787 30757 30759 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 786 30732 30734 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 785 30675 30677 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 784 30637 30639 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 783 30572 30574 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 782 30530 30532 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 781 30485 30487 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 780 30472 30474 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 779 30414 30416 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 777 30359 30361 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 776 30341 30343 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 775 30301 30303 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 773 30167 30169 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 771 30068 30070 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 770 29991 29993 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 769 29918 29920 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 766 29759 29761 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 765 29715 29717 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 762 29609 29611 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 754 29275 29277 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 744 28947 28949 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 735 28683 28685 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 733 28579 28581 "Rust.ml" 805 31426 31438
type(
  unit
)
"Rust.ml" 811 31671 31675 "Rust.ml" 811 31671 31718
type(
  string -> string -> API.call -> string * bool -> unit
)
ident(
  def print_rust_async_handle_call_changing_state "Rust.ml" 838 32740 32740 "Rust.ml" 0 0 -1
)
"Rust.ml" 811 31671 31719 "Rust.ml" 811 31671 31723
type(
  string
)
ident(
  def name "Rust.ml" 811 31671 31724 "Rust.ml" 835 32683 32695
)
"Rust.ml" 811 31671 31724 "Rust.ml" 811 31671 31732
type(
  string
)
ident(
  def aio_name "Rust.ml" 811 31671 31733 "Rust.ml" 835 32683 32695
)
"Rust.ml" 811 31671 31733 "Rust.ml" 811 31671 31737
type(
  API.call
)
ident(
  def call "Rust.ml" 812 31738 31742 "Rust.ml" 835 32683 32695
)
"Rust.ml" 812 31738 31743 "Rust.ml" 812 31738 31752
type(
  string
)
ident(
  def predicate "Rust.ml" 813 31763 31765 "Rust.ml" 835 32683 32695
)
"Rust.ml" 812 31738 31754 "Rust.ml" 812 31738 31759
type(
  bool
)
ident(
  def value "Rust.ml" 813 31763 31765 "Rust.ml" 835 32683 32695
)
"Rust.ml" 812 31738 31742 "Rust.ml" 812 31738 31760
type(
  string * bool
)
"Rust.ml" 813 31763 31769 "Rust.ml" 813 31763 31774
type(
  string
)
ident(
  def value "Rust.ml" 814 31814 31816 "Rust.ml" 835 32683 32695
)
"Rust.ml" 813 31763 31780 "Rust.ml" 813 31763 31785
type(
  bool
)
ident(
  int_ref value "Rust.ml" 812 31738 31754 "Rust.ml" 812 31738 31759
)
"Rust.ml" 813 31763 31791 "Rust.ml" 813 31763 31797
type(
  string
)
"Rust.ml" 813 31763 31803 "Rust.ml" 813 31763 31810
type(
  string
)
"Rust.ml" 813 31763 31777 "Rust.ml" 813 31763 31810
type(
  string
)
"Rust.ml" 814 31814 31816 "Rust.ml" 814 31814 31846
type(
  string -> API.call -> unit
)
ident(
  int_ref print_rust_handle_call_comment "Rust.ml" 479 18615 18623 "Rust.ml" 479 18615 18653
)
"Rust.ml" 814 31814 31847 "Rust.ml" 814 31814 31851
type(
  string
)
ident(
  int_ref name "Rust.ml" 811 31671 31719 "Rust.ml" 811 31671 31723
)
"Rust.ml" 814 31814 31852 "Rust.ml" 814 31814 31856
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 811 31671 31733 "Rust.ml" 811 31671 31737
)
"Rust.ml" 814 31814 31816 "Rust.ml" 814 31814 31856
type(
  unit
)
"Rust.ml" 815 31858 31860 "Rust.ml" 815 31858 31862
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 815 31858 31863 "Rust.ml" 815 31858 31913
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 815 31858 31914 "Rust.ml" 815 31858 31918
type(
  string
)
ident(
  int_ref name "Rust.ml" 811 31671 31719 "Rust.ml" 811 31671 31723
)
"Rust.ml" 816 31919 31924 "Rust.ml" 816 31919 31951
type(
  API.call -> string
)
ident(
  int_ref rust_async_handle_call_args "Rust.ml" 708 27536 27540 "Rust.ml" 708 27536 27567
)
"Rust.ml" 816 31919 31952 "Rust.ml" 816 31919 31956
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 811 31671 31733 "Rust.ml" 811 31671 31737
)
"Rust.ml" 816 31919 31923 "Rust.ml" 816 31919 31957
type(
  string
)
"Rust.ml" 815 31858 31860 "Rust.ml" 816 31919 31957
type(
  unit
)
"Rust.ml" 817 31959 31961 "Rust.ml" 817 31959 31963
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 817 31959 31964 "Rust.ml" 817 31959 31969
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 817 31959 31961 "Rust.ml" 817 31959 31969
type(
  unit
)
"Rust.ml" 818 31971 31973 "Rust.ml" 818 31971 31987
type(
  string -> string -> API.call -> unit
)
ident(
  int_ref print_ffi_call "Rust.ml" 569 22197 22201 "Rust.ml" 569 22197 22215
)
"Rust.ml" 818 31971 31988 "Rust.ml" 818 31971 31996
type(
  string
)
ident(
  int_ref aio_name "Rust.ml" 811 31671 31724 "Rust.ml" 811 31671 31732
)
"Rust.ml" 818 31971 31997 "Rust.ml" 818 31971 32022
type(
  string
)
"Rust.ml" 818 31971 32023 "Rust.ml" 818 31971 32027
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 811 31671 31733 "Rust.ml" 811 31671 31737
)
"Rust.ml" 818 31971 31973 "Rust.ml" 818 31971 32027
type(
  unit
)
"Rust.ml" 819 32029 32031 "Rust.ml" 819 32029 32033
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 819 32029 32034 "Rust.ml" 819 32029 32040
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 819 32029 32031 "Rust.ml" 819 32029 32040
type(
  unit
)
"Rust.ml" 820 32042 32044 "Rust.ml" 820 32042 32046
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 820 32042 32047 "Rust.ml" 820 32042 32117
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 820 32042 32044 "Rust.ml" 820 32042 32117
type(
  unit
)
"Rust.ml" 821 32119 32121 "Rust.ml" 821 32119 32123
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 821 32119 32124 "Rust.ml" 821 32119 32162
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 821 32119 32121 "Rust.ml" 821 32119 32162
type(
  unit
)
"Rust.ml" 822 32164 32166 "Rust.ml" 822 32164 32168
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 822 32164 32169 "Rust.ml" 822 32164 32204
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 822 32164 32166 "Rust.ml" 822 32164 32204
type(
  unit
)
"Rust.ml" 823 32206 32208 "Rust.ml" 823 32206 32210
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 823 32206 32211 "Rust.ml" 823 32206 32268
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 823 32206 32208 "Rust.ml" 823 32206 32268
type(
  unit
)
"Rust.ml" 824 32270 32272 "Rust.ml" 824 32270 32274
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 824 32270 32275 "Rust.ml" 824 32270 32316
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 824 32270 32272 "Rust.ml" 824 32270 32316
type(
  unit
)
"Rust.ml" 825 32318 32320 "Rust.ml" 825 32318 32322
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 825 32318 32323 "Rust.ml" 825 32318 32346
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 825 32318 32320 "Rust.ml" 825 32318 32346
type(
  unit
)
"Rust.ml" 826 32348 32350 "Rust.ml" 826 32348 32352
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 826 32348 32353 "Rust.ml" 826 32348 32371
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 826 32348 32350 "Rust.ml" 826 32348 32371
type(
  unit
)
"Rust.ml" 827 32373 32375 "Rust.ml" 827 32373 32377
type(
  (string -> string -> unit, unit, string, unit) format4 ->
  string -> string -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 827 32373 32378 "Rust.ml" 827 32373 32428
type(
  (string -> string -> unit, unit, string, unit) format4
)
"Rust.ml" 827 32373 32429 "Rust.ml" 827 32373 32438
type(
  string
)
ident(
  int_ref predicate "Rust.ml" 812 31738 31743 "Rust.ml" 812 31738 31752
)
"Rust.ml" 827 32373 32439 "Rust.ml" 827 32373 32444
type(
  string
)
ident(
  int_ref value "Rust.ml" 813 31763 31769 "Rust.ml" 813 31763 31774
)
"Rust.ml" 827 32373 32375 "Rust.ml" 827 32373 32444
type(
  unit
)
"Rust.ml" 828 32446 32448 "Rust.ml" 828 32446 32450
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 828 32446 32451 "Rust.ml" 828 32446 32478
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 828 32446 32448 "Rust.ml" 828 32446 32478
type(
  unit
)
"Rust.ml" 829 32480 32482 "Rust.ml" 829 32480 32484
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 829 32480 32485 "Rust.ml" 829 32480 32497
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 829 32480 32482 "Rust.ml" 829 32480 32497
type(
  unit
)
"Rust.ml" 830 32499 32501 "Rust.ml" 830 32499 32503
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 830 32499 32504 "Rust.ml" 830 32499 32552
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 830 32499 32501 "Rust.ml" 830 32499 32552
type(
  unit
)
"Rust.ml" 831 32554 32556 "Rust.ml" 831 32554 32558
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 831 32554 32559 "Rust.ml" 831 32554 32573
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 831 32554 32556 "Rust.ml" 831 32554 32573
type(
  unit
)
"Rust.ml" 832 32575 32577 "Rust.ml" 832 32575 32579
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 832 32575 32580 "Rust.ml" 832 32575 32590
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 832 32575 32577 "Rust.ml" 832 32575 32590
type(
  unit
)
"Rust.ml" 833 32592 32594 "Rust.ml" 833 32592 32596
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 833 32592 32597 "Rust.ml" 833 32592 32645
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 833 32592 32594 "Rust.ml" 833 32592 32645
type(
  unit
)
"Rust.ml" 834 32647 32649 "Rust.ml" 834 32647 32651
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 834 32647 32652 "Rust.ml" 834 32647 32681
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 834 32647 32649 "Rust.ml" 834 32647 32681
type(
  unit
)
"Rust.ml" 835 32683 32685 "Rust.ml" 835 32683 32687
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 835 32683 32688 "Rust.ml" 835 32683 32695
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 835 32683 32685 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 834 32647 32649 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 833 32592 32594 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 832 32575 32577 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 831 32554 32556 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 830 32499 32501 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 829 32480 32482 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 828 32446 32448 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 827 32373 32375 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 826 32348 32350 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 825 32318 32320 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 824 32270 32272 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 823 32206 32208 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 822 32164 32166 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 821 32119 32121 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 820 32042 32044 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 819 32029 32031 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 818 31971 31973 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 817 31959 31961 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 815 31858 31860 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 814 31814 31816 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 813 31763 31765 "Rust.ml" 835 32683 32695
type(
  unit
)
"Rust.ml" 838 32740 32744 "Rust.ml" 838 32740 32773
type(
  unit -> unit
)
ident(
  def print_rust_async_handle_impls "Rust.ml" 852 33286 33286 "Rust.ml" 0 0 -1
)
"Rust.ml" 838 32740 32774 "Rust.ml" 838 32740 32776
type(
  unit
)
"Rust.ml" 839 32779 32781 "Rust.ml" 839 32779 32783
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 839 32779 32784 "Rust.ml" 839 32779 32806
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 839 32779 32781 "Rust.ml" 839 32779 32806
type(
  unit
)
"Rust.ml" 840 32808 32810 "Rust.ml" 840 32808 32822
type(
  (NameMap.key -> API.call -> unit) -> API.call NameMap.t -> unit
)
ident(
  int_ref NameMap.iter "map.mli" 154 6537 6541 "map.mli" 154 6537 6586
)
"Rust.ml" 840 32808 32823 "Rust.ml" 840 32808 32850
type(
  NameMap.key -> API.call -> unit
)
ident(
  int_ref print_rust_sync_handle_call "Rust.ml" 719 27952 27956 "Rust.ml" 719 27952 27983
)
"Rust.ml" 840 32808 32851 "Rust.ml" 840 32808 32868
type(
  API.call NameMap.t
)
ident(
  int_ref sync_handle_calls "Rust.ml" 687 26575 26579 "Rust.ml" 687 26575 26596
)
"Rust.ml" 840 32808 32810 "Rust.ml" 840 32808 32868
type(
  unit
)
"Rust.ml" 841 32870 32872 "Rust.ml" 841 32870 32890
type(
  (string * API.call * API.async_kind) NameMap.t
)
ident(
  int_ref async_handle_calls "Rust.ml" 674 25905 25909 "Rust.ml" 674 25905 25927
)
"Rust.ml" 842 32891 32896 "Rust.ml" 842 32891 32908
type(
  (NameMap.key -> string * API.call * API.async_kind -> unit) ->
  (string * API.call * API.async_kind) NameMap.t -> unit
)
ident(
  int_ref NameMap.iter "map.mli" 154 6537 6541 "map.mli" 154 6537 6586
)
"Rust.ml" 842 32891 32914 "Rust.ml" 842 32891 32918
type(
  NameMap.key
)
ident(
  def name "Rust.ml" 842 32891 32919 "Rust.ml" 849 33236 33269
)
"Rust.ml" 842 32891 32920 "Rust.ml" 842 32891 32928
type(
  string
)
ident(
  def aio_name "Rust.ml" 843 32951 32960 "Rust.ml" 849 33236 33269
)
"Rust.ml" 842 32891 32930 "Rust.ml" 842 32891 32934
type(
  API.call
)
ident(
  def call "Rust.ml" 843 32951 32960 "Rust.ml" 849 33236 33269
)
"Rust.ml" 842 32891 32936 "Rust.ml" 842 32891 32946
type(
  API.async_kind
)
ident(
  def async_kind "Rust.ml" 843 32951 32960 "Rust.ml" 849 33236 33269
)
"Rust.ml" 842 32891 32919 "Rust.ml" 842 32891 32947
type(
  string * API.call * API.async_kind
)
"Rust.ml" 843 32951 32966 "Rust.ml" 843 32951 32976
type(
  API.async_kind
)
ident(
  int_ref async_kind "Rust.ml" 842 32891 32936 "Rust.ml" 842 32891 32946
)
"Rust.ml" 844 32982 32993 "Rust.ml" 844 32982 33015
type(
  API.async_kind
)
type(
  API.async_kind
)
"Rust.ml" 845 33019 33032 "Rust.ml" 845 33019 33079
type(
  NameMap.key -> string -> API.call -> unit
)
ident(
  int_ref print_rust_async_handle_call_with_completion_cb "Rust.ml" 730 28383 28387 "Rust.ml" 730 28383 28434
)
"Rust.ml" 845 33019 33080 "Rust.ml" 845 33019 33084
type(
  NameMap.key
)
ident(
  int_ref name "Rust.ml" 842 32891 32914 "Rust.ml" 842 32891 32918
)
"Rust.ml" 845 33019 33085 "Rust.ml" 845 33019 33093
type(
  string
)
ident(
  int_ref aio_name "Rust.ml" 842 32891 32920 "Rust.ml" 842 32891 32928
)
"Rust.ml" 846 33094 33109 "Rust.ml" 846 33094 33113
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 842 32891 32930 "Rust.ml" 842 32891 32934
)
"Rust.ml" 845 33019 33032 "Rust.ml" 846 33094 33113
type(
  unit
)
"Rust.ml" 847 33114 33139 "Rust.ml" 847 33114 33148
type(
  string
)
ident(
  def predicate "Rust.ml" 848 33160 33173 "Rust.ml" 849 33236 33269
)
"Rust.ml" 847 33114 33150 "Rust.ml" 847 33114 33155
type(
  bool
)
ident(
  def value "Rust.ml" 848 33160 33173 "Rust.ml" 849 33236 33269
)
"Rust.ml" 847 33114 33125 "Rust.ml" 847 33114 33156
type(
  API.async_kind
)
type(
  API.async_kind
)
"Rust.ml" 848 33160 33173 "Rust.ml" 848 33160 33216
type(
  NameMap.key -> string -> API.call -> string * bool -> unit
)
ident(
  int_ref print_rust_async_handle_call_changing_state "Rust.ml" 811 31671 31675 "Rust.ml" 811 31671 31718
)
"Rust.ml" 848 33160 33217 "Rust.ml" 848 33160 33221
type(
  NameMap.key
)
ident(
  int_ref name "Rust.ml" 842 32891 32914 "Rust.ml" 842 32891 32918
)
"Rust.ml" 848 33160 33222 "Rust.ml" 848 33160 33230
type(
  string
)
ident(
  int_ref aio_name "Rust.ml" 842 32891 32920 "Rust.ml" 842 32891 32928
)
"Rust.ml" 848 33160 33231 "Rust.ml" 848 33160 33235
type(
  API.call
)
ident(
  int_ref call "Rust.ml" 842 32891 32930 "Rust.ml" 842 32891 32934
)
"Rust.ml" 849 33236 33252 "Rust.ml" 849 33236 33261
type(
  string
)
ident(
  int_ref predicate "Rust.ml" 847 33114 33139 "Rust.ml" 847 33114 33148
)
"Rust.ml" 849 33236 33263 "Rust.ml" 849 33236 33268
type(
  bool
)
ident(
  int_ref value "Rust.ml" 847 33114 33150 "Rust.ml" 847 33114 33155
)
"Rust.ml" 849 33236 33251 "Rust.ml" 849 33236 33269
type(
  string * bool
)
"Rust.ml" 848 33160 33173 "Rust.ml" 849 33236 33269
type(
  unit
)
"Rust.ml" 843 32951 32960 "Rust.ml" 849 33236 33269
type(
  unit
)
"Rust.ml" 842 32891 32909 "Rust.ml" 849 33236 33270
type(
  NameMap.key -> string * API.call * API.async_kind -> unit
)
"Rust.ml" 842 32891 32896 "Rust.ml" 849 33236 33270
type(
  (string * API.call * API.async_kind) NameMap.t -> unit
)
"Rust.ml" 841 32870 32872 "Rust.ml" 849 33236 33270
type(
  unit
)
"Rust.ml" 850 33272 33274 "Rust.ml" 850 33272 33276
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 850 33272 33277 "Rust.ml" 850 33272 33284
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 850 33272 33274 "Rust.ml" 850 33272 33284
type(
  unit
)
"Rust.ml" 841 32870 32872 "Rust.ml" 850 33272 33284
type(
  unit
)
"Rust.ml" 840 32808 32810 "Rust.ml" 850 33272 33284
type(
  unit
)
"Rust.ml" 839 32779 32781 "Rust.ml" 850 33272 33284
type(
  unit
)
"Rust.ml" 852 33286 33290 "Rust.ml" 852 33286 33314
type(
  unit -> unit
)
ident(
  def print_rust_async_imports "Rust.ml" 866 33709 33709 "Rust.ml" 0 0 -1
)
"Rust.ml" 852 33286 33315 "Rust.ml" 852 33286 33317
type(
  unit
)
"Rust.ml" 853 33320 33322 "Rust.ml" 853 33320 33324
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 853 33320 33325 "Rust.ml" 853 33320 33354
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 853 33320 33322 "Rust.ml" 853 33320 33354
type(
  unit
)
"Rust.ml" 854 33356 33358 "Rust.ml" 854 33356 33360
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 854 33356 33361 "Rust.ml" 854 33356 33397
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 854 33356 33358 "Rust.ml" 854 33356 33397
type(
  unit
)
"Rust.ml" 855 33399 33401 "Rust.ml" 855 33399 33403
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 855 33399 33404 "Rust.ml" 855 33399 33424
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 855 33399 33401 "Rust.ml" 855 33399 33424
type(
  unit
)
"Rust.ml" 856 33426 33428 "Rust.ml" 856 33426 33430
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 856 33426 33431 "Rust.ml" 856 33426 33448
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 856 33426 33428 "Rust.ml" 856 33426 33448
type(
  unit
)
"Rust.ml" 857 33450 33452 "Rust.ml" 857 33450 33454
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 857 33450 33455 "Rust.ml" 857 33450 33484
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 857 33450 33452 "Rust.ml" 857 33450 33484
type(
  unit
)
"Rust.ml" 858 33486 33488 "Rust.ml" 858 33486 33490
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 858 33486 33491 "Rust.ml" 858 33486 33531
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 858 33486 33488 "Rust.ml" 858 33486 33531
type(
  unit
)
"Rust.ml" 859 33533 33535 "Rust.ml" 859 33533 33537
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 859 33533 33538 "Rust.ml" 859 33533 33572
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 859 33533 33535 "Rust.ml" 859 33533 33572
type(
  unit
)
"Rust.ml" 860 33574 33576 "Rust.ml" 860 33574 33578
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 860 33574 33579 "Rust.ml" 860 33574 33606
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 860 33574 33576 "Rust.ml" 860 33574 33606
type(
  unit
)
"Rust.ml" 861 33608 33610 "Rust.ml" 861 33608 33612
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 861 33608 33613 "Rust.ml" 861 33608 33630
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 861 33608 33610 "Rust.ml" 861 33608 33630
type(
  unit
)
"Rust.ml" 862 33632 33634 "Rust.ml" 862 33632 33636
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 862 33632 33637 "Rust.ml" 862 33632 33660
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 862 33632 33634 "Rust.ml" 862 33632 33660
type(
  unit
)
"Rust.ml" 863 33662 33664 "Rust.ml" 863 33662 33666
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 863 33662 33667 "Rust.ml" 863 33662 33696
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 863 33662 33664 "Rust.ml" 863 33662 33696
type(
  unit
)
"Rust.ml" 864 33698 33700 "Rust.ml" 864 33698 33702
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 864 33698 33703 "Rust.ml" 864 33698 33707
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 864 33698 33700 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 863 33662 33664 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 862 33632 33634 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 861 33608 33610 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 860 33574 33576 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 859 33533 33535 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 858 33486 33488 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 857 33450 33452 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 856 33426 33428 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 855 33399 33401 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 854 33356 33358 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 853 33320 33322 "Rust.ml" 864 33698 33707
type(
  unit
)
"Rust.ml" 866 33709 33713 "Rust.ml" 866 33709 33741
type(
  unit -> unit
)
ident(
  def generate_rust_async_bindings "Rust.ml" 870 33843 33877 "Rust.ml" 0 0 -1
)
"Rust.ml" 866 33709 33742 "Rust.ml" 866 33709 33744
type(
  unit
)
"Rust.ml" 867 33747 33749 "Rust.ml" 867 33747 33764
type(
  ?extra_sources:string list ->
  ?copyright:string -> Utils.comment_style -> unit
)
ident(
  int_ref Utils.generate_header "utils.mli" 54 1958 1958 "utils.mli" 55 1980 2054
)
"Rust.ml" 867 33747 33765 "Rust.ml" 867 33747 33771
type(
  Utils.comment_style
)
"Rust.ml" 867 33747 33783 "Rust.ml" 867 33747 33799
type(
  string
)
type(
  string option
)
"Rust.ml" 867 33747 33749 "Rust.ml" 867 33747 33799
type(
  unit
)
"Rust.ml" 868 33801 33803 "Rust.ml" 868 33801 33805
type(
  (unit, unit, string, unit) format4 -> unit
)
ident(
  int_ref Utils.pr "utils.mli" 65 2270 2270 "utils.mli" 65 2270 2317
)
"Rust.ml" 868 33801 33806 "Rust.ml" 868 33801 33810
type(
  (unit, unit, string, unit) format4
)
"Rust.ml" 868 33801 33803 "Rust.ml" 868 33801 33810
type(
  unit
)
"Rust.ml" 869 33812 33814 "Rust.ml" 869 33812 33838
type(
  unit -> unit
)
ident(
  int_ref print_rust_async_imports "Rust.ml" 852 33286 33290 "Rust.ml" 852 33286 33314
)
"Rust.ml" 869 33812 33839 "Rust.ml" 869 33812 33841
type(
  unit
)
"Rust.ml" 869 33812 33814 "Rust.ml" 869 33812 33841
type(
  unit
)
"Rust.ml" 870 33843 33845 "Rust.ml" 870 33843 33874
type(
  unit -> unit
)
ident(
  int_ref print_rust_async_handle_impls "Rust.ml" 838 32740 32744 "Rust.ml" 838 32740 32773
)
"Rust.ml" 870 33843 33875 "Rust.ml" 870 33843 33877
type(
  unit
)
"Rust.ml" 870 33843 33845 "Rust.ml" 870 33843 33877
type(
  unit
)
"Rust.ml" 869 33812 33814 "Rust.ml" 870 33843 33877
type(
  unit
)
"Rust.ml" 868 33801 33803 "Rust.ml" 870 33843 33877
type(
  unit
)
"Rust.ml" 867 33747 33749 "Rust.ml" 870 33843 33877
type(
  unit
)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 Caml1999O030 T   n         -             :          i   8           "   ?       (      c   (      5       (          8          !   
   3   !   
   	   +       8          "   
   6       8          &      c   ?       h      ]          	      }   U      \            
   C      @          I            	                  z   U   c             C   8          %          W               !   %   )   l   8   <   l   @   D   H   L   P   T   X   \   `   d   h   5       (      5       (      5       (      5       (      5       (          C   
   D   
   h   3   "   6       8          &      5       (      5       (      5       (      5       (      5       (      5       (      5       (      5       (      5       (      5       (      5       (      5       (      5       (          D   
   C   
   
   8          %      )   *          V          C   
         T      5          3   8          "   6       8          "      V         C   
   6       8          "         T      5       
   6       8          "      8          "   6       8          &          W            '   0   9   F   J   S       C   6          4   !   8          "   6       8          &          D      C         @      4   %          C   
   ?   
   4   %          C   
   ?      4   %          C   
   4   !   6       8          &      5       (          C   
   ?      4   %          C   
   ?      4   %      )   *      5          F   ^       V         F   l   
   8          "   6       8          "   6       8          "   5          G      ^       V   !   5          F   ^       V      5       8          !      G         3   "   
   6       8          !   8          &      (          6       8          "   U   
       6       8          "   V      c   (          6       8          "   V          ]       
      l      
   8          #   
   6       8          "   ?       (          6       8          "   V   *   g         ^       i   8           "   ]          ]       
      l         8          #   
   l   #      8           "   8          "   ?       (          6       8          "   V   
          6       8           '          ?       (          C   
   V         D   6          8       $   "   6       8       $   &         D   
   (             6       8          "   @       (          8       	   !   
   ]       h      ^             j      8          #         
      
            T          W                  '         '         +      6       8          &         6       8          &            T   l      6       8          &            T   i      ]          6       8          "   V   1          l         8          #   6          ^       V      5          ^       V      5          ^       V   
          6       8          '          6       8          &   
      6       8          "   U   
      6       8          "   V   
      
   6       8          '   
      6       8          &   	         6       8           '          6       8          &      )   *            +      ;6       8           !   8          #   
   6       8          "   
   	   +       8          "   
   8          !   
   	   +       8          "   
   8       
   !   
      +      d8          &   
   c   6       h   8          #   5       8          !   c      !   c      %      5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          %      )   *         E      D   
   C      V         D   
   C         @                      $                     '      5       8          !               G      "                  +         G      !   !   5       8          %      )   *         D      C      V      5       T      5                "            !      6       8          #   5       8          !      6             #   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !          6       8          #   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          %          D      C      W               C   
   C   6          ^       V         ?       (      c   (      c   (      )   *            @       (      )   *         D   8          !   
   	   +       8          "   	   +       8          "   
   V          C   
         T         6       8           "   
   h      8          #   8       
   !               O   o               8          #   8       
   !   
      8       $   "               "         
   G         G         G   
   
   G   	      G         G         G         G            G         	   F      
   E               C   >   
                   !      6       8          #   5       8          !   5       8          !   5       8          !         ^          !   6       8          "   5       8          !   5       8          !   5       8          !         6          	         #   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          %   
   )   *               "               !            !      6       8                    6                #   5       8          %          D      C         8          "         8          "   8       $   "            8          "            8          "   8       $   "   
      6       8          !   8          #   6       8          &          W                C   
   ?         !   6       8          &             %          W                                                                            %      5       (      5       (      )   *         D      C               F   '          C            E   "   X   (          C            E   "   X   (      )   *         D      C               F   '                   A             !   @       (          D      C      G   
            +      8       
   !   %          C            E   "   X   (          6       8          "   V          ]          l         8          '          6       8           &          C   
   (          D   
   G      
   (      c   6       h   8          #   5       8          !   c         !   7             8          "   5       8          !   7             8          "   7                8          "   7                8          "   7                8          "   5       8          !   7                 8          "   5       8          %      5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          %          D      C      D         8          "      C         8          "   8       $   "      D         8          "   
   C         8          "   8       $   "   
      6       8          !   8          #   6       8          "            	   "            E   "   V      5       8          !   5       8          !   T      5       8          !                  !            6       8                    6             
   #   5       8          %      )   *         D      8          "   
   C      8          "   8       
   !   8       $   "   6       8          !   5       8          !      C         8          "      D         8          "   5       8          !   5       8          !            6       8          "         6       8                 5       8          !   5       8          !            !   5       8          %          D      C      6          "            8          "   8       
   !   
         8          "   8       
   !         8          "         6       8          #      6       8          "   5       8          !      
   6       8          !   8          #   6       8          "   6       8          "      6       8          "   5       8          !   5       8          !   5       8          !            8          "       6       8          "   6       8          "   5       8          !   5       8          !      6       8          "   5       8          !   5       8          !   5       8          !   5       8          !   5       8          !   5       8          %             !      E   
   W              #   '   +   /   3   7            M   V      6       8          "   T   I   5       T   E   5       T   A   5       T   =   5       T   9   5       T   5   5       T   1   5       T   -   5       T   )   5       6       8          "   6       8          "   6       8          "   T         6       8          "   T   
      6       8          "   T               G   	   V   N      E   
      V   8       W                                   4   4   4   5       8          !   5       8          !   5       8          !   T      5       8          !   5       8          !   5       8          !   T      5       8          !             6       8          &          6       8          &                !         !         !   6       8          #      W      #               H            V   Y      D   
   V            T   P     C   
   6       8          "               T   G     C   
   W                           <                                 k            V   !      D   
   V          D   
   V            T     5       8          !         T            T           T   c         T         V   )      D   
   V          D   
   V            T         C      C         6       8          #               T            T            T   4         T         V   )      D   
   V          D   
   V            T         C      C         6       8          #               T            T            T            T            T          V          D   
   V          D   
   V            T         C   
   C         6       8          #               T            T   w         T   y      C   
   W                                    /                                    V         D   
   V            T   M   5       8          !         T   $         T   ?      V         D   
   V            T   3      C   
   6       8          "               T            T             T   "       V          D   
   V            T         C   
   6       8          "               T      5       8          !   5       8          %             !         !      W         ;      C   
   C   
   
   6       8          #      6       8          "       6       8          "   5       8          !   5       8          !   5       8          !   5       8          !   5       8          %         D   
   C   
   8          !   
         6       8          $      
          !         !      W                 :   a                          O  |                  V          D   
   V            T   
      C   
               T      5       6       @       [         6       8          '          V          D   
   V            T   
      C   
               T      5       6       @       [      
      6       8          $             V          D   
   V            T   
      C   
               T      5       6       @       [         6       8          '      5       6       @       [       V          D   
   V            T   
      C   
               T      5       6       @       [         6       8          '          V          D   
   V            T   
      C   
               T      5       6       @       [         6       8          '          V          D   
   V            T   
      C   
               T      5       6       @       [      6       8          "      6       8          "   5       8          !         6       8          '          V   6       D   
   V   /       D   
   V            T   (      C   
   C                  	      
   6       8          #      	      6       8          #      	      6       8          '            5       6       @       [       V          D   
   V            T   
      C   
               T      5       6       @       [      
   6       8          #         6       8          '          V          D   
   V            T   
      C   
               T      5       6       @       [   
   6       8          "      6       8          "   5       8          !   5       8          !   5       8          !       6       8          "       6       8          "       6       8          "          6       8          '          V   ,       D   
   V   %       D   
   V            T         C   
   C                  	      6       8          #      	      6       8          '            5       6       @       [       V   ,       D   
   V   %       D   
   V            T         C   
   C                  	      6       8          #      	      6       8          '            5       6       @       [       E   
      V   @       W                         $   (   ,   0   4   8   5       T   9   5       T   5   5       T   1   5       T   -   5       T   )   5       T   %   5       T   !   5       T      5       T      5       T      5       T      5       T   
       C   
   C   
   
   8          !                  G   	   V   	       6       8          &          (          W         1   5   9   =   b   f   j       C   
   W                                                                      5       8          %      5       (      5       (      5       (      5       (      5       (          C   
   W                                                                     5       8          %      5       (      5       (      5       (      5       (          W         2         K                C   
   h   6          8          "   @       (          D      C   h   6       
   8          "   @       6             !   8          "   @       (          D      C   h   6       
   8          "   @       6          8          "   @       (          C   h   6             !   8          "   @       (          W                C   
   C   
         T          C   
         6          8          &          W         ,   ,   ,   ,         %                     ,                         C   
         T   ,       C   
   C   
         T   #   5       6       @       [       D      C         h   6       
   8          "   @       6          8          "   @       (      h   6          8          "   @       (          W                C   
   ?         !   6       8          &          D      C         @   	      !   6       8          &          W                                  C   
   
   (          C   
   
      %          W                C   
   C   
         T          C   
         
   (          W                                                                         C   
         T          C   
   C   
         
   (          D      C            !   6       8          '          D      C   
   6       8          "      8          "   	                  !         !   6       8                       +      8          !   %          D      C   
         !   6       8          #            +      8          !   %          D      C         6       8          '          E      C   6       8          !   5       8          !   5       8          !       8          !   6       8          "      	   +       8          "   5       8          !   5       8          %          D      C         8          !   6       8          '      5       8          !   5       8          !       C   8          !   6       8          "       D   	   +       8          "   5       8          %          D      C         6       8          '      5       6       
   G      ?             8           8                 !   6          G   $   !   	   +       	   +       	   +       ]	   ,             +      ,	   +       	   +          +      	   ,          /n   +      _	   +       	   +             +      	   +       	   +                +      X         +            	      
   +      o
   +                              +      	   ,          8               
         +      l
   
      
                              !      #   +   	   	   +       
                              !   +      "8           	   +       8       (   !   !   	   +       8          !   !   6       8       $   "         G   $   !   6       6       
   G      ?             8           8                 !   	   +       8           
      #   +      8       (   !   !      +      8          !   !      C   
   +      k8          "   !   8                 $   +      R8       (   !   !         +      >8       (   !   !   
   C      +      &8          "   !         +      
         +      
                   +      
                     +      i      
            !   +                     +      :
            	               +      	   +       
      +      	             @          -   9        b  6  8  筠  , K$Rust&_none_@@ AA"??A@@@@@@@@@@@  , K	A"??Aðç@*floatarrayQ  8 @@@A@@@@@Z@@@5extension_constructorP  8 @@@A@@@@@^@@@#intA  8 @@@A@@@@@b@A@$charB  8 @@@A@@@@@f@A@&stringO  8 @@@A@@@@@j@@@%floatD  8 @@@A@@@@@n@@@$boolE  8 @@%false^@@x@$true_@@~@@@A@@@@@@A@$unitF  8 @@"()`@@@@@A@@@@@@A@
#exnG  8 @@AA@@@@@@@@%arrayH  8 @ @O@A@A@ @@@@@@@@$listI  8 	 @P@A"[]a@@@"::b@@ @Q@@@
@@A@Y@@@@@@@@&optionJ  8 % @S@A$Nonec@@@$Somed@@@@@A@Y@@@@@@@@&lazy_tN  8 ; @U@A@A@Y@@@@@@@@)nativeintK  8 @@@A@@@@@@@@%int32L  8 @@@A@@@@@@@@%int64M  8 @@@A@@@@@@@@:Undefined_recursive_module]    W@@@ @J@@ @@@ @V@@A񠰠=ocaml.warn_on_literal_patterna@.Assert_failure\    @@ @X@@A o@
0Division_by_zeroY    &@@@Aw@+End_of_fileX    .@@@A@)Sys_errorW    6@2@@A(@.Sys_blocked_io[    ?@@@A!0$$@)Not_foundV    G@@@A)8,,@'FailureU    O@K@@A2A55@0Invalid_argumentT    X@T@@A;J>>@.Stack_overflowZ    a@@@ACRFF@-Out_of_memoryS    i@@@AKZNN@-Match_failureR    q@plm@ @c@@AYh\\@
%bytesC  8 @@@A@@@@@`@@@&Stdlib&Printf#API%Utils'NameSet+Y@#eltZ  8 @@@A&String!t@@ @ H@@@@'set.mli7-M-v7-M-@@@@+Stdlib__SetqA@!t Z  8 @@@A+Stdlib__Set$Make@@ @ G@@@@ G:> G:D@@@@DA@%empty@@ @ F@# Jcg$ Jcs@@"E@(is_empty@@@ @ E$boolE@@ @ D@ @ C@7 M8 M@@6F@#mem@P@@ @ B@)@@ @ A@@ @ @@ @ ?@ @ >@O PP P@@NG@#add@@@ @ =@@@@ @ <C@@ @ ;@ @ :@ @ 9@e S9=f S9S@@dH@)singleton@.@@ @ 8T@@ @ 7@ @ 6@v Y
Z
^w Y
Z
u@@uI@&remove@?@@ @ 5@g@@ @ 4j@@ @ 3@ @ 2@ @ 1@ \

 \

@@J@%union@x@@ @ 0@}@@ @ /@@ @ .@ @ -@ @ ,@ b b @@K@%inter@@@ @ +@@@ @ *@@ @ )@ @ (@ @ '@ e e2@@L@(disjoint	@@@ @ &@@@ @ %@@ @ $@ @ #@ @ "@ hQU hQq@@M@$diff
@@@ @ !@@@ @  @@ @ @ @ @ @ @ l l@@N@'compare@@@ @ @@@ @ #intA@@ @ @ @ @ @ @ p15 p1O@@O@%equal@@@ @ @@@ @ @@ @ @ @ @ @ @ t t@@P@&subset
@@@ @ @@@ @ @@ @ @ @ @ @ @, xMQ- xMk@@+Q@$iter@@@@ @ 
$unitF@@ @ @ @ @%@@ @ 
@@ @ 	@ @ @ @ @K |L |@@JR@#map@@@@ @ @@ @ @ @ @A@@ @ D@@ @ @ @ @ @  @f g @@eS@$fold@@1@@ @ @!a @ @ @ @ @ @_@@ @ @@ @ @ @ @ @ @  @@T@'for_all@@N@@ @ b@@ @ @ @ @z@@ @ k@@ @ @ @ @ @ @ vz v@@U@&exists@@k@@ @ @@ @ @ @ @@@ @ @@ @ @ @ @ @ @    *@@V@&filter@@@@ @ @@ @ @ @ @@@ @ @@ @ @ @ @ @ @  @@W@*filter_map@@@@ @ &optionJ@@ @ @@ @ @ @ @@@ @ @@ @ @ @ @ @ @  @@X@)partition@@@@ @ @@ @ @ @ @@@ @ @@ @ ֠@@ @ @ @ @ @ @ @ @  B@@Y@(cardinal@
@@ @ 4@@ @ @ @ @0 041 0J@@/Z@(elements@@@ @ $listI@@ @ @@ @ @ @ @H I @@G[@'min_elt@4@@ @ @@ @ @ @ @Y |Z |@@X\@+min_elt_opt@E@@ @ ~)@@ @ @@ @ @ @ @o 59p 5Y@@n]@'max_elt@[@@ @ ;@@ @ @ @ @ 
 @@^@+max_elt_opt@l@@ @ P@@ @ @@ @ @ @ @ { {@@_@&choose@@@ @ b@@ @ @ @ @  0@@`@*choose_opt@@@ @ ̠w@@ @ @@ @ @ @ @   @@a@%split@@@ @ @@@ @ @@ @ @@ @ @@ @ @ @ @ @ @ @ @     !@@b@$find@@@ @ @@@ @ @@ @ @ @ @ @ @ "" ""@@c@(find_opt @@@ @ @@@ @ @@ @ @@ @ @ @ @ @ @ #[#_ #[#@@d@*find_first!@@@@ @ @@ @ @ @ @@@ @ @@ @ @ @ @ @ @, $.$2- $.$[@@+e@.find_first_opt"@@@@ @ @@ @ @ @ @#@@ @ \@@ @ @@ @ @ @ @ @ @M&6&:N&6&n@@Lf@)find_last#@@@@ @ ,@@ @ @ @ @D@@ @ $@@ @ @ @ @ @ @i
']'aj
']'@@hg@-find_last_opt$@@4@@ @ H@@ @ @ @ @`@@ @ D@@ @ @@ @ @ @ @ @ @(k(o(k(@@h@'of_list%@WW@@ @ @@ @ ~@@ @ @ @ @))))@@i@+to_seq_from&@i@@ @ @@@ @ &Stdlib#Seq!t{@@ @ @@ @ ~@ @ }@ @ |@ ** **@@j@&to_seq'@@@ @ {#Seq!t@@ @ z@@ @ y@ @ x@%+a+e%+a+@@k@*to_rev_seq(@@@ @ w5#Seq!t@@ @ v@@ @ u@ @ t@)++)++@@l@'add_seq)@K#Seq!t@@ @ s@@ @ r@@@ @ q@@ @ p@ @ o@ @ n@-,@,D-,@,e@@m@&of_seq*@i#Seq!t@@ @ m@@ @ l@@ @ k@ @ j@*1,,+1,,@@)n@@@'Rust.ml[[@@3hidden_handle_calls,K!t@@ @ -@``@@A3print_rust_constant@&stringO@@ @ o[@ 4#intA@@ @ Ê[@ 5@ @ 6[@ 1$unitF@@ @ B[@ 2@ @ 3[@ 0@7d158d1H@@B/print_rust_enum@#API$enum@@ @ ;[@ å@@ @ D[@ æ@ @ ç[@ ä@QgRg@@E0print_rust_flags@%flags@@ @ v[@ q4@@ @ .[@ r@ @ s[@ p@hqiq@@I3to_upper_snake_case@&stringO@@ @ j[@ \@@ @ ʢ[@ ]@ @ ^[@ Z@}EM}E`@@1N'explode@@@ @ [@ _$listI$charB@@ @ ʒ\@ {@@ @ z[@ `@ @ a[@ [@ J		 J		@@SO8print_metadata_namespace$@@@@ @ 6[@ $listIS@@ @ <\@ ˕c@@ @ ^@ U@@ @ ̱^@ V@ @ W^@ P@@ @ O\@ ˖@ @ ˗\@ ː@@ @ ˏ[@ 
@ @ [@ 	$unitF@@ @ ˎ[@ 
@ @ [@ @ S
f
j S
f
@@Y-rust_arg_name0@<#arg@@ @ @@@ @ @ @ @ amq am~@@a0rust_optarg_nameG@N&optarg@@ @ ͳR@@ @ Ͳ@ @ ͱ@ z)- z)=@@c/rust_cbarg_nameK@`%cbarg@@ @ d@@ @ @ @ @! ~" ~@@e-rust_arg_typeU@v#arg@@ @ l[@ y|@@ @ Д[@ z@ @ {[@ j@9 : @@h2rust_closure_traitV(lifetimeBH@@ @ [@ @@ @ [@ @@ @ [@ }@%cbarg@@ @ u[@ 4@@ @ 3[@ ~&stringO@@ @ m[@ ΀@ @ ΁@ @ ΂[@ b@q r @@!i/rust_cbarg_typeW@	@@ @ )[@ 2@ @ 5[@ s@ `d `s@@2j0rust_optarg_typem@&optarg@@ @ m@@ @ l@ @ k@ '+ ';@@D}-ffi_arg_namesr@#arg@@ @ Ҋ@@ @ ҉@@ @ ҈@ @ ҇@   @@[ A/ffi_optarg_name@&optarg@@ @ Ӣ @@ @ ӡ@ @ Ӡ@  $@@m E/ffi_cbarg_names@%cbarg@@ @ @@ @ @@ @ @ @ @  @@ G/ffi_cbarg_types@%%cbarg@@ @ -@@ @ @@ @ @ @ @  @@ N-rust_ret_type@$call@@ @ ְ[@ F@@ @ 
[@ @ @ [@ @      @@ O/rust_arg_to_ffi@s@@ @ [@ @@ @ [@ 	@ @ 
[@ @#$#$@@ S2rust_optarg_to_ffi@q@@ @ [@ @@ @ [@ @ @ [@ @-Z22".Z224@@ s2ffi_cbargs_to_rust@@@ @ [@ @@ @ [@ @ @ [@ @Bq55Cq55@@ z/ffi_ret_to_rust@W@@ @ |[@ #@@ @ [@ @ @ [@ @W;;X;;@@ <print_rust_closure_to_raw_fn@ 'closure@@ @ [@ :@@ @ [@ @ @ [@ @nCCoCC@@ >print_rust_handle_call_comment@[@@ @ [@ @@@ @ [@ @@ @ [@ @ @ @ @ [@ @HHHH@@; 4longdesc_to_markdown@[@ @&stringO@@ @ [@ @@ @ [@ @@ @ [@ @ @ @ @ [@ @JJJJ@@\ .print_ffi_call
@@@ @ >[@ @@@ @ V[@ @@@ @ [@ @@ @ [@ @ @ [@ @ @ [@ @ @ [@ @9VV9VV@@ 8print_rust_handle_method@(!@@ @  %[@ 7@@ @ U[@ 8@ @ 9[@ 4@@ @ d[@ 5@ @ 6[@ 3@NYYNYY@@ 2print_rust_imports@0@@ @ [@ @@ @ [@ @ @ [@ @d\\d\] @@ 6generate_rust_bindings@@@ @ &[@ #@@ @ p[@ $@ @ %[@ "@ s^^!s^^@@ 5excluded_handle_callsj!t@@ @ @-aa.aa@@ 'NameMap[@#key^\  8 @@@A&String!t@@ @ =@@@@'map.mlig78g78%@@@@+Stdlib__MapoA@!t_\  8 !a @ !@A@A+Stdlib__Map$Make@@ @ <I@B@@@ F;? F;J@@@@DA@%empty`"!a @  @@ @ ;@0 I1 I@@/E@(is_emptya@!a @ @@ @ :$boolE@@ @ 9@ @ 8@I LJ L@@HF@#memb@b@@ @ 7@3!a @ @@ @ 6@@ @ 5@ @ 4@ @ 3@f Og O$@@eG@#addc@@@ @ 2@!a @ @U	@@ @ 1Y
@@ @ 0@ @ /@ @ .@ @ -@ S S@@H@&updated@;@@ @ ,@@&optionJ!a @ @@ @ +	@@ @ *@ @ )@@@ @ (@@ @ '@ @ &@ @ %@ @ $@ \dh \d@@I@)singletone@g@@ @ #@!a @ @@ @ "@ @ !@ @  @ i i9@@J@&removef@@@ @ @!a @ 
@@ @ @@ @ @ @ @ @ @ o o@@K@%mergeg@@@@ @ @`!a @ 
@@ @ @k!b @ 
@@ @ t!c @ 
@@ @ @ @ @ @ @ @ @@@ @ @@@ @ @@ @ @ @ @ @ @ @ @# v$ xb@@"L@%unionh@@@@ @ 
@!a @ 
@
@@ @ @ @ @ @ 
@ @ 	@@@ @ @!@@ @ %@@ @ @ @ @ @ @ @ @P 48Q 4y@@OM@'comparei@@!a @ 
@#intA@@ @ @ @ @ @  @D@@ @ @J@@ @ @@ @ @ @ @ @ @ @ @y z @@xN@%equalj@@!a @ 
@I@@ @ @ @ @ @ @k@@ @ @q@@ @ Y@@ @ @ @ @ @ @ @ @ X\ X@@O@$iterk@@Y@@ @ @!a @ 
$unitF@@ @ @ @ @ @ @@@ @ @@ @ @ @ @ @ @  @@P@$foldl@@@@ @ @!a @ 
@!b @ 
@ @ @ @ @ @ @@@ @ @@ @ @ @ @ @ @  	@@Q@'for_allm@@@@ @ @!a @ 
@@ @ @ @ @ @ @ߠ
@@ @ @@ @ @ @ @ @ @  
@@
R@&existsn@@@@ @ @!a @ 
@@ @ @ @ @ @ @
@@ @ @@ @ @ @ @ @ @2 3 @@1S@&filtero@@@@ @ @!a @ 
@@ @ @ @ @ @ @'
@@ @ +@@ @ @ @ @ @ @V @DW @s@@UT@*filter_mapp@@@@ @ @!a @ 
֠!b @ 
@@ @ @ @ @ @ @P@@ @ T@@ @ @ @ @ @ @  @@~U@)partitionq@@8@@ @ @!a @ 
R@@ @ @ @ @ @ @t
@@ @ {@@ @ @@ @ @ @ @ @ @ @ @ !! !!@@V@(cardinalr@!a @ 
@@ @ [@@ @ @ @ @ "" "#
@@W@(bindingss@!a @ 
@@ @ $listI@@ @ @ @ @@ @ @ @ @ #]#a #]#@@X@+min_bindingt@Ǡ!a @ 
z@@ @ @@ @ @ @ @ @ @ $$ $$@@Y@/min_binding_optu@!a @ 
u@@ @ z@@ @ @ @ @@ @ @ @ @ %t%x %t%@@Z@+max_bindingv@ !a @ 
o@@ @ @@ @ @ @ @ @ @6 &a&e7 &a&@@5[@/max_binding_optw@!a @ 
j@@ @ @@ @ @ @ @@ @ @ @ @U ''V ''C@@T\@&choosex@9!a @ 
d@@ @ @@ @ @ @ @ @ @o ''p ''@@n]@*choose_opty@S!a @ 
_@@ @ 5@@ @ @ @ @@ @ @ @ @((((@@^@%splitz@E@@ @ @w!a @ 
V@@ @ @@ @ @@ @ @@ @ @ @ @ @ @ @ @)))*@@_@$find{@o@@ @ @!a @ 
O@@ @ @ @ @ @ @++++@@`@(find_opt|@@@ @ @!a @ 
J@@ @ R	@@ @ @ @ @ @ @,0,4,0,Z@@a@*find_first}@@@@ @ @@ @ @ @ @ܠ!a @ 
B@@ @ @@ @ ~@ @ }@ @ |@ @ {@ ,, ,-/@@b@.find_first_opt~@@@@ @ z@@ @ y@ @ x@!a @ 
9@@ @ w@@ @ v@ @ u@@ @ t@ @ s@ @ r@<-//=-//X@@;c@)find_last@@@@ @ q	@@ @ p@ @ o@+!a @ 
/@@ @ n	@@ @ m@ @ l@ @ k@ @ j@a40P0Tb40P0@@`d@-find_last_opt@@@@ @ i.@@ @ h@ @ g@P!a @ 
&@@ @ f2@@ @ e@ @ d@@ @ c@ @ b@ @ a@;1o1s;1o1@@e@#map@@!a @ 
!b @ 
@ @ `@{
@@ @ _
@@ @ ^@ @ ]@ @ \@C22C22@@f@$mapi@@c@@ @ [@!a @ 
!b @ 
@ @ Z@ @ Y@
@@ @ X
@@ @ W@ @ V@ @ U@J44J44B@@g@&to_seq@!a @ 
@@ @ T&Stdlib#Seq!t@@ @ S@ @ R@@ @ Q@ @ P@P44P45@@h@*to_rev_seq@נ!a @ 
	@@ @ O%#Seq!t@@ @ N@ @ M@@ @ L@ @ K@T5t5xT5t5@@i@+to_seq_from@@@ @ J@!a @ 
@@ @ IL#Seq!t@@ @ H@ @ G@@ @ F@ @ E@ @ D@<X55=X56-@@;j@'add_seq@f#Seq!t@@ @ C!a @ @ @ B@@ @ A@5
@@ @ @9@@ @ ?@ @ >@ @ =@d]66e]66@@ck@&of_seq@#Seq!t%@@ @ <!a @ @ @ ;@@ @ :[@@ @ 9@ @ 8@a7H7La7H7q@@l@@@c^c^c^c@| )strip_aio@@@ @ ]@ ?%@@ @ F]@ @@ @ A]@ >@cccc@@ 2async_handle_calls!t9@@ @ Ѡ
?$call@@ @ Ҡ
E*async_kind@@ @ @ @ @@ @ @	e1e5	e1eG@@  1sync_handle_calls!t
X$call@@ @ Z@@ @ Y@	gg	gg@@ ʠ3rust_async_arg_type@
g#arg@@ @ k@@ @ @ @ ~@	(ibif	)ibiy@@ Р6rust_async_optarg_type @
y&optarg@@ @ }@@ @ @ @ @	:jj	;jj@@ Ҡ;rust_async_handle_call_args#@O@@ @ ]@ @@ @ ]@ @ @ ]@ @	Pkk	Qkk@@  ՠ;print_rust_sync_handle_call*@	=@@ @ ]@ g@n@@ @ ]@ m	:@@ @ "]@ n@ @ o]@ h@ @ i]@ f@	nm0m4	om0mO@@ ڠ	/print_rust_async_handle_call_with_completion_cb.@	[@@ @ p]@ Q@	d@@ @ !~]@ W@@@ @ !|]@ ]	a@@ @ &m]@ ^@ @ _]@ X@ @ Y]@ R@ @ S]@ P@	nn	no@@E ݠ	+print_rust_async_handle_call_changing_statew@	@@ @ ']@ &@	@@ @ 's]@ &@@@ @ 'q]@ &@	@@ @ )D]@ &@@ @ &]@ &@ @ &]@ &	@@ @ *]@ &@ @ &]@ &@ @ &]@ &@ @ &]@ &@ @ &]@ &@	+{{	+{{@@ =print_rust_async_handle_impls@@@ @ +
]@ +
	@@ @ +]@ +@ @ +]@ +	@	F	F  @@ 8print_rust_async_imports@@@ @ ,!]@ ,	@@ @ .P]@ ,@ @ , ]@ ,@	T    
	T    "@@ <generate_rust_async_bindings@@@ @ .]@ .~	@@ @ .]@ .@ @ .]@ .}@
b    
b    @@ @a@@A[A@@9c@@A`@@BC	G@@P@@AdR@@OS@@ABDW@@~Q@@AX@@2m@@A#_@@BC
.B@@[@@A\@@BD	H@@j@@Ai@@Bik@@Wl@@AY@@
2C@@ABCEF

D@@	E@@AZ@@w]@@AV^@@h@@ABC	cI@@NU@@A	1L@@?e@@Ag@@0f@@ABCD	JK@@N@@A	%M@@B	bJ@@KV@@AO@@BzT@@b@@Afd@@
F@@ABCDEG@@m@  , K
qb    
rf  3  UAA	!Rust.generate_rust_async_bindingsA@@@  , K#
wT    #
x`    AA=Rust.print_rust_async_importsA@"!@@  , Kt)
}F  
~R    AA	"Rust.print_rust_async_handle_implsA@('@@  , KD/
+{{
CAA	0Rust.print_rust_async_handle_call_changing_stateA@.-@@  , K$5
no
%zzAA	4Rust.print_rust_async_handle_call_with_completion_cbA@43@@  , J;
m0mP
n(n1AA	 Rust.print_rust_sync_handle_callA@:9@@  , JA
kk
llAA	 Rust.rust_async_handle_call_argsA@@?@@  , JG
jj
kk@A;Rust.rust_async_optarg_typeA@FE@@  , JM
ibi
ii@A8Rust.rust_async_arg_typeA@LK@@  , JS
gg
hh@~]@ _@@ @ ^6Rust.sync_handle_callsAM\@@AB@@AB}|CDEzyw@u@u@ABCrqo@BDhgcb^@]@AZ@BCDEF@@c@  , Jv
hh#@@
@@]@ ^@ ~*@@]@ a^@ @]@ ^@ u@@]@ t
]@ @@]@ ^@ s@]@ r<B;d@  , Jp
hh
hh@A<Rust.sync_handle_calls.(fun)A@@@  , JXQ
hRh@.]@ JAIc@  , JT hRhW	@@
J6_@ @@^@ @^@ YAXd@  , JDhRhc@AA@@@  , J0lhhQ@^@ eAdc@  , J,ǰhh	@@`@ @@_@ @_@ rAqd@  , J԰(hh@A5A@@@  , Iذ,eseu-frf@GH]@ @@ @ 7Rust.async_handle_callsA&$@!@AB CEF@@b@  , IBfrfw@@xw@@]@ W^@ Hw@@]@ ]@ i@@]@ h@@]@ @]@ ^@ I@]@ J^@ ?@@]@ >]@ U@@]@ V^@ =@]@ <9B	8c@  , I tfrfufrf@A=Rust.async_handle_calls.(fun)A@@@  , I&Nzf5fq@8]@ GA'Fb@  , I.ee	@@
5_@ 4_@ @^@ _@ @@^@ @^@ ]A-=\c@  , IDee@A#A@A@@@  , IHpee@^@ iA9Ihb@  , IPee	@@"`@ @@_@ @_@ wAGWvc@  , I^ee@A=A@[Z@@  , Ipbccd3dtAA.Rust.strip_aioA@a`@@  , I4hc^cyc^c@A,Rust.NameMapA@gf@@  , Inbbcc8@[@ :Rust.excluded_handle_callsA^q@@ABCEutpok@f@ACDEF@@_@  , Hbb#@t@@[@ @@[@ [@ Bw_@  , Hbb#@$listI\@ @@\@ \@ +A*_@  , Hcccc7@@
^@ 
@@]@ ]@ @]@ ^@ @@]@ $@]@ DAC`@  , Hcc @A	 Rust.excluded_handle_calls.(fun)A@@@  , Hbbbc@]@ RAQ_@  , Hɰbb	@@&_@ 	@@^@ 
@^@ `A_`@  , Hװ+bb@AA@@@  , H۰/s^^0`m`yAA;Rust.generate_rust_bindingsA@@@  , HX5d\]6q^^AA7Rust.print_rust_importsA@@@  , HH;NYY<b\\AA=Rust.print_rust_handle_methodA@@@  , GA9VVBIXXAA3Rust.print_ffi_callA@@@  , GGCCHHmHvAA	!Rust.print_rust_closure_to_raw_fnA@@@  , GM;;NBBAA4Rust.ffi_ret_to_rustA@@@  , G|Sq55T::AA7Rust.ffi_cbargs_to_rustA@@@  , G\YZ225Zk44AA7Rust.rust_optarg_to_ffiA@@@  , GD_#$`W11AA4Rust.rust_arg_to_ffiA@
	@@  , G,e   f	"j"AA2Rust.rust_ret_typeA@@@  , Gk l  W j@A4Rust.ffi_cbarg_typesA@@@  , Gq r @A4Rust.ffi_cbarg_namesA@@@  , F#w :x C@A4Rust.ffi_optarg_nameA@"!@@  , F)} 8~ @A2Rust.ffi_arg_namesA@('@@  , F/ 'Q @A5Rust.rust_optarg_typeA@.-@@  , F5 ~ P@A4Rust.rust_cbarg_nameA@43@@  , F; z)S {\@A5Rust.rust_optarg_nameA@:9@@  , FA am w

@A2Rust.rust_arg_nameA@@?@@  , F|G S
f
 ^DAA=Rust.print_metadata_namespaceA@FE@@  , FTMqzAA5Rust.print_rust_flagsA@LK@@  , FDSgnAA4Rust.print_rust_enumA@RQ@@  , F4Yd1IeYAA8Rust.print_rust_constantA@XW@@  , F$_ab/@[@ /8Rust.hidden_handle_callsA1b@@A@@A@  , Ek[[@A,Rust.NameSetA@ji@@  , EqeY[@@AAd11@$name@d1Jd1N@@C%value@d1Pd1U@@D@C@@A%paramA@@B@@AB@@CA  , E;A8@@@A@@A  , Elk+-mz@@@[@ ǳJBogQ@$enum@Vg@@F@	A@@A@@A@  , E\
l7;
l7y@A:Rust.print_rust_enum.(fun)A@@@  , ED
j
j)@@@[@ hBA@  , E,
j
@@@\@ F]@ \sA)A@  , E̰
 i
!i@@@[@ }A3(A@  , Dְ
*h
+h@@@[@ òA=2A@  , D
@@@@5A@  , D
7l7c
8l7t@
@@]@ ^@ /8AN$name&stringO@@\@ 0\@ Ǻ@
Nl7A
Ol7E@@G#num
.@@\@ \@ ǻ@
Zl7G
[l7J@@
H@C@@AB@@A@@AB@@D@  , D
hl7O
il7x@@cA*
CA  , DjAg@z@
@A@@A  , D 
ty
uy	@
G@@[@ אA
)
q@+flag_prefix&stringO@@ @ w@
q
q@@;J%flags$listI@@ @ #intA@@ @ Ȁ@ @ ~@@ @ }@
q
q@@WKR@-C@@A!B@@A@@AB@@C@  , Dla
v
x@@@[@ sBAdC@  , D\k
w
w@A;Rust.print_rust_flags.(fun)A@ji@@  , DHq
udf
ud@
@@[@ "(BQt"C@  , D0{
ud
@
@@\@ R]@ h3A\-C@  , D
t#%
t#b@
@@[@ =Af7C@  , D
s

s
!@
@@[@ ȾGApAC@  , C
r
r@
@@[@ ȌQAzKC@  , C
V@@UA}NCA  , C\AY@@N@A@@A  , Cww@@CA$name
@@\@ ɻ\@ z@ww@@L%value
@@\@ \@ {@ww@@Mư@C@@ADA@@B@@AB@@CA  , ClAi@Ұ@
@A@@A  , Cܰ0 V

@@
z
P@[@ ˍA
: S
f
f@"ns&
@? S
f
@ S
f
@@Z%ctxts'
@F S
f
G S
f
@@[@B@@AC@@q/A@@AB@
B@@A@D@  , CxV V

@A	#Rust.print_metadata_namespace.(fun)A@ @@  , C`[ T

\ T

@.@@[@ ĐC-
C@  , CHe T

f T

@K@@\@ N]@ |АA9%D@  , C<@@A<(CA  , C("A@>@(@A&@A  , C '{ ]| ^C@@

@@\@ ˒]@ N@]@ M/AU$ctxt(
@ V

 V
@@>\&consts)
@ V
 V

@@E]!s*
3@@ @ ˡ^@ ˝@ W W@@R^M@B@@A C@@.A@@D@@ABC@vC@@HB@@AB@E@  , Cb ];@A`A@_^@@  , Bf X3< [@@@]@ ˹iD:iD@  , Bp Ymx Ym@@@^@ _@ 5uAFu(I@  , B| Z Z@@@^@ _@ ;AR4H@  , B"`@@AU7DA  , B W  W/@AB\?=@<@AB8@C  , B W%
@
@@^@ ˢ_@ ˩BkC@  , B W{@@AoCA  , BxA@@R@AN@A  , B\ ^) ^@@@@_@ ̖`@ A!n+:@ ] ]@@_!i,;@ ] ]@@`°@B@@AC@@B-A@@AB@B@@A@D@  , BPӰ' ^
( ^B@@ACA  , B<xA@հ@@A
@A  , B4߰3 w

@@A!n1@@ @ ͕p@ @? b@ b@@b@B@@AhFA@@B@@BA  , AA@@@A@@A  , AR {\@@AӠ!nH@@ @ ]@ @^ {\t_ {\u@@d	@B@@AJA@@B@@BA  , A@A@@@A@@A  , A4q P~@@A#argR6#arg@@ @ >]@ 8@ Pc Pf@@/g	'
+@CB@@ATA@@B@B@@A@CB  , A? HN HO@@
A!nL@@ @ .a@ @  @@Qf
	&M@CB@@A"@B @C  , @\'A$@/W@'@A%@A#  , @a 2@@@\@ *]@ @7AC$nameoi@@ @ ь@  @@v%flagspo@@ @ э@  @@ @{@B@@AC@@qA@@AB@B@@A@C@  , @  @A]A@@@  , @ b@@aA)CB  , @ Z Z@@@\@ ]@ nAy!xn
@@ @ т@ Zg Zh@@~@(@B@@AB(@B@  , @x Z Z@AA@@@  , @p Zl @@A
B&  , @PA@@8@A6@A+  , @H  &@AA@@@  , @@ư  $@g@@[@ Җ\@ TB!ns@@ @ 
j@ ҥ@. AJ/ AK@@ Bٰ@B@@AWA@@B@@C@  , @$%@ABC  , @> ? @AA@@@  , @C D @)\@ eȐBѠ"n1@@ @ =`@ @V ';W '=@@ C"n2@@ @ >`@ @c '?d 'A@@ D	#	$
@E"[C@@A	D\B@@?@AB@@F@  , ?#w 9AAA@ @@  , ?'{ @`\@ sB73&)F@  , ?0F@A;7*-EL  , ?5 @r@@[@ ҕ[@ ҝB;@`@A@@A@  , ?D@A?A^  , >GA@BAa  , >J C{'@@&A&$nameL@@ @ ]@ ӻ@ C[ C_@@Y FT@B@@AA@@B@@BA  , >c@A=@<^@@A@@A  , >h K@AJA@ed@@  , >|l  @
@@[@ \@ ԥVBR#argU@@ @ @@  @@ M}@B@@AA@@B@B@@A@C@  , >l  @z@@\@ ԧ]@ ԬuAD@  , >X0@xA!BD  , >D 
$ 
@@AA@@@  , >< 
& 
1@5\@ aB"n1c@@ @ 1@ 
 
@@ I"n2@@ @ 2@ 
 
@@ J@C@@AB@@>@AB<@D@  , > ư 
3*AAA@@@  , >ʰ 
>@]\@ oB(D@  , =5@A*C9  , =԰( Aa) A@AA@@@  , =ٰ- Ac. A}@m\@ ԀB#arg@@ @ 9@; AT< AW@@ K#len@@ @ :@F AYG A\@@ L@C@@AB@@v@ABt@D@  , =%R At@r@@\@ Ԃ]@ ԇA(E@  , =	] A5AAA@@@  , =
a A@\@ ԔB3
D@  , =@@A5C|  , =tk l 	@AA@@@  , =lp q @\@ PB!n@@ @ (`@ @  @@1 H
	"-@CnB@@A@B@D@  , =P;$@A7
C  , =?"A@:@@A@A  , =D GY Gb@@-A"B@A@@A@@AK  , <O  +@@8A-MA  , <U cu c@@>A3SA
  , <[  @@DA9Y@'*match*|B@@A@B@@B  , <g   P@@OADdB  , <@l ,= ,F@@UAJj(A$  , <0r  @@[APp.A*  , < x  @@aAVv4A0  , <~  @@gA\|@#vB@@A=@B@@B;  , <   7@@rAgBA  , ; OU @@xAmBG  , ;P~A{@pNAJ  , ;D	"j"@@Ay   @$call@   @@ P)core_type@@ @ a\@ @      @@ Q@A@@B@@AB@@B@  , ;$
	"j"	"j"@@A"
B@  , ;	"j"l@@A&B@  , ; °"M"U"M"d@A.$name@@ @ X^@ M@%""#&""'@@ R	!Ѱ@xC{~B@@A*@ED@@AB@@E@  , :#@AE@  , :<!"=!"@@AP@@A:@B@@B@  , :D!!E!!@@AXB@  , :I!!J!!@@A]
B@  , :N!!O!!@@AbB@  , :S!!T!!@@AgB@  , :xX !q!Y !q!@@AlB@  , :h	] ![!k^ ![!p@@Aq!B@  , :Xb !D!Rc !D!Z@@Av&B@  , :Hg !/!<h !/!C@@A{+B@  , :8l !!*m !!.@@A0B@  , :(q  !r  !@@A5B@  , :"v   w   @@A :B@  , 9'{   @@@$@w@A@@A@  , 9-L/x/L/x/@@@ @ ]@ @@ @ ]@ @ @ 1B!##:@#arg@?#$@@M T)rust_name@@ @ \@ @$$$$'@@Y U)ffi_names@@ @ @@ @ \@ @$?$E$?$N@@i Vd@&A@@AC@@#B@@AB@.C@@B@@AB@C@  , 9vI@hA6q
C@  , 9xxN//N/0@@@\@ #qCD,ffi_buf_nameS@K/Q/[K/Q/g@@ k,ffi_len_nameT@K/Q/iK/Q/u@@ l	
	@7E:D@@A1@KI@@AJH@@BC:@:@A!xG@@!yF@@ABD@@K@  , 9\:O00I@@A4$0#)"K@  , 9HL/x/
L/x/@@A}l@@ @ @L/x/L/x/@@ mt@@ @ @L/x/L/x/@@ nȰ9d@Bc)C`@G@  , 8Ұ&K/Q/W!@@AkC@  , 8ְ*F.[.+F.[.@@@ @  ]@ Ԡ@@ @ ]@ @ @ ڐBC@  , 8@AC@  , 8AH..BH..@@@\@ C,ffi_buf_name@PE.4.>QE.4.J@@  g,ffi_len_name @WE.4.LXE.4.X@@ h	
	@ED@@A@KI@@AJH@@BC@@A!xG@@!yF@@ABD@K@  , 8':{I./*@@A4$0#)&"K@  , 8t-F.[.F.[.@@"A@@ @ @F.[.zF.[.{@@: i@@ @ @F.[.}F.[.~@@B j=9@B)C@G@  , 8GE.4.:!@@;A	DC@  , 7KB--B--@r@@\@ -DB(ffi_name@@ @ V]@ 9@2* *
2* *@@` e[@@D@@ABC@D@  , 7g?--
@-N-^@@@\@ `BjD@  , 7q>,,>,-@@@\@ ޑjB&tD@  , 7{9++9++@@@\@ _tA0~#D@  , 78+f+l8+f+@@@\@ -~A:-D@  , 7t7+8+>7+8+d@@@\@ AD7D@  , 7\6++6++6@@@\@ ݷBNAD@  , 7@5**5*+@@@\@ iBXKD@  , 7(
C-.@@A\OD@  , 7 2* *<2* *H@\BvMC@  , 7@AxOC@  , 62* *32* *4@@A~!xo@@ @ F@2* *,2* *-@@ fð@kD@@Ab@Ba@`@E@@ABCa@E@  , 6Ӱ'2* *'@@AlC@  , 6װ+'((,)(f(@@@\@ 
АC(ffi_name@@ @ ]@ @<&''=&''@@ a@@D@@ABC@D@  , 6tG*((@@A	D@  , 6lK&''L&'(
@BC@  , 6T@AC@  , 6< T&''U&''@@AĠ!x@@ @ @^&''_&''@@ b	@D@@A@B@@E@@ABC@E@  , 6 m&'''@@
AC@  , 5q &&r &&@@@ @ ْ]@ f@@ @ ٓ]@ g@ @ i!B+C@  , 52@$A-C@  , 54#'9'?#'9'v@[@@\@ -C -ffi_addr_name@&~&&~&@@G ],ffi_len_name @&~&&~&@@N ^	
	 K@ED@@A@KI@@AJH@@BC@@A!xG@@!yF@@ABD@K@  , 5n"&&"&'7@@@\@ ٧gC:*6)/s(K@  , 5pz$'x'@@nA@0</5y.K@  , 5\ && &&@@uAE4@@ @ v@ && &&@@ _#<@@ @ |@ && &&@@ `E,@B+5C(@G@  , 5&~&!@@A\3C@  , 4/))/))@@@\@ ܥAg(ffi_nameZ@@ @ ]@ @,((,((@@ c@J@D@@ABKJCH@D@  , 4.);)A.);)@@@\@ WBD@  , 4İ-))-))9@@@\@ 	B&D@  , 4ΰ
"0))@@A*D@  , 4Ұ&,()',()@*ȐBnC@  , 4t@ApC@  , 4\۰/,((0,((@@A!x@@ @ @9,((:,((@@ d@D@@A@B@@E@@ABC@E@  , 4 H,(('@@AC@  , 4 L&2&8M&2&e@@A(ffi_name@@ @ ]@ @X%%Y%%@@ [@@D@@ABC@D@  , 3c%&"d%&.@	BC@  , 3@	AC@  , 3l%&m%&@@	
Aܠ!x@@ @ @v%&w%&@@& \!@D@@A@B@@E@@ABC@E@  , 31%%9@@	%A.C@  , 3l5R00R00@@	*A(ffi_name@@ @ ]@ @Q0V0`Q0V0h@@E o@@@D@@ABC@D@  , 3dLQ0V0Q0V0@	BBLC@  , 3LS@	EANC@  , 34UQ0V0Q0V0@@	JA!x
@@ @ @Q0V0Q0V0@@c p^@D@@A@B@@E@@ABC@E@  , 2nQ0V0\9@@	bA0kC@  , 2rW11	g@	gB6q
C@  , 2x@	jA8sC@  , 2z%%%%@@	oA>(ffi_name1@@ @ ^]@ A@%U%_%U%g@@ Y@!@D@@AB"!C@D@  , 2%U%%U%@	BV-C@  , 2@	AX/C@  , 2%U%%U%@@	A^!xO@@ @ N@%U%%U%@@ Z@KD@@AB@BA@@@E@@ABCA@E@  , 2H%U%[9@@	AuLC@  , 2 U181>V11@@	A{(ffi_namen@@ @ ]@ @T00T00@@ q°@^@D@@AB_^C\@D@  , 2ΰ"T01(#T014@	ĐBjC@  , 2 @	AlC@  , 1װ+T01,T01 @@	A!x@@ @ @5T016T01@@ r@D@@A@B~@}@E@@ABC~@E@  , 1DT009@@	AC@  , 1H%% I%%F@@	A(ffi_name@@ @ ]@ ׯ@T$$U$$@@ W@@D@@ABC@D@  , 1_$%
`$%@
BC@  , 1l@
A
C@  , 1Th$%i$%@@
	Aؠ!x@@ @ ׼@r$$s$$@@" X@D@@A@B@@E@@ABC@E@  , 1-$$9@@
!A*C@  , 01$f$h
&@@
%A.CA  , 07$?$Q$?$b@A
,A6@@@AB@B  , 0A$?$A
6@@
5A>BA  , 0G$$*$$;@A
<A	F@@A@A
  , 0P$$
E@@
D@MA@  , 0xTj4T4Z
O@@
NA:Z22
X@#arg@
]Z228@@e t)rust_name@@ @ \@ @[2;2A[2;2J@@q u(ffi_name@@ @ \@ @\2e2k\2e2s@@} v+flag_prefix	O@@ @ @h34h34@@ x*flags_type	@@ @ ]@ @i4#4-i4#47@@ y@7D@@A<A@@B+C@@"E@@AF@@=B@@ABC@IC@@B@@AB@FA  , 0ti4#4:i4#4P@A
AW@@A@BC@E  , 0d	i4#4)
@@
A`	E@  , 04
f33f33@@@\@ 
Aj&cbname@@ @ @^22^22@@ wǰ@oD@@A8@E@@AB9@4@AC3@E@  , 0װ+e33,e33@@@\@ [
֐AE@  , 05d336d33@@@\@ )
A(E@  , /?c3~3@c3~3@@@\@ 
A2'E@  , /Ib3G3MJb3G3|@@@\@ 
B<1E@  , /S`22Ta343E@&@@\@ [
BF;E@  , /	]_22^_22@0@@\@ CPEE@  , /
gg33@@
ATIE@  , /\k]22@@A@@AHBz@CA  , /X t\2e2vu\2e2@AA@@@AB@B  , /P*~\2e2g%@@$A'BA  , /L0[2;2M[2;2a@A+A/@@A@A
  , /@9[2;2=4@@3@6A@  , /$=::>@@=A!dq55D@%cbargd@Iq55@@K {)ffi_names٠@@ @ @@ @ \@ @r55r55@@[ |V@A@@B@@AB@D@@AB@@EC@@AB@B@  , /$h:::o:@@@[@ zmA1kB@  , /r
@pA3mB@  , .tw66w66@vB;(ffi_name@@ @ b@w66w66@@ ~@&C@@A,@D@@A-@BC,@D@  , .@A
D@  , .h959\959~@(BW(ffi_name@@ @ 1@959N959V@@ @BDEC@@AK@E@@AL@BCK@E@  , .P@A
E@  , -999:@GAu@VD@A]\BZ@D@  , -
@A}D@  , -y7!7'z7d7x@VC,ffi_buf_nameM@@ @ @x67 x67
@@ ,ffi_len_nameW@@ @ @)x67*x67@@ ԰@{D~C@@A@F@@AE@@@ABC@F@  , ,*@A%F@  , ,@>|77?|77@C,ffi_arr_namey@@ @ @K{7y7L{7y7@@ ,ffi_len_name@@ @ @U{7y7V{7y7@@  @EDC@@A@"G@@AF@@@ABC@G@  , ,$-@A(G@  , +m~8D8Jn88@C,ffi_arr_name@@ @ @z}78${}780@@* ,ffi_len_name@@ @ @}782}78>@@4 /@ED/@A@ G@@AF@@@ABC@G@  , +hD+@BA&?G@  , *F889"94@HAF@EDF@AB@E@  , *V@TAQE@  , )Xv66v66@ZB(ffi_name@@ @ C@u6H6}u6H6@@h }c@
C@@A@D@@A@BC@D@  , )r@pAm
D@  , )tts55s56%@@@[@ yC=w!B@  , )\~s55s56
@@@\@ ]@ AI-C@  , )Ps56@@@\@ ]@ 
AT8B@  , )H!@@AW;BA  , )Dr55r55@AA^@C@A@@A
  , )4r55@@@eA@  , )BB@@A;;@$call@;;@@ (ret_type@@ @ \@ @;;;;@@ )pure_expr@@ @ )\@ @;;;;@@ ɰ@"A@@AC@@B@@AB@<B@@A@C@  , (ٰ-AA.AB@@A3C@  , (ް2AA3AA@@@[@ &A=@D@@A@BC@D@  , (@AED@  , (DALATEALA\@]@ AND@  , (MAANAAJ@ @@]@ 
AXD@  , (W@@X@A@*@@]@ X
Ab%D@  , (

@@
Ae	(D@  , (|d@@e@@@2
Al/D@  , (dk@c@kl@c@@>@@]@ 
"Av9D@  , (L!u@B@Jv@B@a@H@@]@ 
,A$CD@  , (4+
@@
0A'FD@  , '.??AB@@
5A,cC@  , '3??
:@@
9A0gC@  , '7>m>u>m>@t
?B+flag_prefix@@ @ @>M>\>M>g@@G B@C@@A{@y@ABx@C@  , 'O@
SAJC@  , 'Q?h?p??@
YBQC@  , '|X@
\ASC@  , 'tZ==>>L@
bBZC@  , '\a==@O@@]@ =^@ E
mBe#C@  , 'Dl>>@Z@@^@ F_@ N
xBp.C@  , '$w@
{Ar0C@  , 'y<<<<@@
Aw5C@  , '~<=<=0@@
A|:C@  , &<~<<~<@@
A?C@  , &<C<Q<C<}@@
ADC@  , &=1=>=1=P@@
AIC@  , &<0<><0<B@@
ANC@  , &=Q=h=Q=@@
ASC@  , &<<!<</@@
AXC@  , &>>>>@
B_C@  , &@
AaC@  , &8;;
@@
A@bB@BA  , &4;;;;@A
A@@A@A
  , &(;;
@@
@A@  , &HaHcHaHk@@@[@ m
АAƐ#CC
@&cbname
@@ @ @+CC,CC@@ &cbargs%cbarg@@ @ @@ @ @<CC=CC@@ -closure_trait@@ @ \@ @HCCICC@@ 0ffi_cbargs_names@@ @ \@ @@ @ \@ @[DD
\DD@@  0ffi_cbargs_types@@ @ \@ @@ @ \@ @mDODUnDODe@@  1rust_cbargs_names_@@ @ \@ @@ @ \@ @DDDD@@ 0  +@ZB@@AeC@@LD@@ABAE@@1F@@A
A@@#G@@ABC@D@@AE@@jF@@AB@@aC@@ABC@G@  , % LHQHSHQH_@s@@[@ ;]A O$G@  , % VHHHHO@}@@[@ 	gA Y.G@  , % `GGGH@@@[@ qA c8G@  , % jGGGG@@@[@ {A mBG@  , % tGGGG@@@[@ WB wLG@  , %x ~GGGIGGG@@@[@ %A VG@  , %` G7G9G7GE@@@[@ A `G@  , %H FFFG5@@@[@ B jG@  , %0 FG
@@@\@ ]@ B uG@  , % FFFF@@@[@ B G@  , $ FFFF@@@[@ TA G@  , $ F`FbF`F@@@[@ "̐A G@  , $ ŰFPFRFPF^@@@[@ ֐A G@  , $ ϰ#F&F($F&FN@@@[@ B G@  , $ ٰ-EeEg.EF$@ @@[@ B G@  , $| 7EE
@@@\@ ]@ ,B% G@  , $d BEECEF#@$listI@@]@ .@@]@ -]@ 7C8 G@  , $T!UEEVEF @@?@@^@ p^@ <@F@@^@ ^@ :^@ 8@^@ >@^@ =^@ n!AQ!I@  , $4!nEYE[oEYEc@A@@[@ +A[!G@  , $!$xE3E5yE3EW@K@@[@ e5Be!'G@  , $ !.DDE E1@U@@[@ ?Co!1G@  , #!8
D@@CAr!4	GA  , #!=DDDD@AJBy!<
@BC@F  , #!GDDT@@SA!DFA  , #!MDODhDOD@AZA!L @@ABC@E  , #!XDODu@R@@\@ @@\@ \@ qB!cE@  , #!jDODQw@@vA!gEA  , #!pDDDDK@A}A!oCA@A@A<@BC8@D  , #!{DD*@#"@@\@ @@\@ \@ B!D@  , #t!DD@@A!DA  , #p!CCCD @AB!db@\@ABX@C  , #`!CC@@A!CA  , #L!A@!@g@Ac@A  , #0!HXXHXX@@@[@ A!V9VV@$nameV@
9VV@@! &handle
S@9VV9VV@@! $callQ@9VV9VV@@! .ffi_args_names9@@ @ \@ @@ @ \@ @-:VV.:VV@@! !ذ@A@@D@@AB(B@@0C@@AC@B@@AC@@F@@AB;D@@(E@@AC@D@  , # !FGXXGGXX@@@[@ 	AL!D@  , #!PFXXQFXX@#@@[@ AV!'D@  , ""ZDX$X&[EXkX@-@@[@ D`"	1D@  , ""dEXkXo
@I@@\@ n]@ (Bk"<G@  , ""oCWWpCWX"@B@@[@ 2Au"FD@  , ""%yBWWzBWW@L@@[@ <A"(PD@  , "x"/AWWAWW@@@[@ FB"2ZD@  , "X"9@WW@WW@@@[@ wPB"<dD@  , "8"C?WcWe?WcW@j@@[@ HZA"FnD@  , " "M>WWWY>WWWa@t@@[@ dA"PxD@  , ""W
i@@hA"S{DA  , ""\;VV<W&WQ@AoB"[@@AB}@C  , !"f
;VW%@ՠ@@\@ \@ A"lD@  , !"s;VW@]@ @@]@ @@]@ ]@ B"~#D@  , !"<W&W,)@@@\@ \@ B"/C@  , !":VV@@@"3C@  , !"a\\a\\@@@[@ TC"NYY@$name@NYYNYY@@" $call@NYYNYY@@" /rust_args_names@@ @ V\@ E@@ @ D\@ ?@OYYOYY@@" /rust_args_types@@ @ \@ u@@ @ t\@ @@(QZBZH)QZBZW@@" )rust_args@@ @ \@ @4TZZ5TZZ@@" "߰@<B@@ADC@@B_A@@F@@A<D@@,E@@ABC@!B@@AGC@@J@@ABI@@bD@@AC-F@@TE@@AG@@iH@@ABD@F@  , !l#Z`\p\r[`\p\@-@@[@  #Dq#	*F@  , !D#d`\p\
@I@@\@ 2]@ I.A|#5I@  , !,#3@@2A#8F@  , !,#r_\^\es_\^\n@G@@[@  j\@  =A##DF@  , !#*@@A#%FF@  , !#,^\H\L^\H\\@FA#,MF@  ,  #3]\+\/]\+\F@Z@@\@  9PA#6WF@  ,  #=Z[o[^\H\]@@VA#;\F@  ,  #BZ[o[tZ[o[@@@\@  1\@  #aB#GhF@  ,  #NX[ ["X[ [J@@@[@  kB#QrF@  ,  #X
p@@oA#TuFA  ,  #]UZZVZ[@AvB#\|z@{@AvuBCs@E  ,  #hVZZ@yF@@\@ @@\@ \@ C#pE@  ,  #wVZZVZZ@@@@]@ ]@ @@@]@  ]@ ]@ @]@ @]@ ]@ A#-G@  ,  h#TZZ@@A#1EA  ,  d#RZZZ^RZZZ@AB#@@@ABC@D  ,  T#RZZZ~@;@@\@ w\@ }B#E@  ,  4#RZZZ@@@\@ v\@ ̐B#D@  ,  #
PYYPYZA@ӐB#@@AB@C@  ,  #ð
PYZ@]@@\@ G\@ MB-#D@  , #ϰ#PYZ@>@@\@ F\@ `B9#C@  , #۰/OYY@@A=#CA  , #A@?#ܰ@@A@A  , #:p^^;p^^@
@@\@ 	A#IDd\\@#@iA@@A@@A@  , #Lo^g^iMo^g^@@@\@ A#A@  , h$Vn^O^QWn^O^e@)@@\@ `%A$A@  , P$`m^-^/am^-^M@3@@\@ ./A&$"A@  , 8$jl^^kl^^+@=@@\@ 9A0$,A@  ,  $ tk]]uk]^@G@@\@ CA:$#6A@  , $*~j]]j]]@Q@@\@ MAD$-@A@  , $4i]]i]]@[@@\@ fWAN$7JA@  , $>h]w]yh]w]@e@@\@ 4aAX$ATA@  , $Hg]L]Ng]L]u@o@@\@ kAb$K^A@  , $Rf](]*f](]J@y@@\@ uAl$UhA@  , $\e]]e]]&@@@\@ Av$_rA@  , x$f
@@@y$buA@  , \$i~`:`<~`:`k@@@\@ SB$Ys^^@$p@A@@A@*E@@AwF@@B@@AC@@BCD@@G@@H@@ABD@A@  , 8$}`"`$}`"`8@@@\@ $A $A@  ,  $|__|_` @@@\@ B*$&A@  , ${__{__@@@\@ ƐB4$0A@  , $z__z__@@@\@ АB>$:A@  , $y_b_dy_b_@$@@\@ ڐBH$DA@  , $x_W_Yx_W_`@@@\@ AR$NA@  , |$Űw_,_.w_,_U@8@@\@ |B\$XA@  , \$ϰ#v__$v__*@@@\@ rAf$bA@  , L$ٰ-u__
.u__@ @@\@ DAp$lA@  , 4$7t^^8t^_@
@@\@ .
C{$wA@  , $@@@~$zA@  , $EbcFbc@@7A$ݠ+modifies_fd!$boolE@@ @ @RbbSbb@@% $@
B@@AC@@~"A@@AB@@CA  , %8AR@$%
@@A@@A  , %hcc2icc6@@ZA% $namek@occ&pcc*@@% %@B@@A A@@B@@BA  , %)nAl@%%$@@A@@A  , %.d3d:@@A%cc@$name@cc@@%; %6@	A@@A@@A@  , %@dddd2@@A%>A@  , %Ecccc@@@]@ R]@ KB%JA@  , h%Qcc@@@#%NA@  , \%Ueeee@$boolE@@a@ b@ >B%N!n``@ @eeee@@%l %g@
B@@AA@@B@$B@@AC@@B@B@  , L%xee#@@WA%uBA  , @%~ A[@%i%y@@A@A  , 8%fff5fp@@&optionJa@ @@`@ _@ @@_@ _@ @`@ xA%$namef@eeee@@% Ơ$callj@eeee@@% %@B@@AC@@'A@@AB@:B@@A@D@  , (% ff"5@AA@%%@@  , % ee9@@A"%CA  , %~A@%%@@A@A  , %ǰ f5fE f5fo@AA@%%@@  , %̰  f5fF !f5fT@]@ A8*async_kindH@ +ff' ,ff1@@% %ְ@
A@@A@<D@@ADC@@hB@@AB@B@  , % :f5fV ;f5fn@AA@%%@@  , %$@@%A@  , % Afrf Bfrf@@A%ޠ!m@ Jfrf Kfrf@@% à!k@ Qfrf Rfrf@@& Ġ!v
@ Xfrf Yfrf@@& &@D@@AB@@BA@@C@@AC@7B@@A@DA  , &A@&&@@A
@B	@B  , |& rhh+ shhP@@@a@ #b@ (B&!n@@^@ *`@ @ hh hh@@&5 &0@B@@AA@@B@$B@@AoC@@B@B@  , l&A hh'#@@A&>BA  , `&GsA@&3&B@@A@A  , T&L hRhv hRh@@@`@ a@ B&C!n_@ @ hRhi hRhj@@&` &[@
B@@AA@@B@B@@AC@@B@B@  , D&l hRhr @@A&iBA  , 8&rA@&^&m@@A@A  ,  &w hh hh@@A&i!m@ hh hh@@& ˠ!k@ hh hh@@& ̠!v@ hh hh@@& &@D@@AB@@B
A@@C@@AC@B@@A@DA  , &A@&&@@A
@B	@B  , & ii ii@@[A&&@!xA@@A@B@@A@AC  , &!
ii!ii@@iA&&A  , &!iio@@nA&%\@@ @ @!ii!ii@@& &A  , p&~A{@&& A  , `&ΰ!"kk
@@A&!x"%p@@ @ @!,kk!-kk	@@& &װ@A@@A@C@@B@@AB@AB  , D&!;jj!<jk@!!@@^@ (_@ >A&!x!@@ @ @!Ljj!Mjj@@& &@
B"@A!@B@  , <'!Vjj!Wjk@AA@' &@@  , 4'![jj @@A'
B&  , 'A@&'0A)  , '!cll@ @@]@ @@]@ ]@ אC'6!vkk@$args%@@ @ @@ @ @!kk!kk@@'3 ֠'optargs&!J&optarg@@ @ @@ @ @!kk!kk@@'D נ/rust_args_names'z @@ @ ^@ @@ @ ^@ @!kk!kk@@'V ؠ/rust_args_types(@@ @ ^@ @@ @ ^@ @!l)l/!l)l>@@'h 'c@HC@@A:B@@)A@@A.D@@E@@ABC@ B@@AD@@BE@@ C@@AC@E@  , '~!ll!ll@@!@@^@ :^@ @!@@^@ R^@ }^@ @^@ @^@ ^@ 8PAy'-G@  , '!llV@@UA}'1EA  , '!lAlE!lgl@A\B'97@5@4@ABC1@D  , '!lAlf@BR@@^@ ^@ mB'E@  , '"lglm@#^@@^@ ^@ yB'D@  , '"kk"kl(@{B'][@Y@ABT@C@  , p'ʰ
"kl@d@@^@ ^@ B'D@  , X'ְ"*kl@E@@^@ ^@ B'C@  , D'"6kk@@A'CA  , 0'A@'@{@Av@A  , '"Amm"Bmn&@"@@]@ C'"Mm0m0@$name,@"Rm0mT@@( ۠$call-@"Xm0mU"Ym0mY@@( (@
A@@B@@AB@D@@AC@@)E@@ zB@@ABC@B@  , ("kmm"lmm@">@@]@ D*(B@  , (!"umm"vmm@"[@@^@ _@ A6(&#F@  , (-"mm@"f@@^@ _@ AA(1.E@  , (8"m\m^"m\m@ 	@@]@ wBK(;8B@  , (B
@@@N(>;B@  , |(E"$zz"$zz@"l@@]@ &<A(H8"nn#@$name08@("no@@(` ޠ(aio_name15@"no"no @@(g ߠ$call23@"no!"no%@@(n 'optargs3%arrayHA@@ @ ^@ @@ @ ^@ c@"oo"oo@@( 3completion_cb_indexk#intA@@ @ =^@ @@ @ ^@ @"pp"pp$@@( 3completion_cb_indexr@@ @ m^@ S@"qq"qq,@@( <optargs_before_completion_cbt$listIx@@ @ ^@ @@ @ ^@ @#
r[ra#r[r}@@( ;optargs_after_completion_cbu@@ @ ^@ @@ @ ^@ @#rr#rr@@( =optargs_without_completion_cbv@@ @ &^@  @@ @ ^@ @#.ss#/ss@@( (ٰ@B@@A}A@@MFeE@@ABC@@~D@@A3H@@JG@@%I@@ABCD@ D@@A C@@
E@@"LB@@ABC@I@  , d(#O#zgzi#P#zgz@#"@@]@ &
ʐA(%I@  , L)#Y"zVzX#Z"zVze@#,@@]@ %ԐA)/I@  , 4)#c!zAzC#d!zAzT@#6@@]@ %ސA)9I@  , )#m z
z#n z
z?@#@@@]@ %tA)CI@  , )##wyy#xyz@#J@@]@ %BA)&MI@  , )-#yy#yy@#T@@]@ %A)0WI@  , )7#yy#yy@#^@@]@ $A):aI@  , )A#yy#yy@#h@@]@ $A)DkI@  , )K#ygyi#ygy@#r@@]@ $zA)NuI@  , )U#yCyE#yCye@#|@@]@ $H$A)XI@  , t)_#y$y&#y$yA@#@@]@ $.A)bI@  , \)i#xx#xy"@#@@]@ #8A$)lI@  , D)s#xx#xx@#@@]@ #BA.)vI@  , ,)}#xx#xx@#@@]@ #LA8)I@  , )#xx#xx@#@@]@ #NVAB)I@  , )#xsxu#xsx@#@@]@ #`AL)I@  , )#x%x'#x%xq@#@@]@ "jAV)I@  , )#xx#xx#@#@@]@ "tA`)I@  , )$ww$wx
@#@@]@ "~Aj)I@  , )$
ww$ww@#@@]@ "TAt)I@  , )ð$wlwn$wlw@#@@]@ ""A~)I@  , l)Ͱ$!wBwD$"wBwj@#@@]@ !A)I@  , T)װ$+
ww$,
ww@@#@@]@ !A)I@  , <)$5ww
$6ww@$@@]@ !A)I@  , $)$?vv$@vw@$@@]@ !{C)I@  ,  )$I	vv$J	vv@$@@]@ !KĐA)I@  , )$Svv$Tvv@$&@@]@ !ΐA*)I@  , *	$]v]v_$^v]v@$0@@]@  ؐA*3I@  , *$guu$hvv[@$:@@]@  B*=I@  , *$qvv!
@$V@@^@  _@  A*!HI@  , *($|vv3$}vvZ@#|@@_@  `@  B*-TI@  , *4$utuv$utu@$[@@]@  VA*7^I@  , p*>$u'u)$u'ur@$e@@]@  $
A*AhI@  , X*H$tt$tu%@$o@@]@ A*KrI@  , @*R$t?tA$ tt@$y@@]@ =!C
*U|I@  , $*\$t~t
@$@@^@ _@ ,A*`I@  , *g$ tt$ tt@A2A@*e*d@@  , `*l$tt$tt=@"=@@]@ /;B'*oI@  , T*v
@@@?A**rIA  , L*{$ss$st
@AFB1*z@@ABC@H  , 8*$ssQ@@PA:*	HA  , 4*$rr$s%sa@AWA@*@@@ABC@G  , $*$rr@)@@^@ ^@ iCR*G@  , *$rr$rr@pAY*@@ABC@F@  , *%rr@@@^@ ^@ Ci*F@  , *%r[r]@@Am*F@  , *%qrqz%rCrU@%Bs*@@ABC@E@  , *@Ay*E@  , *̰% qRqb%!qRqc@@A!xsE@@ @ _@%*qRq]%+qRq^@@* *հB@@F@@ABC@F@  , *%6qq@@A* EA  , |*%<p'p+%=pq
@AB*
@CBC@D  , l*%Fp:p@%Gpp@A	:Rust.print_rust_async_handle_call_with_completion_cb.(fun)A@**@@  , \*%Lpp@%arrayH|^@ @@^@ ^@ @^@ ^@ @@^@ ^@ 7ؐB+%D@  , L+%gpp%hpq@A!A@++@@  , <+%lpp
@@A+.DA  , 8+%roo%soo@AA+CA@=@AB4@C  ,  +(%|oo@@@+%C@  , +,%pp%pq@A:A@+*+)@@  , +1@<@!xp@%pp%pp@@+: !yq3_@ :@%pp%pp@@+C +>@B@@AA@@B@@B@  , +J%pp%pp@@XA!ilJ@%p:pF%p:pG@@+V &optargmO@%p:pI%p:pO@@+] +X@C@@AB@@oA@@AB@@C@  , +g%pp%pp@@uA&cbnamen@@ @ @%pnp%pnp@@+u +p@	D@@AE@@@ABC@@E@  , +%pp%pp@AA@+}+|@@  , +@A+E@  , +%pp%pp@@@`@  `@ B&+E@  , +%pp+@@A*+E@  , +%pTp\L@@AK+;CA  , t+A@J+@;@A@@A  , X+%B%B@%@@]@ *vA+j&+{{@$nameyj@&
+{{@@+ (aio_namezg@&+{{&+{{@@+ $call{e@&+{{&+{{@@+ )predicate|^@&,{{&,{|@@+ %value}_@&%,{|
&&,{|@@+ %value~*@@ @ &^@ &@&1-||&2-||@@+ +ܰ@-C@@A'B@@6D@@AB^A@@'F@@AG#E@@BC@#C@@A#B@@
D@@AB@G@  , @+&MAPR&NAP@& @@]@ *tΐAX+ G@  , (,&W@?A&X@?N@&*@@]@ *BؐAb,*G@  , ,
&a?*,&b?*=@&4@@]@ *Al,4G@  , ,&k>~~&l>~(@&>@@]@ )Av,>G@  , ,!&u=~~&v=~~@&H@@]@ )A,$HG@  , ,+&<~~&<~~@&R@@]@ )z A,.RG@  , ,5&;~u~w&;~u~@&\@@]@ )
C,8\G@  , ,?&:~\~^&:~\~s@&f@@]@ (A,BfG@  , x,I&9~>~@&9~>~Z@&p@@]@ (A,LpG@  , `,S&8~~&8~~<@&z@@]@ ({(A,VzG@  , H,]&7}}&7}~@&@@]@ (I2A,`G@  , 0,g&6}}&6}}@&@@]@ (<A,jG@  , ,q&5}w}y&5}w}@&@@]@ 'FA,tG@  ,  ,{&4}*},&4}*}u@&@@]@ 'PA,~G@  , ,&3}}&3}}(@&@@]@ 'ZA,G@  , ,&2||&2|}@&@@]@ 'pdC,G@  , ,&1||&1||@&@@]@ '@nA,G@  , ,&/|r|t&0||@&@@]@ &xC,G@  , ,'0||
@&@@^@ '_@ '3A
,G@  , t,'.|F|H'
.|F|p@$@@]@ &B,G@  , h,°
@@A,G@  , \,Ű'-||;'-||B@@A,ð@BC@F@  , L,Ͱ'!-||/'"-||5@@A&,F@  , D,Ұ'&-||@@A*,FA  , 0,A@),Ӱ@BC@D  , ,ް'2I  f  h'3Q    @"2@@^@ +yA,e'<F@,@aA@@A@$B@@AaC@@G@@ABF@@E@@GD@@ABC@A@  , ,'PJ  {  @@l'?@@_@ +`@ +%m@@_@ +`@ +''*async_kind@@_@ +`@ +@_@ +`@ +{@@_@ +z;@_@ +xA8-4B@  , - 'tJ  {  B@A	(Rust.print_rust_async_handle_impls.(fun)A@--@@  , -%'yH  (  *'zH  (  d@"y@@^@ +F BG-(CA@  , -/'G    
'G    &@'V@@^@ +
AQ-2MA@  , -9
@@@T-5PA@  , -<'M    'N  F  Y@@A]$name@@_@ +L@'J  {  'J  {  @@-M (aio_nameG@'J  {  'J  {  @@-T $callH@'J  {  'J  {  @@-[ *async_kindI@'J  {  'J  {  @@-b -]@E@@A
C@@D@@AB(B@@A@@AC@+C@@TB@@AB@E@  , h-t'Q    'Q    @AUA@-r-q@@  , \-y'P    @@YA>)predicateO@@ @ +@'O  Z  s'O  Z  |@@- %value@@ @ +@'O  Z  ~'O  Z  @@- -1+@+@AG@@F@@ABC,@G@  , @-'K    (@@|A_-<EA  , $-A@-@;@A9@B7@B  , -'_  ~  '_  ~  @'@@^@ .A-(T    @-@+A@@A@@A@  , -(^  `  b(^  `  |@'@@^@ -A-A@  , -İ(]  H  J(]  H  ^@'@@^@ -A-A@  , -ΰ("\  &  ((#\  &  F@'@@^@ -A&-"A@  , -ذ(,[    (-[    $@'@@^@ -WA0-,A@  , -(6Z    (7Z    @(	@@^@ -%ÐA:-6A@  , l-(@Y    (AY    @(@@^@ ,͐AD-@A@  , T-(JX    (KX    @(@@^@ ,אAN-JA@  , <. (TW  w  y(UW  w  @('@@^@ ,AX.TA@  , $.
(^V  L  N(_V  L  u@(1@@^@ ,]Ab.
^A@  , .(hU  (  *(iU  (  J@(;@@^@ ,+Al.hA@  , 
.
@@@o.kA@  , 
.!(ue    (ve    1@(H@@^@ .A.~(b    @.(@A@@A@B@@AC@@B@A@  , 
.7(d  	  (d  	  @(^@@^@ .A.:A@  , 
.A(c    (c    @	^@@^@ .(C .DA@  , 
.K
-@@,@#.GA@  , 
.N(RDRQ(3UU@A?Rust.longdesc_to_markdown.(fun)A@.M.L@@  , 
|.T(RDRF(3UU@@9Rust.longdesc_to_markdownA.D$name&!@(JJ(JJ@@.g (longdesc&%[@ @(JJ(JJ@@.o 'content&-@@ @ \@ @(K	K(K	K@@.| %lines(A@@ @ @@ @ \@ @(PZP`(PZPe@@. %linesq$boolE@@ @ \@ @@ @ \@ @ @ \@ @@ @ \@ @(PP) PP@@. %lines..L@@ @ .(.]@@ @ @@ @ 
@ @ @@ @ 
@)Q&Q-)Q&Q2@@. %lines
-@@ @ D^@ <@@ @ ;\@ $@@ @ #\@ @)4QdQj)5QdQo@@. %lines.@@ @ z\@ t@@ @ s\@ p@)FQR)GQR	@@. .@C@@H2GQFtED@@ABA@@B@@AC@@&@@@& @@ABHA  , 
x/)cQR)dQR@AA/@@@ABC@G  , 
h/)nQR @@A/	GA  , 
d/ )tQrQv)uQQ@A̐B/@.@)@AB$#C@!F  , 
T/+)QrQ)QQ@AA@/)/(@@  , 
D/0)QdQf@@A/-FA  , 
@/6)Q&QR)Q&Q`@AA/5@D@=@AB:9C@7E  , 
0/A)Q&Q(@@A/>	EA  , 
,/G)PP)PQ"@AB/F@U@L@ABKJC@HD  , 
/R)PP)PQ@AA@/P/O@@  , 
/W)PP@@A/TDA  , 
/])PZPh)PZP{@A	B/\@k@A`_B@]C  , /g)PZP\@@A/dCA  , /m)KK)PP@AC/l@onB@lB
  , /v)KK3)KKQ@#Str&regexp@@\@ ]@ -A'/D@  , /)KRKX)PP@A9A@//@@  , /)K	K8@@7@0/B@  , /)L~L)L~L@@BA:!s'V@@\@ \@ @)KRK])KRK^@@/ $expr'c@@ @ ^@ @*KbKn*KbKr@@/ #len#intA@@ @ ^@ @*KK*KK@@/ !c)~@@ @ ^@ @*KK*KK@@/ 'content)@@ @ ^@ @*+KK*,KK@@/ /ְ@D@@AE@@>B@@AB2C@@NA@@AC@B@@A@E@  , `/*>	OuO*?
OP@@AZ/E@  , @/*CO=OJ*DO=Oe@@A`#lenA@@ @ ]^@ Z@*OLL*PLL@@/ /$G @@(switcherF@@ABC"@G@  , 0
*^NN*_NN@@A0G@  , 0*cNN*dNN@
@@]@ {^@ ȐB(0G@  , 0*pNENX*qNEN@
@@]@ |^@ ՐB50"(G@  , 0)*}NENU:@@A90&,G@  , 0-*NN'*NN7@@A?!nc@@ @ t^@ o@*MWMh*MWMi@@0= 08b>@H@@A]>BC\@H@  , 0D*MM*MN@@A0B
H@  , 0I*MM*MM@
@@^@ _@ B$0OH@  , l0V*MM*MM@@@^@ _@ B10\$H@  , P0c*MM*MM@
@@]@ ^@ B=0h0H@  , D0o*MMB@@ AA0l4HA  , <0u*MWMl*MWM@A'C0tzG  , 0|*MMU*N8ND@@.A0zG@  , 0*MM&*MMO@!@@]@ n]@ f9B0G@  , 
0*MM#@@>A0G@  , 
0*LL@@BA 0C@F@  , 
0*LL*LL@@IA0F@  , 
0*LL*LL5@@NA0F@  , 
d0*LQLb*LQL}@@SA0F@  , 
0*KL@@WA0EA  , 
 0+ KK+KK@A^C0@@A@BC@D  , 	0+KK+KK@jB'0@@AB@C@  , 	0+KK@@rA.0C@  , 	0Ű+KK@@vA10°@@A@B@BA  , 	0ΰ+"KbKu+#KbK@AA;0Ͱ@@A@A
  , 	0װ++KbKj@@@B0A@  , 	0۰+/PP+0PQ@AA@00@@  , 	0+4PQ@FB$lineD\@ @+>PP+?PP@@0 0@A@@A@@B@  , 	|0@@0A@  , 	t0+IQQ+JQQ@@A%lines(\@ +@+RQQ+SQQ@@1 0@B@@AC@@~A@@AB@@CB  , 	L1+cQQ+dQQ@?@@^@ =^@ JȐB%lines "@+rQQ+sQQ@@1" 1@ @AC@@@AB@@C@  , 	81)+}QQ@@A1&	C   , 	1.A@1)@'@A@@A%  , 	13+2UuU}+2UuU@AA@1110@@  , 	 18@A!s([@ @+RSR[+RSR\@@1B 1=@A@@A@B@@A@A@  , 1I+/TT+0U*Ui@@A1G
A@  , 1N+.TT+.TT@!@@\@ O\@ HB 1SA@  , 1Z+.TT'@@A$1WA@  , 1^+,TT+,TT@AA@1\1[@@  , 1c+,TT@*\@ 3B3!i#intA@@ @ ]@ @+)ST+)ST@@1z #len@@ @ ]@ @+*T2T>+*T2TA@@1 "s'	@@ @ ]@ @++TWTc++TWTe@@1 1@+B@@AC@@T@D@@ABCU@D@  , 1+,TT+,TT@@@\@ 5]@ ;TB>1E@  , |1J@WA@1DA  , x1, +TWTh,+TWT~@A^CG1@o@ABn@C  , T1,
+TWT_X@@gAO1C@  , H1,*T2T:\@@kAR1@*@A{@Bz@BA  , D1ð,)ST,)ST.@AuA1A  , <1ʰ,)ST@*@@]@ ^@ B1A@  , (1ְ,*)ST(,+)ST-@+@@^@ _@ B1A@  , 1,6(SS,7-TT@@A1A@  , 1,;(SS,<(SS@"y@@\@ \@ B1A@  , 1,G(SS@@A1A@  , 1,K&SS,L&SS@AA@11@@  , 1,P&SS@[@ Bˠ#lenQ@@ @ ]@ @,_$SQS],`$SQS`@@2 "s'A@@ @ ]@ @,k%SvS,l%SvS@@2 2@B@@A@C@@AB@C@  , 2#,@A"2CA  , 2',{%SvS,|%SvS@AِC)2&@B@B
  , 20,%SvS~9@@A02-B@  , 24,#SSO,'SS@@A22A@  , 29,#SS%,#SSI@"@@\@ \@ B2>A@  , l2E,#SS"@@A2BA@  , `2I,"S
S,"S
S@@A2G
A@  , X2N,!RR,!RS@?@@\@ ]@ B 2SA@  , 42Z, RR, RR@>@@\@ ]@ B,2_"A@  , 2f, RR3@@@02c&A@  , 2j,JmJ{,JmJ@@* C@@[@ @[@ [@ 	#Rust.print_rust_handle_call_commentA2^$name*X@,HH,HH@@2 $call*X@,HH,HH@@2 "md*>[@ @,J5J=,J5J?@@2 2@A@@A
C@@B@@AB@@*^C@@*}@@@ABD@  , 2,JmJq,JmJ@@+A)2CA  , 2,J5JB,J5Ji@A2B02@@@AB@B  , 2-J5J9@@;A82B@  , 2-JJ(-JJ3@*@@[@ \@ rFAD2B@  , 2@IAF2B@  , 2-JJ-JJ"@#R@@\@ k\@ bTBR2"B@  , 2̰- I~I-!JJ@@ZAW2'B@  , 2Ѱ-%I~I-&I~I@#c@@[@ ][@ TeBc23B@  , l2ݰ-1I~I@@jAg27B@  , l2-5I!I%-6I3I|@*@@[@ O\@ uBs2CB@  , T2-AI3I9@-&@@\@ !]@ 8B~2NB@  , <2-LI3IQ-MI3I{@
+@@]@ :@@]@ 9]@ BB3^B@  , 3'@A3`B@  , 3
-^II-_II@#@@\@ \@ B3lB@  , 3-jIIJ@@@3pB@  , 3-n &-o 0@A4Rust.rust_cbarg_typeA@33@@  , 3 -t @@A2!nf@@ @ г@-~ - @@3.w3)@B@@A lA@@B@@,f @@A,@@@,Q @@ABBH  , 3>- - @A$A@3<3;@@  , 3C- @@(A3!nd @@ @ Ч@- - @@3Qu3L@B@@A#@B@!B  , 3X- 1C- 1J@@>A33!ng6@@ @ й@- 1>- 1?@@3fx3a@6@A@4A.  , |3k- - @,[@ SA3I#argkO@@ @ @- - @@3||3w@B@@AN@B@LB@  , p3- @@gA3BJ  , T3- - @AmA@33@@  , L3- @@qA3f!ne a@@ @ Э@- - @@3v3@B@@Al@B@jBd  , 03- - @AA@33@@  , (3- @@A3!nc {@@ @ С@. . @@3t3@B@@A@B@B~  , 3. Ks. K@AA@33@@  ,  3. Ke@@A3"n1h~@@ @ @. KZ. K\@@3y"n2i@@ @ @.( K^.) K`@@3z3Ӱ@C@@AB@@@AB@C  , 3.5 .6 @,@@\@ ]@ ͐B3à$elemj@@ @ @.F .G @@3{3@B@@A@B@B@  , 3.P @- [@ КA3C@  , 4.W "@@A4 Bˠ  , t4.\ `@A@34AР  , X4
.a .b -@,@@[@ l\@ t7Rust.rust_closure_traitB3%*opt*\-,-+@@ @ @.x .y +A@4(m-8]-2[@ @. @@4.n&cbargs_-*[@ u@. -. 3@@46p+rust_cbargs`.@@ @ '\@ "@. ?E. ?P@@4Bq3lifetime_constrainta3_@@ @ R\@ #@. . @@4Nr4I@5B@@A%A@@.C@@AE@@#D@@ABC@@- @@A-<C@@-v@@@ABE@  , D4a. T@-O@@\@ u]@ }SBR4eE@  , ,4l. _@@XAV4i E@  ,  4p. . @@]AY4n%#@!@@ABC@D@  , 4y. . @6gBe!xb3@@ @ L@. . @@4s4;9@8@A5@E@@ABC@6E@  , 4@{A4E@  , 4. ?S. ?@\B~4JH@F@AB@BC@  , 4. ?f
@-{@@\@ (\@ 1B4C@  , 4. ?A@@A4C@  , 4/ @@A4a_@B@XB@  , 4@A%*sth*^-@
@4o4@j@AC@@k@AB@dC@  , 4@@4B@  , `4/ / @@2Rust.rust_arg_typeA4$nameX!@@ @ ]@ @/# Kh/$ Kl@@4k	%4ϰ@v=B@@AD"C@@"S[A@@AB@@.@@@A-F@@-C@@ABDT  , 84/> ,=/? ,D@@)A44@@A@A	  , (4/F p/G p@@1A44A  , 4/L EU/M EZ@@7A44A  , 4/R #/S +@@=A44A  , 5/X /Y '@@CA45A!  , 5
/^ /_ @@IA45 A'  , 5/d /e @@OA45&A-  , 5/j /k @@UA45,A3  , 5/p (6/q (J@@[A452A9  , 5"/v [j/w [o@@aA45 8A?  , 5(/|  
/}  @@gA55&>AE  , 5./ / @@mA55,DAK  , x54/ / @@sA552JAQ  , \5:/ Os/ O@.)zB5&cbargsZed@@ @ 1@@ @ 0@/ O]/ Oc@@5Nl5I@9B@@AC@@w@AB@uC@  , P5W/ Oi@@A5TCs  , ,5\/ ";/ "N@@A565ZrAy  , 5b/ / !@@A5<5`xA  , 5h/ / @@A5B5f~A  , 5n/ / @@A5H5lA  , 5t/ / @@A5N5rA  , 5z/ F@A@5S5wA  , p5/ P
6
8/ P
6
C@@,Rust.explodeA5U#str /P[@ q@/ J		/ J		@@5U!r!&Stdlib#ref5/Z[@ ʹ@@ @ ʸ\@ ʶ@@ @ ʵ\@ ʲ@/ K		/ K		@@5V5@B@@A(A@@B@@/~@@@/ @@ABB@  , ,50 N

%0 N

,@A4A@55@@  , 50 N

 @@8A9!i"
@@\@ \@ @0 L		0 O
.
4@@5W!c#/@@ @ ^@ @0& M		0' M		@@5X5Ѱ@E@@A C@@B1@1@AC@0E@  , 5߰03 M		04 N

-@@`A'5ݰ@
@A:	B@8D@  ,  5"g@@fAe5@B@  ,  50> K		0? K		@AkA@55@@  ,  50C K		p@@o@m5@G@A@FA@  ,  50I E		0J E		*@@8Rust.to_upper_snake_caseA5͠!s/@0T}Ea0U}Eb@@6P!s/@@ @ i\@ f@0a~ek0b~el@@6Q!s/[@ n@0i0j@@6R!s/ޠ5<@@ @ ʇ\@ y@@ @ x\@ t@0| @0} @@@6,S6'@D C/B8A@@A@@0C@@0!@@@ABDA  ,  6=0 @0 D	
	@AHBG6<@@A@C
  ,  6F0 @0 D	
	@A>Rust.to_upper_snake_case.(fun)A@6E6D@@  ,  6L0 @W@@VAT6I
CA  ,  6R00@A]A[6Q@&@A@#B
  ,  6[0f@@eAb6XBA  ,  6a0~eo0~e@AlAi6`@3@A@2A
  ,  l6j0~egu@@t@p6gA@  ,  \6n0 B0 B@@(Aw6l@"chA@@A@@AC  ,  P6z0 B0 B@@4A6xA  ,  H60 C0 C	@A:A@6~6}@@  ,  @60 C@f]@ ʑAB0G\@ ʀ@0 C0 C@@6T6!A@  , h6@KA	6#A  , H6QAN@6&A!@         
   5/tmp/libnbd/generator@       k  d  ( $RustPK.Stdlib__Stringt@!_'Rust.ml B B@@@ ` t%Utils   E		'@@ ! 5caml_ml_string_length 蠠,Stdlib__List|$bool& ' @@𠠐%&[u8]/ 0 @@ )&mut [u8]8 9 @@-&'static [u8]A B  @@ 1&'static mut [u8]J "<K "M@@0%impl S OjT Oo@@`&Stdlibh)NbdExtenta b @@|'OwnedFdj k @@%c_ints  t  @@#i64| [k} [n@@2impl Into<PathBuf> (7 (I@@%usize  @@̠*SocketAddr  @@ܠ2impl Into<Vec<u8>>  @@젠	*impl IntoIterator<Item = impl AsRef<[u8]>>  &@@&c_uint $ *@@#u32 EV EY@@#u64 p p@@,%usize ,> ,C@@<d@''static # *@@@",  ?b ?d@@̠Ԡ# +   @@  @@$8) -> c_int + Send + Sync  @@08L&FnMut(  @@\d!]" # @@Ġ"&[. / @@Ԡܠ%&mut : ; @@%&[u8]F 1DG 1I@@ OII@@ 4caml_string_notequalb0%
/// ^I3II_I3IO@@@nH@K$/// nI!I(oI!I2A@B@LJ@@@@'/// %s
@@X{` I~I@@p< JJ!@@G@K%/// 
JJ+JJ3A@@@%/// 

@@@K$/// JmJJmJA@B@LJ@@@@'/// %s
@@蠠𠠑 %=over RR RR@@ (%=back!RR!RS@@DL%=item#SSA#SSF@@t|
!-&SS&SS@@̠Ԡ%=head(SS(SS@@ /caml_string_get$)02caml_int_of_string@L3l6!=5.TT6.TT@@1Ƞ@K<rust: API documentation for E/TTF0U*UbA@B@K+ contains '@B@K	?' which
                   cannot be converted to Rust markdown@@@@@@@	jrust: API documentation for %s contains '%s' which
                   cannot be converted to Rust markdown @@蠠^𠠐@#```pQQqQQ@@@@	4 	@@'```textQQQQ@@@@	P1	X! PQPQ@@		#Str		Ƞ	ؠ	@K#<b>LQLjLQLuA@B@K$</b>@@@@@)<b>%s</b>@@
l.Stdlib__Printf
t@L `B@L `@@@@$`%s`LL'LL-A@@
"
@LfB@L{@@@@$&%s;LLLLA@@
B
Ġ
젠$nbd_MMBMMF@@

 $0)get_error MM!MM@@@L)get_errno,MM-MM@@\h%close8MM9MM@@x@L [B@K*](Handle::RMMSMNA@B@Li@@@@@@0[%s](Handle::%s)@@@L `B@L `@@@@$`%s`NN/NN5A@@Ġ'http://NENtNEN{@@ܠ䠠(https://NNNN@@ @L [B@K"](NNNNA@B@Li@@@@@@([%s](%s)@@(0@K#<i>O=ORO=O]A@B@K$</i>@@@@@)<i>%s</i>@@H(P@K<rust: API documentation for 	OuO
OOA@B@K+ contains '@B@K	B' which
                      cannot be converted to Rust markdown@@@@@@@	mrust: API documentation for %s contains '%s' which
                      cannot be converted to Rust markdown @@lt@K#<i>%L~L&L~LA@B@K$</i>@@@@@)<i>%s</i>@@w-[A-Z]<[^>]+?>CKKADKKN@ ȠРࠠ!
TPZPpUPZPr@@P?
 V
4E
XH
l_
@.Tage Johanssonqc    rc    @@@
m
@LJ@@!
d  	  d  	  A@@
Ġ
̠@K:use crate::{*, types::*};
U  (  -U  (  JA@@@:use crate::{*, types::*};

@@
 @K	!use os_socketaddr::OsSocketAddr;
V  L  QV  L  uA@@@	!use os_socketaddr::OsSocketAddr;

@@@K1use std::ffi::*;
W  w  |W  w  A@@@1use std::ffi::*;

@@(0@K.use std::mem;
X    X    A@@@.use std::mem;

@@@H@K:use std::net::SocketAddr;
Y    Y    A@@@:use std::net::SocketAddr;

@@X`@K	%use std::os::fd::{AsRawFd, OwnedFd};

Z    Z    A@@@	%use std::os::fd::{AsRawFd, OwnedFd};

@@p
x@K?use std::os::unix::prelude::*;
![    "[    $A@@@?use std::os::unix::prelude::*;

@@$@K8use std::path::PathBuf;
8\  &  +9\  &  FA@@@8use std::path::PathBuf;

@@;@K.use std::ptr;
O]  H  MP]  H  ^A@@@.use std::ptr;

@@R@K4use std::sync::Arc;
f^  `  eg^  `  |A@@@4use std::sync::Arc;

@@Рiؠ@K:use tokio::sync::oneshot;
}_  ~  ~_  ~  A@@@:use tokio::sync::oneshot;

@@蠠𠠐@LJ@@!
`    `    A@@ @K3impl AsyncHandle {
G    G    &A@@@3impl AsyncHandle {

@@@K#}

R    R    A@@@#}


@@$true-||0-||4@@P%false-||<-||A@@`@K-pub async fn /|r|w/|r|A@B@K((&self, @B@K6) -> SharedResult<()>
@@@@@@@	/pub async fn %s(&self, %s) -> SharedResult<()>
 @@@K"{
1||1||A@@@"{

@@7self.data.handle.handle*2||+2|}@@@K#?;
73}}"83}}(A@@@#?;

@@Ԡ:ܠ@K	C    let (ret_tx, ret_rx) = oneshot::channel::<SharedResult<()>>();
N4}*}/O4}*}uA@@@	C    let (ret_tx, ret_rx) = oneshot::channel::<SharedResult<()>>();

@@젠Q@K	#    let mut ret_tx = Some(ret_tx);
e5}w}|f5}w}A@@@	#    let mut ret_tx = Some(ret_tx);

@@h@K	     let completion_predicate = 
|6}}}6}}A@@@	     let completion_predicate = 

@@$@K	6     move |handle: &Handle, res: &SharedResult<()>| {
7}}7}~A@@@	6     move |handle: &Handle, res: &SharedResult<()>| {

@@4<@K	&      let ret = if let Err(_) = res {
8~~8~~<A@@@	&      let ret = if let Err(_) = res {

@@LT@K4        res.clone()
9~>~C9~>~ZA@@@4        res.clone()

@@dl@K/      } else {
:~\~a:~\~sA@@@/      } else {

@@|@K2        if handle.;~u~z;~u~A@B@K&() != @B@K3 { return false; }
@@@@@@@	/        if handle.%s() != %s { return false; }
 @@@K8        else { Ok(()) }
<~~<~~A@@@8        else { Ok(()) }

@@@K)      };
3=~~4=~~A@@@)      };

@@̠6Ԡ@K	-      ret_tx.take().unwrap().send(ret).ok();
J>~~K>~(A@@@	-      ret_tx.take().unwrap().send(ret).ok();

@@䠠M젠@K+      true
a?*/b?*=A@@@+      true

@@d@K'    };
x@?Dy@?NA@@@'    };

@@{@K	-    self.add_command(completion_predicate)?;
APUAPA@@@	-    self.add_command(completion_predicate)?;

@@,4@K:    ret_rx.await.unwrap()
BBA@@@:    ret_rx.await.unwrap()

@@DL@K#}

CCA@@@#}


@@\d*completionpppp@@1caml_string_equal-Stdlib__Array,Pp@K0The handle call qqr"rBA@B@K	 is claimed to have a completion callback among its optional arguments by the async_kind field, but that does not seem to be the case.@@@@@	The handle call %s is claimed to have a completion callback among its optional arguments by the async_kind field, but that does not seem to be the case.@@-Р0ࠠ36(@@K-pub async fn t?tDt?txA@B@K((&self, @B@K8) -> SharedResult<()> {
@@@@@@@	1pub async fn %s(&self, %s) -> SharedResult<()> {
 @@,64@K	?    // A oneshot channel to notify when the call is completed.
JttKtu%A@@@	?    // A oneshot channel to notify when the call is completed.

@@DML@K	C    let (ret_tx, ret_rx) = oneshot::channel::<SharedResult<()>>();
au'u,bu'urA@@@	C    let (ret_tx, ret_rx) = oneshot::channel::<SharedResult<()>>();

@@\dd@K	<    let (ccb_tx, mut ccb_rx) = oneshot::channel::<c_int>();
xutuyyutuA@@@	<    let (ccb_tx, mut ccb_rx) = oneshot::channel::<c_int>();

@@t{|3caml_array_get_addr@K(    let uuuvA@B@K	3 = Some(utils::fn_once_to_fn_mut(|err: &mut i32| {
@@@@@	=    let %s = Some(utils::fn_once_to_fn_mut(|err: &mut i32| {
@@@K>      ccb_tx.send(*err).ok();
v]vbv]vA@@@>      ccb_tx.send(*err).ok();

@@Ġ@K(      1
vvvvA@@@(      1

@@Ԡܠ@K)    }));
	vv	vvA@@@)    }));

@@젠7self.data.handle.handlevvvw @@@K#?;
	ww
	wwA@@@#?;

@@(	0@K	#    let mut ret_tx = Some(ret_tx);
	
ww	
ww@A@@@	#    let mut ret_tx = Some(ret_tx);

@@@	H@K	     let completion_predicate = 
	1wBwG	2wBwjA@@@	     let completion_predicate = 

@@X	4`@K	7     move |_handle: &Handle, res: &SharedResult<()>| {
	Hwlwq	IwlwA@@@	7     move |_handle: &Handle, res: &SharedResult<()>| {

@@p	Kx@K<      let ret = match res {
	_ww	`wwA@@@<      let ret = match res {

@@	b@K	/        Err(e) if e.is_fatal() => res.clone(),
	vww	wwx
A@@@	/        Err(e) if e.is_fatal() => res.clone(),

@@	y@K/        _ => {
	xx	xx#A@@@/        _ => {

@@	@K	D          let Ok(errno) = ccb_rx.try_recv() else { return false; };
	x%x*	x%xqA@@@	D          let Ok(errno) = ccb_rx.try_recv() else { return false; };

@@Р	ؠ@K:          if errno == 0 {
	xsxx	xsxA@@@:          if errno == 0 {

@@蠠	𠠐@K3            Ok(())
	xx	xxA@@@3            Ok(())

@@ 	@K3          } else {
	xx	xxA@@@3          } else {

@@	 @K	"            if let Err(e) = res {

 xx
xxA@@@	"            if let Err(e) = res {

@@0
8@K=              Err(e.clone())

xy
xy"A@@@=              Err(e.clone())

@@H
P@K5            } else {

.y$y)
/y$yAA@@@5            } else {

@@`
1h@K;              Err(Arc::new(
EyCyH
FyCyeA@@@;              Err(Arc::new(
@@x
H@K	C                Error::Recoverable(ErrorKind::from_errno(errno))))

\ygyl
]ygyA@@@	C                Error::Recoverable(ErrorKind::from_errno(errno))))

@@
_@K.            }

syy
tyyA@@@.            }

@@
v@K,          }

yy
yyA@@@,          }

@@
Ƞ@K+        },

yy
yyA@@@+        },

@@ؠ
ࠠ@K)      };

yy
yzA@@@)      };

@@𠠑
@K	-      ret_tx.take().unwrap().send(ret).ok();

 z
z
 z
z?A@@@	-      ret_tx.take().unwrap().send(ret).ok();

@@
@K+      true

!zAzF
!zAzTA@@@+      true

@@ 
(@K'    };

"zVz[
"zVzeA@@@'    };

@@8 @@K	-    self.add_command(completion_predicate)?;
#zgzl#zgzA@@@	-    self.add_command(completion_predicate)?;

@@PX@K:    ret_rx.await.unwrap()
+$zz,$zzA@@@:    ret_rx.await.unwrap()

@@h.p@K#}

B%zzC%zzA@@@#}


@@E@K'pub fn YmmZmmA@B@K((&self, @B@K%) -> @B@LJ@@@@@@@@;pub fn %s(&self, %s) -> %s
*@@ࠠ|蠠7self.data.handle.handlemn	mn @@ @LJ@@!
n(n-n(n1A@@ LdUt^@B@K": llllA@B@@@@@&%s: %s@@Ԡ	ܠ젠", llll@@@K'Option<jjjjA@B@L~@@@@*Option<%s>@@H	BP%&[u8]iiii@@䠠)&mut [u8]iiii@@,$aio_#cc$cc@@px9@K2Asynchronous call 9d3dD:d3doA@B@K5 must begin with aio_@@@@@	)Asynchronous call %s must begin with aio_@@ȠGР@.Tage JohanssonYt^^Zt^_@@@U(@LJ@@!
ou__
pu__A@@8k@#API`_p@LJ@@!
x_W_\x_W_`A@@{$̠*ܠ𠠑0 @K.impl Handle {
}`"`'}`"`8A@@@.impl Handle {

@@$,M<P@K#}

`m`r`m`yA@@@#}


@@`h@K8use bitflags::bitflags;
e]]e]]&A@@@8use bitflags::bitflags;

@@|@K:use crate::{*, types::*};

 f](]-
f](]JA@@@:use crate::{*, types::*};

@@
@K	!use os_socketaddr::OsSocketAddr;

g]L]Q
g]L]uA@@@	!use os_socketaddr::OsSocketAddr;

@@
@K1use std::ffi::*;

.h]w]|
/h]w]A@@@1use std::ffi::*;

@@Ġ
1̠@K.use std::mem;

Ei]]
Fi]]A@@@.use std::mem;

@@ܠ
H䠠@K:use std::net::SocketAddr;

\j]]
]j]]A@@@:use std::net::SocketAddr;

@@
_@K	,use std::os::fd::{AsRawFd, OwnedFd, RawFd};

sk]]
tk]^A@@@	,use std::os::fd::{AsRawFd, OwnedFd, RawFd};

@@
v@K?use std::os::unix::prelude::*;

l^^	
l^^+A@@@?use std::os::unix::prelude::*;

@@$
,@K8use std::path::PathBuf;

m^-^2
m^-^MA@@@8use std::path::PathBuf;

@@<
D@K.use std::ptr;

n^O^T
n^O^eA@@@.use std::ptr;

@@T
\@K0use std::slice;

o^g^l
o^g^A@@@0use std::slice;

@@l
t@K<use libnbd_sys::nbd_extent;

p^^
p^^A@@@<use libnbd_sys::nbd_extent;

@@
@LJ@@!
q^^q^^A@@

ؠ

 
 (
 H
 X@B@K": *VZZ+VZZA@B@@@@@&%s: %s@@ pv x! ", EUZZFUZZ@@ U @K1#[allow(unused)]
U]\+\2V]\+\FA@@@1#[allow(unused)]

@@ ࠠX 蠠@K+pub(crate) l^\H\Om^\H\\A@@@+pub(crate) 
@@ o! @K$pub _\^\h_\^\nA@@@$pub 
@@!! @K#fn `\p\u`\p\A@B@K((&self, @B@K%) -> @B@LJ@@@@@@@@7fn %s(&self, %s) -> %s
*@@!T!\+self.handlea\\a\\@@!t@LJ@@!
b\\b\\A@@!!!!ܠ!젠!@K"{
>WWW\>WWWaA@@@"{

@@""@K	0    // Convert all arguments to FFI-like types.
?WcWh?WcWA@@@	0    // Convert all arguments to FFI-like types.

@@"$","L"l@LJ@@!
6BWW7BWWA@@"|2"@K>    // Call the FFI-function.
FCWXGCWX"A@@@>    // Call the FFI-function.

@@"I"", YEXkXZEXkX@@"i"@K	$    let ffi_ret = unsafe { sys::nbd_iDX$X)jDX$X^A@B@LhB@K", @B@K%) };
#@@@@@@@@@	2    let ffi_ret = unsafe { sys::nbd_%s(%s, %s) };
*@@"ؠ"ࠠ@LJ@@!
FXXFXXA@@""@K	3    // Convert the result to something more rusty.
GXXGXXA@@@	3    // Convert the result to something more rusty.

@@##@K"}
IXXIXXA@@@"}

@@#4#<@@@#d#####Ԡ@K5pub(crate) unsafe fn DDDEA@B@K=_to_raw<F>(f: F) -> sys::nbd_@B@K*_callback
@@@@@@@	@pub(crate) unsafe fn %s_to_raw<F>(f: F) -> sys::nbd_%s_callback
 @@#젠#@K+  where F: 'E3E8(E3EIA@B@LJ@@@@.  where F: %s
@@$4$@K"{
HEYE^IEYEcA@@@"{

@@$ K$(@B@K": dEEeEEA@B@@@@@&%s: %s@@$@
$H[$X", EEEE@@$h$p@K	<    unsafe extern "C" fn call_closure<F>(data: *mut c_void, EjEnEEA@B@K+) -> c_int
@@@@@	I    unsafe extern "C" fn call_closure<F>(data: *mut c_void, %s) -> c_int
@@$$@K/      where F: F&F+F&F@A@B@LJ@@@@2      where F: %s
@@$$@K&    {
FPFUFPF^A@@@&    {

@@$$@K	+        let callback_ptr = data as *mut F;
F`FeF`FA@@@	+        let callback_ptr = data as *mut F;

@@$̠$Ԡ@K	+        let callback = &mut *callback_ptr;
 FFFFA@@@	+        let callback = &mut *callback_ptr;

@@$䠠$젠%", FGFG!@@%&%$@K1        callback(&FF'FGA@B@K")
@@@@@5        callback(%s)
@@%44%<@K&    }
HG7G<IG7GEA@@@&    }

@@%LK%T@K	4    let callback_data = Box::into_raw(Box::new(f));
_GGGL`GGGA@@@	4    let callback_data = Box::into_raw(Box::new(f));

@@%db%l@K-    sys::nbd_vGGwGGA@B@K,_callback {
@@@@@;    sys::nbd_%s_callback {
@@%%@K	+        callback: Some(call_closure::<F>),
GGGGA@@@	+        callback: Some(call_closure::<F>),

@@%%@K	,        user_data: callback_data as *mut _,
GGGHA@@@	,        user_data: callback_data as *mut _,

@@%%@K	+        free: Some(utils::drop_data::<F>),
HH!HHOA@@@	+        free: Some(utils::drop_data::<F>),

@@%Ƞ%Р@K&    }
HQHVHQH_A@@@&    }

@@%ࠠ%蠠@K"}
HaHfHaHkA@@@"}

@@%& @LJ@@!
HmHrHmHvA@@&
&@K+ffi_ret as !>>">>A@B@@@@-ffi_ret as %s@@&m&,ffi_ret != 09<<":<<.@@&	-unsafe { CStr::from_ptr(ffi_ret) }.to_bytes()B=Q=iC=Q=@@&"()K<0<?L<0<A@@&Ƞ0ffi_ret as RawFdT=1=?U=1=O@@&ؠ	*TryInto::<u32>::try_into(ffi_ret).unwrap()]<C<R^<C<|@@&蠠	*TryInto::<u64>::try_into(ffi_ret).unwrap()f<~<g<~<@@&	#Cookie(ffi_ret.try_into().unwrap())o<=p<=/@@'	,TryInto::<usize>::try_into(ffi_ret).unwrap()x<<y<<@@'%res }>>F>>K@@'(	'unsafe { libc::free(ffi_ret.cast()); }
>>>>A@@'07'8	>  unsafe { CStr::from_ptr(ffi_ret) }.to_owned().into_bytes();
===>@@'HC'P-{ let res = 
====@@'`O'h@K	!unsafe { mem::transmute::<isize, ?h?x?h?A@B@K5>(ffi_ret as isize) }@@@@@	8unsafe { mem::transmute::<isize, %s>(ffi_ret as isize) }@@''@B@K=::from_bits(ffi_ret).unwrap()>m>}>m>A@@@@?%s::from_bits(ffi_ret).unwrap()
@@' '@K1if ffi_ret < 0 {
@B@M@B@aA@@@1if ffi_ret < 0 {

@@(8(@@K	8    Err(unsafe { Error::get_error(self.raw_handle()) })
@c@n@c@A@@@	8    Err(unsafe { Error::get_error(self.raw_handle()) })

@@(P
(X@K"}
@@@@A@@@"}

@@(h!(p@K7if ffi_ret.is_null() {
5@@6@AA@@@7if ffi_ret.is_null() {

@@(8(@K	8    Err(unsafe { Error::get_error(self.raw_handle()) })
LAAMAAJA@@@	8    Err(unsafe { Error::get_error(self.raw_handle()) })

@@(O(@K"}
cALAWdALA\A@@@"}

@@(f(	3In ffi_ret_to_rust: Return type cannot be an error.vAAwAA@@(ؠ#(ࠠ@K*else { Ok(AAAAA@B@K$) }
@@@@@0else { Ok(%s) }
@@()@B@LJ@@@#%s
BBBBA@@))$@K$let s55s55A@B@K": @B@K# = @@@@@@@-let %s: %s =  @@)`)h@B@@@"%sv66v66A@@)ࠠ)蠠	Lgenerator/Rust.ml: in ffi_cbargs_to_rust: Unsupported type of array element.889"93@@**Ġ@K6slice::from_raw_parts(~8D8M~8D8A@B@K6 as *const NbdExtent, @B@Li@@@@@@	1slice::from_raw_parts(%s as *const NbdExtent, %s)@@+p*+x@K6slice::from_raw_parts(>|77?|77A@B@K", @B@Li@@@@@@=slice::from_raw_parts(%s, %s)@@,,V,4@K6slice::from_raw_parts(jy7!7*ky7!7VA@B@K/ as *const u8, @B@Li@@@@@@	*slice::from_raw_parts(%s as *const u8, %s)@@,- 	Ogenerator/Rust.ml: in ffi_cbargs_to_rust: Unsupported type of mutable argument.999:@@-ࠠ?-蠠@B@K2.as_mut().unwrap()959_959uA@@@@4%s.as_mut().unwrap()
@@.T.\@K/CStr::from_ptr(w66w66A@B@K,).to_bytes()@@@@@=CStr::from_ptr(%s).to_bytes()@@.ࠠ.蠠	Fgenerator/Rust.ml: In ffi_cbargs_to_rust: bad number of ffi arguments.:(:1:o:@@//@K";
::::A@@@";

@@/(/0@K$let _22_22A@B@K) = match @B@K# {
@@@@@@@4let %s = match %s {
 @@//@K	)    Some(f) => unsafe { crate::bindings::0`221`233A@B@K._to_raw(f) },
@@@@@	9    Some(f) => unsafe { crate::bindings::%s_to_raw(f) },
@@/>/@K5    None => sys::nbd_Rb3G3PSb3G3uA@B@K,_callback { @@@@@	#    None => sys::nbd_%s_callback { @@/`/Ƞ@K0callback: None, tc3~3uc3~3A@@@0callback: None, 
@@/ؠw/ࠠ@K,free: None, d33d33A@@@,free: None, 
@@/𠠑/@K;user_data: ptr::null_mut() e33e33A@@@;user_data: ptr::null_mut() 
@@00@K#},
f33f33A@@@#},

@@0 0(@K#};
g33g33A@@@#};

@@080@0h@K$let j4T4]j4T4A@B@K# = @B@K+.unwrap_or(@B@K3::empty()).bits();
$@@@@@@@@@	+let %s = %s.unwrap_or(%s::empty()).bits();
+@@00@$%
 $%@@|@1p.Assert_failure\1x@K$let 7%%#8%%3A@B@K# = @B@K";
@@@@@@@-let %s = %s;
 @@1P1@_aT01(bT014@@T|@2B2@K$let wU181AxU181xA@B@K= = unsafe { crate::bindings::@B@K(_to_raw(@B@K%) };
$@@@@@@@@@	4let %s = unsafe { crate::bindings::%s_to_raw(%s) };
+@@2,24@%U%%U%@@|@22@K$let %%%%A@B@K# = @B@K+ as c_int;
@@@@@@@6let %s = %s as c_int;
 @@2Ġ2̠@W11W11@@WR@2ࠠ2蠠@Q0V0 Q0V0@@Q|@3P3X@K$let R00R00A@B@K# = @B@K..as_raw_fd();
@@@@@@@9let %s = %s.as_raw_fd();
 @@3t.3|@=?%&"@%&.@@|@3䠠 3젠@K$let U&2&;V&2&RA@B@K# = @B@K).bits();
@@@@@@@4let %s = %s.bits();
 @@4n4@},(),()@@,|@4x`4@K$let -)) -))/A@B@K'_buf = @@@@@-let %s_buf = @@44@K-CString::new(.);)D.);)yA@B@K	$.into().into_os_string().into_vec())@@@@@	3CString::new(%s.into().into_os_string().into_vec())@@44@K?.map_err(|e| Error::from(e))?;
/))/))A@@@?.map_err(|e| Error::from(e))?;

@@4̠4Ԡ@K$let 0))0))A@B@K# = @B@K/_buf.as_ptr();
@@@@@@@:let %s = %s_buf.as_ptr();
 @@4젠	4@K$let "&&"&'#A@B@K9_os = OsSocketAddr::from(@B@K#);
@@@@@@@	$let %s_os = OsSocketAddr::from(%s);
 @@5|65@K$let J#'9'BK#'9'^A@B@K# = @B@K._os.as_ptr();
@@@@@@@9let %s = %s_os.as_ptr();
 @@5c5@K$let w$'x'x$'x'A@B@K# = @B@K+_os.len();
@@@@@@@6let %s = %s_os.len();
 @@5Ġ5̠@ && &&@@ w@5蠠5𠠐@&''&'(
@@&|@6X6`@K$let ((((((eA@B@K4_buf = CString::new(@B@K	'.into()).map_err(|e| Error::from(e))?;
@@@@@@@	Clet %s_buf = CString::new(%s.into()).map_err(|e| Error::from(e))?;
 @@6|6@K$let *((*((A@B@K# = @B@K/_buf.as_ptr();
@@@@@@@:let %s = %s_buf.as_ptr();
 @@66@!2* *<"2* *H@@2|@77@K$let 75**85*+A@B@K8_c_strs: Vec<CString> = @@@@@>let %s_c_strs: Vec<CString> = @@7,E74@B@K,.into_iter()^6++_6++,A@@@@.%s.into_iter()
@@7Ha7P@K	!.map(|x| CString::new(x.as_ref())u7+8+Av7+8+dA@@@	!.map(|x| CString::new(x.as_ref())
@@7`x7h@K	).map_err(|e| Error::from(e.to_string())))8+f+o8+f+A@@@	).map_err(|e| Error::from(e.to_string())))
@@7x7@K	%.collect::<Result<Vec<CString>>>()?;
9++9++A@@@	%.collect::<Result<Vec<CString>>>()?;

@@77@K(let mut >,,>,,A@B@K;_ptrs: Vec<*mut c_char> = 
@@@@@	%let mut %s_ptrs: Vec<*mut c_char> = 
@@77@K"  ?--
?--MA@B@K	9_c_strs.iter().map(|x| x.as_ptr().cast_mut()).collect();
@@@@@	=  %s_c_strs.iter().map(|x| x.as_ptr().cast_mut()).collect();
@@7Ƞ7Р@B@K=_ptrs.push(ptr::null_mut());
B--B--A@@@@?%s_ptrs.push(ptr::null_mut());

@@7䠠7젠@K$let C--C--A@B@K# = @B@K4_ptrs.as_mut_ptr();
@@@@@@@?let %s = %s_ptrs.as_mut_ptr();
 @@838@K$let GH..HH..A@B@K# = @B@K<.as_ptr() as *const c_void;
@@@@@@@	'let %s = %s.as_ptr() as *const c_void;
 @@8`8@K$let tI..uI./A@B@K# = @B@K(.len();
@@@@@@@3let %s = %s.len();
 @@88@F.[.F.[.@@Fw@8ؠ8ࠠ@K$let N//N//A@B@K# = @B@K>.as_mut_ptr() as *mut c_void;
@@@@@@@	)let %s = %s.as_mut_ptr() as *mut c_void;
 @@9d9l@K$let O00O002A@B@K# = @B@K(.len();
@@@@@@@3let %s = %s.len();
 @@99@	L/x/L/x/@@Lw@99$bool      @@:-&'static [u8]&  !
'  !@@:,"()/ !!+0 !!-@@:<%RawFd8 !/!=9 !/!B@@:L&c_uintA !D!SB !D!Y@@:\#u64J ![!lK ![!o@@:l&CookieS !q!T !q!@@:|%usize\!!]!!@@:'Vec<u8>e!!f!!@@:&c_uintn!!o!!@@:%usizew!!x!!@@:#u64!"!"@@:̠|:@K'Result<	"j"	"j"A@B@L~@@@@*Result<%s>@@;,;4	Igenerator/Rust.ml: in ffi_cbarg_types: Unsupported type of array element. ^g @@;蠠Z;𠠐@/*mut nbd_extent  +@@@%usize / 4@@@@@<@(*mut u32  @@@%usize  @@@@@<@-*const c_void  @@@%usize  @@@@@<$@%c_int   @@@@<4@#i64 ,@ ,C@@@@<D	Lgenerator/Rust.ml: in ffi_cbarg_types: Unsupported type of mutable argument.  	   W i@@<<Ġ@**mut c_int( ) @@@@<ؠ@-*const c_char6 cx7 c@@@@<蠠@&c_uintD "E (@@@@<@#u64R G\S G_@@@@=$_ffi^ _ @@=T=`$_ffij Ak A@@==$_ffiv Axw A|@@=#=̠$_ffi 
9 
=@@> />$_ffi 
, 
0@@>$;>0$_ffi  @@>\G>p$_ffi C C@@>ܠS>蠠@  @@ РR@??$_ffi  @@?Ԡr?ࠠ$_ffi  @@?~@$_ffi  #@@@(@4@K'Option< Zt ZA@B@L~@@@@*Option<%s>@@@>@@K'Option<  A@B@L~@@@@*Option<%s>@@@Ƞ_@Р@K*pub const / ^
0 ^(A@B@K(: u32 = @D@@@K";
@@@@@@@8pub const %s: u32 = %d;
&@@B`NBh!:^ W&_ W'@@BBB@K2pub const CONTEXT_q X3?r X3lA@B@L _B@K,: &[u8] = b"@B@K#";
#@@@@@@@@@	(pub const CONTEXT_%s_%s: &[u8] = b"%s";
*@@B䠠B젠C@K4pub const NAMESPACE_ T

 T

A@B@K,: &[u8] = b"@B@K$:";
@@@@@@@	(pub const NAMESPACE_%s: &[u8] = b"%s:";
 @@CLCTC|@K.        const wwA@B@K# = @D@@@K";
@@@@@@@7        const %s = %d;
&@@CC@K,bitflags! {
rrA@@@,bitflags! {

@@CؠCࠠ@K/    #[repr(C)]
%s
&s
!A@@@/    #[repr(C)]

@@C𠠑(C@K	7    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
<t#(=t#bA@@@	7    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

@@D?DBD$@K/    pub struct VudiWudA@B@K(: u32 {
@@@@@9    pub struct %s: u32 {
@@D4dD<SD`@K&    }
{y |y	A@@@&    }

@@Dp~Dx@K#}

zzA@@@#}


@@DDD@K$    l7Rl7bA@B@K# = @D@@@K",
@@@@@@@-    %s = %d,
&@@D̠DԠ@K	3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
hhA@@@	3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

@@D蠠D𠠐@K.#[repr(isize)]iiA@@@.#[repr(isize)]
@@E EE @K)pub enum jjA@B@K# {
@@@@@.pub enum %s {
@@E0E8
E`@K#}

5n6nA@@@#}


@@Ep8Ex@K*pub const LeY^MeYyA@B@K(: u32 = @D@@@K";
@@@@@@@8pub const %s: u32 = %d;
&@@EkEEEȠ+Stdlib__SetE젠E@)get_debugbb@@@)set_debugbb@@@2set_debug_callbackbb@@@4clear_debug_callbackbb,@@@@@@@F7HHHԠ@*aio_get_fdb%b-b%b7@@@1aio_get_directionb:bBb:bS@@@4clear_debug_callbackbVb^bVbr@@@)get_debugbub}bub@@@)set_debugbbbb@@@2set_debug_callbackbbbb@@@@@@@@@H蠠H𠠑  I I+Stdlib__MapI@ILItI  II蠠IJ JHJt +K@%Utils0#_Aк6u2+l#Str0jxЊ0ĩ-٠-Stdlib__Uchar0o9us:2[].Stdlib__String0.BdJP.F4Y3+Stdlib__Set0b)uǑ
bQ8+Stdlib__Seq0Jd8_mJk.Stdlib__Printf0pJUX빃Ύ+Stdlib__Map0@mŘ`rnࠠ,Stdlib__List0U#r&L.Stdlib__Either0$_ʩ<.Stdlib__Buffer0ok
Vj-Stdlib__Array0XUJө
	ƿ8&Stdlib0-&fºnr39tߠ n0<>>O[6B\NI8CamlinternalFormatBasics0ĵ'(jdǠ#API0e M'cC@
B  Sv ݠ m@@@K c	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                /* NBD client library in userspace
 * WARNING: THIS FILE IS GENERATED FROM
 * generator/generator generator/states*.c
 * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
 *
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#line 1 "generator/states-connect-socket-activation.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine related to connecting with systemd socket activation. */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/un.h>

#include "internal.h"
#include "compiler-macros.h"
#include "unique-name.h"
#include "array-size.h"
#include "checked-overflow.h"

/* This is baked into the systemd socket activation API. */
#define FIRST_SOCKET_ACTIVATION_FD 3

/* Describes a systemd socket activation environment variable. */
struct sact_var {
  const char *prefix; /* variable name and equal sign */
  size_t prefix_len;
  const char *value;
  size_t value_len;
};

/* Determine the length of a string, using "sizeof" whenever possible.
 *
 * Do not use this macro on an argument that has side effects, as no guarantees
 * are given regarding the number of times the argument may be evaluated.
 * TYPE_IS_ARRAY(s) itself may contribute a different number of evaluations
 * dependent on whether "s" has variably modified type, and then the conditional
 * operator either evaluates "sizeof s" (which contributes 0 or 1 evaluations,
 * dependent on whether "s" has variably modified type) or strlen(s) (which
 * contributes 1 evaluation). Also note that the argument of the "sizeof"
 * operator is *only* parenthesized because "s" is a macro parameter here.
*/
#define STRLEN1(s) ((TYPE_IS_ARRAY (s) ? sizeof (s) - 1 : strlen (s)))

/* Push a new element to an array of "sact_var" structures.
 *
 * "vars" is the array to extend. "num_vars" (of type (size_t *)) points to the
 * number of elements that the array, on input, contains; (*num_vars) is
 * increased by one on output. "prefix" and "value" serve as the values for
 * setting the fields in the new element. "ofs" (of type (size_t *)) may be
 * NULL; if it isn't, then on output, (*ofs) is set to the input value of
 * (*num_vars): the offset of the just-pushed element.
 *
 * Avoid arguments with side-effects here as well.
 */
#define SACT_VAR_PUSH(vars, num_vars, prefix, value, ofs)       \
  SACT_VAR_PUSH1 ((vars), (num_vars), (prefix), (value), (ofs), \
                  NBDKIT_UNIQUE_NAME (_ofs))
#define SACT_VAR_PUSH1(vars, num_vars, prefix, value, ofs, ofs1)             \
  do {                                                                       \
    size_t *ofs1;                                                            \
                                                                             \
    assert (*(num_vars) < ARRAY_SIZE (vars));                                \
    ofs1 = (ofs);                                                            \
    if (ofs1 != NULL)                                                        \
      *ofs1 = *(num_vars);                                                   \
    (vars)[(*(num_vars))++] = (struct sact_var){ (prefix), STRLEN1 (prefix), \
                                                 (value), STRLEN1 (value) }; \
  } while (0)

extern char **environ;

/* Prepare environment for calling execvp when doing systemd socket activation.
 * Takes the current environment and copies it. Removes any existing socket
 * activation variables and replaces them with new ones. Variables in "sact_var"
 * will be placed at the front of "env", preserving the order from "sact_var".
 */
static int
prepare_socket_activation_environment (string_vector *env,
                                       const struct sact_var *sact_var,
                                       size_t num_vars)
{
  const struct sact_var *var_end;
  char *new_var;
  const struct sact_var *var;
  size_t i;

  *env = (string_vector)empty_vector;

  /* Set the exclusive limit for loops over "sact_var". */
  var_end = sact_var + num_vars;

  /* New environment variable being constructed for "env". */
  new_var = NULL;

  /* Copy "sact_var" to the front of "env". */
  for (var = sact_var; var < var_end; ++var) {
    size_t new_var_size;
    char *p;

    /* Calculate the size of the "NAME=value" string. */
    if (ADD_OVERFLOW (var->prefix_len, var->value_len, &new_var_size) ||
        ADD_OVERFLOW (new_var_size, 1u, &new_var_size)) {
      errno = EOVERFLOW;
      goto err;
    }

    /* Allocate and format "NAME=value". */
    new_var = malloc (new_var_size);
    if (new_var == NULL)
      goto err;
    p = new_var;

    memcpy (p, var->prefix, var->prefix_len);
    p += var->prefix_len;

    memcpy (p, var->value, var->value_len);
    p += var->value_len;

    *p++ = '\0';

    /* Push "NAME=value" to the vector. */
    if (string_vector_append (env, new_var) == -1)
      goto err;
    /* Ownership transferred. */
    new_var = NULL;
  }

  /* Append the current environment to "env", but remove "sact_var". */
  for (i = 0; environ[i] != NULL; ++i) {
    for (var = sact_var; var < var_end; ++var) {
      if (strncmp (environ[i], var->prefix, var->prefix_len) == 0)
        break;
    }
    /* Drop known socket activation variable from the current environment. */
    if (var < var_end)
      continue;

    new_var = strdup (environ[i]);
    if (new_var == NULL)
      goto err;

    if (string_vector_append (env, new_var) == -1)
      goto err;
    /* Ownership transferred. */
    new_var = NULL;
  }

  /* The environ must be NULL-terminated. */
  if (string_vector_append (env, NULL) == -1)
    goto err;

  return 0;

 err:
  set_error (errno, "malloc");
  free (new_var);
  string_vector_empty (env);
  return -1;
}


#line 1 "generator/states-connect.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machines related to connecting to the server. */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <assert.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>

extern char **environ;

/* Disable Nagle's algorithm on the socket, but don't fail. */
static void
disable_nagle (int sock)
{
  const int flag = 1;

  setsockopt (sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag);
}

/* Disable SIGPIPE on FreeBSD & MacOS.
 *
 * Does nothing on other platforms, but if those platforms have
 * MSG_NOSIGNAL then we will set that when writing.  (FreeBSD has both.)
 */
static void
disable_sigpipe (int sock)
{
#ifdef SO_NOSIGPIPE
  const int flag = 1;

  setsockopt (sock, SOL_SOCKET, SO_NOSIGPIPE, &flag, sizeof flag);
#endif
}

/* Set unix socket send buffer.
 *
 * Setting send buffer size on the server and client side makes copying
 * from qemu-nbd to qemu-nbd up to 7.6 time faster on macOS and up to
 * 1.6 times faster on Linux.
 *
 * On Linux we must increase net.core.wmem_max to make this chagne
 * effective.
 *
 * TODO: Test on other platforms.
 */
static void
set_buffers (int sock)
{
#if defined(__APPLE__) || defined(__linux__)
  const int value = 2 * 1024 * 1024;
  setsockopt (sock, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
#endif
}


#line 1 "generator/states-issue-command.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for issuing commands (requests) to the server. */


#line 1 "generator/states-magic.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for parsing the initial magic number from the server. */


#line 1 "generator/states-newstyle-opt-export-name.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for ending newstyle handshake with NBD_OPT_EXPORT_NAME. */


#line 1 "generator/states-newstyle-opt-extended-headers.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for negotiating NBD_OPT_EXTENDED_HEADERS. */


#line 1 "generator/states-newstyle-opt-go.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for ending fixed newstyle handshake with NBD_OPT_GO. */


#line 1 "generator/states-newstyle-opt-list.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for sending NBD_OPT_LIST to list exports.
 *
 * This is only reached via nbd_opt_list during opt_mode.
 */


#line 1 "generator/states-newstyle-opt-meta-context.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for negotiating NBD_OPT_SET/LIST_META_CONTEXT. */


#line 1 "generator/states-newstyle-opt-starttls.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for sending NBD_OPT_STARTTLS. */


#line 1 "generator/states-newstyle-opt-structured-reply.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for negotiating NBD_OPT_STRUCTURED_REPLY. */


#line 1 "generator/states-newstyle.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <assert.h>

#include "ascii-ctype.h"
#include "internal.h"

/* Common code for parsing a reply to NBD_OPT_*. */
static int
prepare_for_reply_payload (struct nbd_handle *h, uint32_t opt)
{
  const size_t maxpayload = sizeof h->sbuf.or.payload;
  uint64_t magic;
  uint32_t option;
  uint32_t reply;
  uint32_t len;

  magic = be64toh (h->sbuf.or.option_reply.magic);
  option = be32toh (h->sbuf.or.option_reply.option);
  reply = be32toh (h->sbuf.or.option_reply.reply);
  len = be32toh (h->sbuf.or.option_reply.replylen);
  if (magic != NBD_REP_MAGIC || option != opt) {
    set_error (0, "handshake: invalid option reply magic or option");
    return -1;
  }

  /* Validate lengths that the state machine depends on. */
  switch (reply) {
  case NBD_REP_ACK:
    if (len != 0) {
      set_error (0, "handshake: invalid NBD_REP_ACK option reply length");
      return -1;
    }
    break;
  case NBD_REP_INFO:
    /* Can't enforce an upper bound, thanks to unknown INFOs */
    if (len < sizeof h->sbuf.or.payload.export.info) {
      set_error (0, "handshake: NBD_REP_INFO reply length too small");
      return -1;
    }
    break;
  case NBD_REP_META_CONTEXT:
    if (len <= sizeof h->sbuf.or.payload.context.context ||
        len > sizeof h->sbuf.or.payload.context) {
      set_error (0, "handshake: invalid NBD_REP_META_CONTEXT reply length");
      return -1;
    }
    break;
  }

  /* Read the following payload if it is short enough to fit in the
   * static buffer.  If it's too long, skip it.
   */
  len = be32toh (h->sbuf.or.option_reply.replylen);
  if (len > MAX_REQUEST_SIZE) {
    set_error (0, "handshake: invalid option reply length");
    return -1;
  }
  else if (len <= maxpayload)
    h->rbuf = &h->sbuf.or.payload;
  else
    h->rbuf = NULL;
  h->rlen = len;
  return 0;
}

/* Check an unexpected server reply error.
 *
 * This calls set_error with a descriptive error message and returns
 * 0.  Unless there is a further unexpected error while processing
 * this error, in which case it calls set_error and returns -1.
 */
static int
handle_reply_error (struct nbd_handle *h)
{
  uint32_t reply;
  uint32_t replylen;
  FILE *fp;
  char *s = NULL;
  size_t len = 0;
  int err = 0;

  reply = be32toh (h->sbuf.or.option_reply.reply);
  if (!NBD_REP_IS_ERR (reply)) {
    set_error (0, "handshake: unexpected option reply type %d", reply);
    return -1;
  }

  replylen = be32toh (h->sbuf.or.option_reply.replylen);
  assert (NBD_MAX_STRING < sizeof h->sbuf.or.payload);
  if (replylen > NBD_MAX_STRING) {
    set_error (0, "handshake: option error string too long");
    return -1;
  }

  /* Decode expected errors into a nicer string. */
  fp = open_memstream (&s, &len);
  if (fp == NULL) {
    set_error (errno, "open_memstream");
    return -1;
  }

  switch (reply) {
  case NBD_REP_ERR_UNSUP:
    err = ENOTSUP;
    fprintf (fp, "the operation is not supported by the server");
    break;
  case NBD_REP_ERR_POLICY:
    fprintf (fp, "server policy prevents the operation");
    break;
  case NBD_REP_ERR_PLATFORM:
    fprintf (fp, "the operation is not supported by the server platform");
    break;
  case NBD_REP_ERR_INVALID:
    err = EINVAL;
    fprintf (fp, "the server rejected this operation as invalid");
    break;
  case NBD_REP_ERR_TOO_BIG:
    err = EINVAL;
    fprintf (fp, "the operation is too large to process");
    break;
  case NBD_REP_ERR_TLS_REQD:
    err = ENOTSUP;
    fprintf (fp, "the server requires TLS encryption first");
    break;
  case NBD_REP_ERR_UNKNOWN:
    err = ENOENT;
    fprintf (fp, "the server has no export named '%s'", h->export_name);
    break;
  case NBD_REP_ERR_SHUTDOWN:
    err = ESHUTDOWN;
    fprintf (fp, "the server is shutting down");
    break;
  case NBD_REP_ERR_BLOCK_SIZE_REQD:
    err = EINVAL;
    fprintf (fp, "the server requires specific block sizes");
    break;
  default:
    fprintf (fp, "handshake: unknown reply from the server: 0x%" PRIx32,
             reply);
  }

  if (replylen > 0) {
    /* Since this message comes from the server, take steps to quote it. */
    uint32_t i;
    const unsigned char *msg = (unsigned char *) h->sbuf.or.payload.err_msg;

    fprintf (fp, ": ");
    for (i = 0; i < replylen; ++i) {
      if (ascii_isprint (msg[i]))
        fputc (msg[i], fp);
      else
        fprintf (fp, "\\x%02x", msg[i]);
    }
  }

  fclose (fp);

  set_error (err, "%s", s);
  free (s);

  return 0;
}

/* State machine for parsing the fixed newstyle handshake. */


#line 1 "generator/states-oldstyle.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for parsing the oldstyle handshake. */


#line 1 "generator/states-reply-chunk.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for parsing structured reply chunk payloads from the server. */

#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>

#include "minmax.h"

/* Structured reply must be completely inside the bounds of the
 * requesting command.
 */
static bool
structured_reply_in_bounds (uint64_t offset, uint32_t length,
                            const struct command *cmd)
{
  if (offset < cmd->offset ||
      offset >= cmd->offset + cmd->count ||
      offset + length > cmd->offset + cmd->count) {
    set_error (0, "range of structured reply is out of bounds, "
               "offset=%" PRIu64 ", cmd->offset=%" PRIu64 ", "
               "length=%" PRIu32 ", cmd->count=%" PRIu64 ": "
               "this is likely to be a bug in the NBD server",
               offset, cmd->offset, length, cmd->count);
    return false;
  }

  return true;
}

/* Return true if payload length of block status reply is valid.
 */
static bool
bs_reply_length_ok (uint16_t type, uint32_t length)
{
  size_t prefix_len;
  size_t extent_len;

  if (type == NBD_REPLY_TYPE_BLOCK_STATUS) {
    prefix_len = sizeof (struct nbd_chunk_block_status_32);
    extent_len = sizeof (struct nbd_block_descriptor_32);
  }
  else {
    assert (type == NBD_REPLY_TYPE_BLOCK_STATUS_EXT);
    prefix_len = sizeof (struct nbd_chunk_block_status_64);
    extent_len = sizeof (struct nbd_block_descriptor_64);
  }

  /* At least one descriptor is needed after id prefix */
  if (length < prefix_len + extent_len)
    return false;

  /* There must be an integral number of extents */
  length -= prefix_len;
  if (length % extent_len != 0)
    return false;

  return true;
}


#line 1 "generator/states-reply-simple.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* State machine for parsing simple replies from the server. */


#line 1 "generator/states-reply.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <assert.h>
#include <stddef.h>

#define ASSERT_MEMBER_ALIAS(type, member_a, member_b) \
  STATIC_ASSERT (offsetof (type, member_a) == offsetof (type, member_b) && \
                 sizeof ((type *)NULL)->member_a == \
                 sizeof ((type *)NULL)->member_b, member_alias)

/* State machine for receiving reply messages from the server.
 *
 * Note that we never block while in this sub-group. If there is
 * insufficient data to finish parsing a reply, requiring us to block
 * until POLLIN, we instead track where in the state machine we left
 * off, then return to READY to actually block. Then, on entry to
 * REPLY.START, we can tell if this is the start of a new reply (rlen
 * is 0, stay put), a continuation of the preamble (reply_state is
 * STATE_START, resume with RECV_REPLY), or a continuation from any
 * other location (reply_state contains the state to jump to).
 */

static void
save_reply_state (struct nbd_handle *h)
{
  assert (h->rlen);
  assert (h->reply_state == STATE_START);
  h->reply_state = get_next_state (h);
  assert (h->reply_state != STATE_START);
}


#line 1 "generator/states.c"
/* nbd client library in userspace: state machine
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/* This isn't "real" C code.  It is read by the generator, parsed, and
 * put into generated files.  Also it won't make much sense unless you
 * read the generator state machine and documentation in
 * generator/README.state-machine.md first.
 */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>

#include "minmax.h"

#include "internal.h"

/* Uncomment this to dump received protocol packets to stderr. */
/*#define DUMP_PACKETS 1*/

static int
recv_into_rbuf (struct nbd_handle *h)
{
  ssize_t r;
  void *rbuf;
  size_t rlen;

  /* As a special case h->rbuf is allowed to be NULL, meaning
   * throw away the data.
   *
   * When building with DUMP_PACKETS, it's worth debugging even
   * discarded packets; this makes our stack frame larger, but
   * DUMP_PACKETS is already for developers.  Otherwise, we share a
   * single static sink buffer across all nbd handles; we don't care
   * about thread-safety issues with two clients discarding data at
   * the same time, because we never read the sink.
   */
#ifdef DUMP_PACKETS
  char sink[1024];
#else
  static char sink[BUFSIZ];
#endif

  if (h->rlen == 0)
    return 0;                   /* move to next state */

  if (h->rbuf) {
    rbuf = h->rbuf;
    rlen = h->rlen;
  }
  else {
    rbuf = sink;
    rlen = MIN (h->rlen, sizeof sink);
  }

  r = h->sock->ops->recv (h, h->sock, rbuf, rlen);
  if (r == -1) {
    if (errno == EAGAIN || errno == EWOULDBLOCK)
      return 1;                 /* more data */
    /* sock->ops->recv called set_error already. */
    return -1;
  }
  if (r == 0) {
    set_error (0, "recv: server disconnected unexpectedly");
    return -1;
  }
#ifdef DUMP_PACKETS
  nbd_internal_hexdump (rbuf, r, stderr);
#endif
  h->bytes_received += r;
  if (h->rbuf)
    h->rbuf = (char *)h->rbuf + r;
  h->rlen -= r;
  if (h->rlen == 0)
    return 0;                   /* move to next state */
  else
    return 1;                   /* more data */
}

static int
send_from_wbuf (struct nbd_handle *h)
{
  ssize_t r;

  if (h->wlen == 0)
    goto next_state;
  r = h->sock->ops->send (h, h->sock, h->wbuf, h->wlen, h->wflags);
  if (r == -1) {
    if (errno == EAGAIN || errno == EWOULDBLOCK)
      return 1;                 /* more data */
    /* sock->ops->send called set_error already. */
    return -1;
  }
  h->bytes_sent += r;
  h->wbuf = (char *)h->wbuf + r;
  h->wlen -= r;
  if (h->wlen == 0)
    goto next_state;
  else
    return 1;                   /* more data */

 next_state:
  h->wflags = 0;                /* reset this when moving to next state */
  return 0;                     /* move to next state */
}

/* Forcefully fail any in-flight option */
static void
abort_option (struct nbd_handle *h)
{
  int err = nbd_get_errno () ? : ENOTCONN;

  CALL_CALLBACK (h->opt_cb.completion, &err);
  nbd_internal_free_option (h);
}

/* Forcefully fail any remaining in-flight commands in list */
void
nbd_internal_abort_commands (struct nbd_handle *h, struct command **list)
{
  struct command *next, *cmd;

  for (cmd = *list, *list = NULL; cmd != NULL; cmd = next) {
    bool retire = cmd->type == NBD_CMD_DISC;

    next = cmd->next;
    if (CALLBACK_IS_NOT_NULL (cmd->cb.completion)) {
      int error = cmd->error ? cmd->error : ENOTCONN;
      int r;

      assert (cmd->type != NBD_CMD_DISC);
      r = CALL_CALLBACK (cmd->cb.completion, &error);
      switch (r) {
      case -1:
        if (error)
          cmd->error = error;
        break;
      case 1:
        retire = true;
        break;
      }
    }
    if (cmd->error == 0)
      cmd->error = ENOTCONN;
    if (retire)
      nbd_internal_retire_and_free_command (cmd);
    else {
      cmd->next = NULL;
      if (h->cmds_done_tail)
        h->cmds_done_tail->next = cmd;
      else {
        assert (h->cmds_done == NULL);
        h->cmds_done = cmd;
      }
      h->cmds_done_tail = cmd;
    }
  }
}




#define SET_NEXT_STATE(s) (*blocked = false, *next_state = (s))
#define SET_NEXT_STATE_AND_BLOCK(s) (*next_state = (s))

/* START: Handle after being initially created */
static int
enter_STATE_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
  return 0;
}

#line 1045 "lib/states.c"
int
nbd_internal_enter_STATE_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_START;
  r = enter_STATE_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CONNECT.START: Initial call to connect(2) on the socket */
static int
enter_STATE_CONNECT_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 87 "generator/states-connect.c"

  sa_family_t family;
  int fd, r;

  assert (!h->sock);
  family = h->connaddr.ss_family;
  fd = nbd_internal_socket (family, SOCK_STREAM, 0, true);
  if (fd == -1) {
    SET_NEXT_STATE (STATE_DEAD);
    set_error (errno, "socket");
    return 0;
  }
  h->sock = nbd_internal_socket_create (fd);
  if (!h->sock) {
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }

  disable_nagle (fd);
  disable_sigpipe (fd);
  if (family == AF_UNIX)
    set_buffers (fd);

  r = connect (fd, (struct sockaddr *)&h->connaddr, h->connaddrlen);
  if (r == 0 || (r == -1 && errno == EINPROGRESS))
    return 0;
  assert (r == -1);
#ifdef __linux__
  if (errno == EAGAIN && family == AF_UNIX) {
    /* This can happen on Linux when connecting to a Unix domain
     * socket, if the server's backlog is full.  Unfortunately there
     * is nothing good we can do on the client side when this happens
     * since any solution would involve sleeping or busy-waiting.  The
     * only solution is on the server side, increasing the backlog.
     * But at least improve the error message.
     * https://bugzilla.redhat.com/1925045
     */
    SET_NEXT_STATE (STATE_DEAD);
    set_error (errno, "connect: server backlog overflowed, "
               "see https://bugzilla.redhat.com/1925045");
    return 0;
  }
#endif
  SET_NEXT_STATE (STATE_DEAD);
  set_error (errno, "connect");
  return 0;

}

#line 1125 "lib/states.c"
int
nbd_internal_enter_STATE_CONNECT_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CONNECT_START;
  r = enter_STATE_CONNECT_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CONNECT.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CONNECT.CONNECTING: Connecting to the remote server */
static int
enter_STATE_CONNECT_CONNECTING (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 134 "generator/states-connect.c"

  int status;
  socklen_t len = sizeof status;

  if (getsockopt (h->sock->ops->get_fd (h->sock),
                  SOL_SOCKET, SO_ERROR, &status, &len) == -1) {
    SET_NEXT_STATE (STATE_DEAD);
    set_error (errno, "getsockopt: SO_ERROR");
    return 0;
  }
  /* This checks the status of the original connect call. */
  if (status == 0) {
    SET_NEXT_STATE (STATE_MAGIC_START);
    return 0;
  }
  else {
    SET_NEXT_STATE (STATE_DEAD);
    set_error (status, "connect");
    return 0;
  }

}

#line 1179 "lib/states.c"
int
nbd_internal_enter_STATE_CONNECT_CONNECTING (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CONNECT_CONNECTING;
  r = enter_STATE_CONNECT_CONNECTING (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CONNECT.CONNECTING",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CONNECT_TCP.START: Connect to a remote TCP server */
static int
enter_STATE_CONNECT_TCP_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 155 "generator/states-connect.c"

  int r;

  assert (h->hostname != NULL);
  assert (h->port != NULL);

  if (h->result) {
    freeaddrinfo (h->result);
    h->result = NULL;
  }

  h->connect_errno = 0;

  memset (&h->hints, 0, sizeof h->hints);
  h->hints.ai_family = AF_UNSPEC;
  h->hints.ai_socktype = SOCK_STREAM;
  h->hints.ai_flags = 0;
  h->hints.ai_protocol = 0;

  /* XXX Unfortunately getaddrinfo blocks.  getaddrinfo_a isn't
   * portable and in any case isn't an alternative because it can't be
   * integrated into a main loop.
   */
  r = getaddrinfo (h->hostname, h->port, &h->hints, &h->result);
  if (r != 0) {
    SET_NEXT_STATE (STATE_START);
    set_error (0, "getaddrinfo: hostname \"%s\" port \"%s\": %s",
               h->hostname, h->port, gai_strerror (r));
    return -1;
  }

  h->rp = h->result;
  SET_NEXT_STATE (STATE_CONNECT_TCP_CONNECT);
  return 0;

}

#line 1247 "lib/states.c"
int
nbd_internal_enter_STATE_CONNECT_TCP_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CONNECT_TCP_START;
  r = enter_STATE_CONNECT_TCP_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CONNECT_TCP.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CONNECT_TCP.CONNECT: Initial call to connect(2) on a TCP socket */
static int
enter_STATE_CONNECT_TCP_CONNECT (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 190 "generator/states-connect.c"

  int fd;

  assert (!h->sock);

  if (h->rp == NULL) {
    /* We tried all the results from getaddrinfo without success.
     * Save errno from most recent connect(2) call. XXX
     */
    SET_NEXT_STATE (STATE_START);
    set_error (h->connect_errno,
               "connect: %s:%s: could not connect to remote host",
               h->hostname, h->port);
    return -1;
  }

  fd = nbd_internal_socket (h->rp->ai_family,
                            h->rp->ai_socktype,
                            h->rp->ai_protocol,
                            true);
  if (fd == -1) {
    SET_NEXT_STATE (STATE_CONNECT_TCP_NEXT_ADDRESS);
    return 0;
  }
  h->sock = nbd_internal_socket_create (fd);
  if (!h->sock) {
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }

  disable_nagle (fd);
  disable_sigpipe (fd);

  if (connect (fd, h->rp->ai_addr, h->rp->ai_addrlen) == -1) {
    if (errno != EINPROGRESS) {
      if (h->connect_errno == 0)
        h->connect_errno = errno;
      SET_NEXT_STATE (STATE_CONNECT_TCP_NEXT_ADDRESS);
      return 0;
    }
  }

  SET_NEXT_STATE (STATE_CONNECT_TCP_CONNECTING);
  return 0;

}

#line 1325 "lib/states.c"
int
nbd_internal_enter_STATE_CONNECT_TCP_CONNECT (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CONNECT_TCP_CONNECT;
  r = enter_STATE_CONNECT_TCP_CONNECT (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CONNECT_TCP.CONNECT",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CONNECT_TCP.CONNECTING: Connecting to the remote server over a TCP socket */
static int
enter_STATE_CONNECT_TCP_CONNECTING (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 235 "generator/states-connect.c"

  int status;
  socklen_t len = sizeof status;

  if (getsockopt (h->sock->ops->get_fd (h->sock),
                  SOL_SOCKET, SO_ERROR, &status, &len) == -1) {
    SET_NEXT_STATE (STATE_DEAD);
    set_error (errno, "getsockopt: SO_ERROR");
    return 0;
  }
  /* This checks the status of the original connect call. */
  if (status == 0)
    SET_NEXT_STATE (STATE_MAGIC_START);
  else {
    if (h->connect_errno == 0)
      h->connect_errno = status;
    SET_NEXT_STATE (STATE_CONNECT_TCP_NEXT_ADDRESS);
  }
  return 0;

}

#line 1378 "lib/states.c"
int
nbd_internal_enter_STATE_CONNECT_TCP_CONNECTING (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CONNECT_TCP_CONNECTING;
  r = enter_STATE_CONNECT_TCP_CONNECTING (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CONNECT_TCP.CONNECTING",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CONNECT_TCP.NEXT_ADDRESS: Connecting to the next address over a TCP socket */
static int
enter_STATE_CONNECT_TCP_NEXT_ADDRESS (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 255 "generator/states-connect.c"

  if (h->sock) {
    h->sock->ops->close (h->sock);
    h->sock = NULL;
  }
  if (h->rp)
    h->rp = h->rp->ai_next;
  SET_NEXT_STATE (STATE_CONNECT_TCP_CONNECT);
  return 0;

}

#line 1421 "lib/states.c"
int
nbd_internal_enter_STATE_CONNECT_TCP_NEXT_ADDRESS (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CONNECT_TCP_NEXT_ADDRESS;
  r = enter_STATE_CONNECT_TCP_NEXT_ADDRESS (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CONNECT_TCP.NEXT_ADDRESS",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CONNECT_COMMAND.START: Connect to a subprocess */
static int
enter_STATE_CONNECT_COMMAND_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 265 "generator/states-connect.c"

  enum state next;
  bool parentfd_transferred;
  int sv[2];
  int flags;
  struct socket *sock;
  struct execvpe execvpe_ctx;
  pid_t pid;

  assert (!h->sock);
  assert (h->argv.ptr);
  assert (h->argv.ptr[0]);

  next = STATE_DEAD;
  parentfd_transferred = false;

  if (nbd_internal_socketpair (AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
    set_error (errno, "socketpair");
    goto done;
  }

  /* A process is effectively in an unusable state if any of STDIN_FILENO
   * (fd#0), STDOUT_FILENO (fd#1) and STDERR_FILENO (fd#2) don't exist. If they
   * exist however, then the socket pair created above will not intersect with
   * the fd set { 0, 1, 2 }. This is relevant for the child-side dup2() logic
   * below.
   */
  assert (sv[0] > STDERR_FILENO);
  assert (sv[1] > STDERR_FILENO);

  /* Only the parent-side end of the socket pair must be set to non-blocking,
   * because the child may not be expecting a non-blocking socket.
   */
  flags = fcntl (sv[0], F_GETFL, 0);
  if (flags == -1 ||
      fcntl (sv[0], F_SETFL, flags|O_NONBLOCK) == -1) {
    set_error (errno, "fcntl");
    goto close_socket_pair;
  }

  sock = nbd_internal_socket_create (sv[0]);
  if (!sock)
    /* nbd_internal_socket_create() calls set_error() internally */
    goto close_socket_pair;
  parentfd_transferred = true;

  if (nbd_internal_execvpe_init (&execvpe_ctx, h->argv.ptr[0], h->argv.len) ==
      -1) {
    set_error (errno, "nbd_internal_execvpe_init");
    goto close_high_level_socket;
  }

  pid = fork ();
  if (pid == -1) {
    set_error (errno, "fork");
    goto uninit_execvpe;
  }

  if (pid == 0) {         /* child - run command */
    if (close (sv[0]) == -1) {
      nbd_internal_fork_safe_perror ("close");
      _exit (126);
    }
    if (dup2 (sv[1], STDIN_FILENO) == -1 ||
        dup2 (sv[1], STDOUT_FILENO) == -1) {
      nbd_internal_fork_safe_perror ("dup2");
      _exit (126);
    }
    NBD_INTERNAL_FORK_SAFE_ASSERT (sv[1] != STDIN_FILENO);
    NBD_INTERNAL_FORK_SAFE_ASSERT (sv[1] != STDOUT_FILENO);
    if (close (sv[1]) == -1) {
      nbd_internal_fork_safe_perror ("close");
      _exit (126);
    }

    /* Restore SIGPIPE back to SIG_DFL. */
    if (signal (SIGPIPE, SIG_DFL) == SIG_ERR) {
      nbd_internal_fork_safe_perror ("signal");
      _exit (126);
    }

    (void)nbd_internal_fork_safe_execvpe (&execvpe_ctx, &h->argv, environ);
    nbd_internal_fork_safe_perror (h->argv.ptr[0]);
    if (errno == ENOENT)
      _exit (127);
    else
      _exit (126);
  }

  /* Parent -- we're done; commit. */
  h->pid = pid;
  h->sock = sock;

  /* The sockets are connected already, we can jump directly to
   * receiving the server magic.
   */
  next = STATE_MAGIC_START;

  /* fall through, for releasing the temporaries */

uninit_execvpe:
  nbd_internal_execvpe_uninit (&execvpe_ctx);

close_high_level_socket:
  if (next == STATE_DEAD)
    sock->ops->close (sock);

close_socket_pair:
  assert (next == STATE_DEAD || parentfd_transferred);
  if (!parentfd_transferred)
    close (sv[0]);
  close (sv[1]);

done:
  SET_NEXT_STATE (next);
  return 0;

}

#line 1571 "lib/states.c"
int
nbd_internal_enter_STATE_CONNECT_COMMAND_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CONNECT_COMMAND_START;
  r = enter_STATE_CONNECT_COMMAND_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CONNECT_COMMAND.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CONNECT_SA.START: Connect to a subprocess with systemd socket activation */
static int
enter_STATE_CONNECT_SA_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 180 "generator/states-connect-socket-activation.c"

  enum state next;
  char *tmpdir;
  char *sockpath;
  int s;
  struct sockaddr_un addr;
  struct execvpe execvpe_ctx;
  size_t num_vars;
  struct sact_var sact_var[3];
  size_t pid_ofs;
  string_vector env;
  pid_t pid;

  assert (!h->sock);
  assert (h->argv.ptr);
  assert (h->argv.ptr[0]);

  next = STATE_DEAD;

  /* Use /tmp instead of TMPDIR because we must ensure the path is
   * short enough to store in the sockaddr_un.  On some platforms this
   * may cause problems so we may need to revisit it.  XXX
   */
  tmpdir = strdup ("/tmp/libnbdXXXXXX");
  if (tmpdir == NULL) {
    set_error (errno, "strdup");
    goto done;
  }

  if (mkdtemp (tmpdir) == NULL) {
    set_error (errno, "mkdtemp");
    goto free_tmpdir;
  }

  if (asprintf (&sockpath, "%s/sock", tmpdir) == -1) {
    set_error (errno, "asprintf");
    goto rmdir_tmpdir;
  }

  s = nbd_internal_socket (AF_UNIX, SOCK_STREAM, 0, false);
  if (s == -1) {
    set_error (errno, "socket");
    goto free_sockpath;
  }

  addr.sun_family = AF_UNIX;
  memcpy (addr.sun_path, sockpath, strlen (sockpath) + 1);
  if (bind (s, (struct sockaddr *)&addr, sizeof addr) == -1) {
    set_error (errno, "bind: %s", sockpath);
    goto close_socket;
  }

  if (listen (s, SOMAXCONN) == -1) {
    set_error (errno, "listen");
    goto unlink_sockpath;
  }

  if (nbd_internal_execvpe_init (&execvpe_ctx, h->argv.ptr[0], h->argv.len) ==
      -1) {
    set_error (errno, "nbd_internal_execvpe_init");
    goto unlink_sockpath;
  }

  num_vars = 0;
  SACT_VAR_PUSH (sact_var, &num_vars,
                 "LISTEN_PID=", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", &pid_ofs);
  SACT_VAR_PUSH (sact_var, &num_vars,
                 "LISTEN_FDS=", "1", NULL);
  /* Push LISTEN_FDNAMES unconditionally. This ensures we overwrite any
   * inherited LISTEN_FDNAMES. If "h->sact_name" is NULL, then push
   * "LISTEN_FDNAMES=unknown"; it will have the same effect on the child process
   * as unsetting LISTEN_FDNAMES would (with LISTEN_FDS being set to 1):
   * <https://www.freedesktop.org/software/systemd/man/sd_listen_fds.html>.
   */
  SACT_VAR_PUSH (sact_var, &num_vars,
                 "LISTEN_FDNAMES=",
                 h->sact_name == NULL ? "unknown" : h->sact_name,
                 NULL);
  if (prepare_socket_activation_environment (&env, sact_var, num_vars) == -1)
    /* prepare_socket_activation_environment() calls set_error() internally */
    goto uninit_execvpe;

  pid = fork ();
  if (pid == -1) {
    set_error (errno, "fork");
    goto empty_env;
  }

  if (pid == 0) {         /* child - run command */
    if (s != FIRST_SOCKET_ACTIVATION_FD) {
      if (dup2 (s, FIRST_SOCKET_ACTIVATION_FD) == -1) {
        nbd_internal_fork_safe_perror ("dup2");
        _exit (126);
      }
      if (close (s) == -1) {
        nbd_internal_fork_safe_perror ("close");
        _exit (126);
      }
    }
    else {
      /* We must unset CLOEXEC on the fd.  (dup2 above does this
       * implicitly because CLOEXEC is set on the fd, not on the
       * socket).
       */
      int flags = fcntl (s, F_GETFD, 0);
      if (flags == -1) {
        nbd_internal_fork_safe_perror ("fcntl: F_GETFD");
        _exit (126);
      }
      if (fcntl (s, F_SETFD, (int)(flags & ~(unsigned)FD_CLOEXEC)) == -1) {
        nbd_internal_fork_safe_perror ("fcntl: F_SETFD");
        _exit (126);
      }
    }

    char buf[32];
    const char *v = nbd_internal_fork_safe_itoa (getpid (), buf, sizeof buf);
    NBD_INTERNAL_FORK_SAFE_ASSERT (strlen (v) <= sact_var[pid_ofs].value_len);
    strcpy (env.ptr[pid_ofs] + sact_var[pid_ofs].prefix_len, v);

    /* Restore SIGPIPE back to SIG_DFL. */
    if (signal (SIGPIPE, SIG_DFL) == SIG_ERR) {
      nbd_internal_fork_safe_perror ("signal");
      _exit (126);
    }

    (void)nbd_internal_fork_safe_execvpe (&execvpe_ctx, &h->argv, env.ptr);
    nbd_internal_fork_safe_perror (h->argv.ptr[0]);
    if (errno == ENOENT)
      _exit (127);
    else
      _exit (126);
  }

  /* Parent -- we're done; commit. */
  h->sact_tmpdir = tmpdir;
  h->sact_sockpath = sockpath;
  h->pid = pid;

  h->connaddrlen = sizeof addr;
  memcpy (&h->connaddr, &addr, h->connaddrlen);
  next = STATE_CONNECT_START;

  /* fall through, for releasing the temporaries */

empty_env:
  string_vector_empty (&env);

uninit_execvpe:
  nbd_internal_execvpe_uninit (&execvpe_ctx);

unlink_sockpath:
  if (next == STATE_DEAD)
    unlink (sockpath);

close_socket:
  close (s);

free_sockpath:
  if (next == STATE_DEAD)
    free (sockpath);

rmdir_tmpdir:
  if (next == STATE_DEAD)
    rmdir (tmpdir);

free_tmpdir:
  if (next == STATE_DEAD)
    free (tmpdir);

done:
  SET_NEXT_STATE (next);
  return 0;
}

#line 1777 "lib/states.c"
int
nbd_internal_enter_STATE_CONNECT_SA_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CONNECT_SA_START;
  r = enter_STATE_CONNECT_SA_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CONNECT_SA.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* MAGIC.START: Prepare to receive the magic identification from remote */
static int
enter_STATE_MAGIC_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-magic.c"

  h->rbuf = &h->sbuf;
  h->rlen = 16;
  SET_NEXT_STATE (STATE_MAGIC_RECV_MAGIC);
  return 0;

}

#line 1816 "lib/states.c"
int
nbd_internal_enter_STATE_MAGIC_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_MAGIC_START;
  r = enter_STATE_MAGIC_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "MAGIC.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* MAGIC.RECV_MAGIC: Receive initial magic identification from remote */
static int
enter_STATE_MAGIC_RECV_MAGIC (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 28 "generator/states-magic.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_MAGIC_CHECK_MAGIC);
  }
  return 0;

}

#line 1856 "lib/states.c"
int
nbd_internal_enter_STATE_MAGIC_RECV_MAGIC (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_MAGIC_RECV_MAGIC;
  r = enter_STATE_MAGIC_RECV_MAGIC (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "MAGIC.RECV_MAGIC",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* MAGIC.CHECK_MAGIC: Check magic and version sent by remote */
static int
enter_STATE_MAGIC_CHECK_MAGIC (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 35 "generator/states-magic.c"

  uint64_t version;

  if (be64toh (h->sbuf.new_handshake.nbdmagic) != NBD_MAGIC) {
    SET_NEXT_STATE (STATE_DEAD);
    set_error (0, "handshake: server did not send expected NBD magic");
    return 0;
  }

  version = be64toh (h->sbuf.new_handshake.version);
  if (version == NBD_NEW_VERSION) {
    assert (h->opt_current == 0);
    h->chunks_received++;
    SET_NEXT_STATE (STATE_NEWSTYLE_START);
  }
  else if (version == NBD_OLD_VERSION) {
    h->chunks_received++;
    SET_NEXT_STATE (STATE_OLDSTYLE_START);
  }
  else {
    SET_NEXT_STATE (STATE_DEAD);
    set_error (0, "handshake: server is not either an oldstyle or "
               "fixed newstyle NBD server");
    return 0;
  }
  return 0;

}

#line 1916 "lib/states.c"
int
nbd_internal_enter_STATE_MAGIC_CHECK_MAGIC (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_MAGIC_CHECK_MAGIC;
  r = enter_STATE_MAGIC_CHECK_MAGIC (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "MAGIC.CHECK_MAGIC",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* OLDSTYLE.START: Prepare to receive remainder of oldstyle header */
static int
enter_STATE_OLDSTYLE_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-oldstyle.c"

  /* We've already read the first 16 bytes of the handshake, we must
   * now read the remainder.
   */
  h->rbuf = &h->sbuf.old_handshake;
  h->rlen = sizeof h->sbuf.old_handshake;
  h->rbuf = (char *)h->rbuf + 16;
  h->rlen -= 16;
  SET_NEXT_STATE (STATE_OLDSTYLE_RECV_REMAINING);
  return 0;

}

#line 1960 "lib/states.c"
int
nbd_internal_enter_STATE_OLDSTYLE_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_OLDSTYLE_START;
  r = enter_STATE_OLDSTYLE_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "OLDSTYLE.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* OLDSTYLE.RECV_REMAINING: Receive remainder of oldstyle header */
static int
enter_STATE_OLDSTYLE_RECV_REMAINING (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 33 "generator/states-oldstyle.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_OLDSTYLE_CHECK);
  }
  return 0;

}

#line 2000 "lib/states.c"
int
nbd_internal_enter_STATE_OLDSTYLE_RECV_REMAINING (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_OLDSTYLE_RECV_REMAINING;
  r = enter_STATE_OLDSTYLE_RECV_REMAINING (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "OLDSTYLE.RECV_REMAINING",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* OLDSTYLE.CHECK: Check oldstyle header */
static int
enter_STATE_OLDSTYLE_CHECK (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 40 "generator/states-oldstyle.c"

  uint64_t exportsize;
  uint16_t gflags, eflags;

  /* We already checked the magic and version in MAGIC.CHECK_MAGIC. */
  exportsize = be64toh (h->sbuf.old_handshake.exportsize);
  gflags = be16toh (h->sbuf.old_handshake.gflags);
  eflags = be16toh (h->sbuf.old_handshake.eflags);

  /* Server is unable to upgrade to TLS.  If h->tls is not 'require' (2)
   * then we can continue unencrypted.
   */
  if (h->tls == LIBNBD_TLS_REQUIRE) {
    SET_NEXT_STATE (STATE_DEAD);
    set_error (ENOTSUP, "handshake: server is oldstyle, "
               "but handle TLS setting is 'require' (2)");
    return 0;
  }

  h->gflags = gflags;
  debug (h, "gflags: 0x%" PRIx16, gflags);
  if (gflags) {
    set_error (0, "handshake: oldstyle server should not set gflags");
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }

  if (nbd_internal_set_size_and_flags (h, exportsize, eflags) == -1) {
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }
  nbd_internal_set_payload (h);

  h->protocol = "oldstyle";

  SET_NEXT_STATE (STATE_READY);

  return 0;

}

#line 2072 "lib/states.c"
int
nbd_internal_enter_STATE_OLDSTYLE_CHECK (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_OLDSTYLE_CHECK;
  r = enter_STATE_OLDSTYLE_CHECK (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "OLDSTYLE.CHECK",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.START: Prepare to receive newstyle gflags from remote */
static int
enter_STATE_NEWSTYLE_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 184 "generator/states-newstyle.c"

  if (h->opt_mode) {
    /* NEWSTYLE can be entered multiple times, from MAGIC.CHECK_MAGIC
     * (h->opt_current is 0, run through OPT_STRUCTURED_REPLY for
     * opt_mode, or OPT_GO otherwise) and during various nbd_opt_*
     * calls during NEGOTIATING (h->opt_current is set, run just the
     * states needed).  Each previous state has informed us what we
     * still need to do.
     */
    switch (h->opt_current) {
    case NBD_OPT_GO:
    case NBD_OPT_INFO:
      if ((h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE) == 0)
        SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXPORT_NAME_START);
      else
        SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_START);
      return 0;
    case NBD_OPT_LIST:
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_LIST_START);
      return 0;
    case NBD_OPT_ABORT:
      if ((h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE) == 0) {
        SET_NEXT_STATE (STATE_DEAD);
        set_error (ENOTSUP, "handshake: server is not using fixed newstyle");
        return 0;
      }
      SET_NEXT_STATE (STATE_NEWSTYLE_PREPARE_OPT_ABORT);
      return 0;
    case NBD_OPT_LIST_META_CONTEXT:
    case NBD_OPT_SET_META_CONTEXT:
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_START);
      return 0;
    case NBD_OPT_STRUCTURED_REPLY:
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_START);
      return 0;
    case NBD_OPT_EXTENDED_HEADERS:
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_START);
      return 0;
    case NBD_OPT_STARTTLS:
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_START);
      return 0;
    case 0:
      break;
    default:
      abort ();
    }
  }

  assert (h->opt_current == 0);
  h->rbuf = &h->sbuf;
  h->rlen = sizeof h->sbuf.gflags;
  SET_NEXT_STATE (STATE_NEWSTYLE_RECV_GFLAGS);
  return 0;

}

#line 2159 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_START;
  r = enter_STATE_NEWSTYLE_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.RECV_GFLAGS: Receive newstyle gflags from remote */
static int
enter_STATE_NEWSTYLE_RECV_GFLAGS (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 238 "generator/states-newstyle.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_NEWSTYLE_CHECK_GFLAGS);
  }
  return 0;

}

#line 2199 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_RECV_GFLAGS (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_RECV_GFLAGS;
  r = enter_STATE_NEWSTYLE_RECV_GFLAGS (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.RECV_GFLAGS",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.CHECK_GFLAGS: Check global flags sent by remote */
static int
enter_STATE_NEWSTYLE_CHECK_GFLAGS (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 245 "generator/states-newstyle.c"

  uint32_t cflags;

  h->gflags &= be16toh (h->sbuf.gflags);
  if ((h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE) == 0 &&
      h->tls == LIBNBD_TLS_REQUIRE) {
    SET_NEXT_STATE (STATE_DEAD);
    set_error (ENOTSUP, "handshake: server is not using fixed newstyle, "
               "but handle TLS setting is 'require' (2)");
    return 0;
  }

  if ((h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE) == 0)
    h->protocol = "newstyle";
  else
    h->protocol = "newstyle-fixed";

  cflags = h->gflags;
  h->sbuf.cflags = htobe32 (cflags);
  h->wbuf = &h->sbuf;
  h->wlen = 4;
  SET_NEXT_STATE (STATE_NEWSTYLE_SEND_CFLAGS);
  return 0;

}

#line 2256 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_CHECK_GFLAGS (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_CHECK_GFLAGS;
  r = enter_STATE_NEWSTYLE_CHECK_GFLAGS (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.CHECK_GFLAGS",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.SEND_CFLAGS: Send newstyle client flags to remote */
static int
enter_STATE_NEWSTYLE_SEND_CFLAGS (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 269 "generator/states-newstyle.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    /* Start sending options. */
    if ((h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE) == 0) {
      if (h->opt_mode)
        SET_NEXT_STATE (STATE_NEGOTIATING);
      else
        SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXPORT_NAME_START);
    }
    else
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_START);
  }
  return 0;

}

#line 2305 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_SEND_CFLAGS (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_SEND_CFLAGS;
  r = enter_STATE_NEWSTYLE_SEND_CFLAGS (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.SEND_CFLAGS",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STARTTLS.START: Try to send newstyle NBD_OPT_STARTTLS to upgrade
 * to TLS
 */
static int
enter_STATE_NEWSTYLE_OPT_STARTTLS_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-newstyle-opt-starttls.c"

  assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
  if (h->opt_current == NBD_OPT_STARTTLS)
    assert (h->opt_mode);
  else {
    /* If TLS was not requested we skip this option and go to the next one. */
    if (h->tls == LIBNBD_TLS_DISABLE) {
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_START);
      return 0;
    }
    assert (CALLBACK_IS_NULL (h->opt_cb.completion));
  }

  h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
  h->sbuf.option.option = htobe32 (NBD_OPT_STARTTLS);
  h->sbuf.option.optlen = 0;
  h->chunks_sent++;
  h->wbuf = &h->sbuf;
  h->wlen = sizeof (h->sbuf.option);
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_SEND);
  return 0;

}

#line 2362 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STARTTLS_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STARTTLS_START;
  r = enter_STATE_NEWSTYLE_OPT_STARTTLS_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STARTTLS.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STARTTLS.SEND: Send newstyle NBD_OPT_STARTTLS to upgrade to TLS
 */
static int
enter_STATE_NEWSTYLE_OPT_STARTTLS_SEND (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 44 "generator/states-newstyle-opt-starttls.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->rbuf = &h->sbuf;
    h->rlen = sizeof (h->sbuf.or.option_reply);
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY);
  }
  return 0;

}

#line 2406 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STARTTLS_SEND (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STARTTLS_SEND;
  r = enter_STATE_NEWSTYLE_OPT_STARTTLS_SEND (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STARTTLS.SEND",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STARTTLS.RECV_REPLY: Receive newstyle NBD_OPT_STARTTLS reply */
static int
enter_STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 54 "generator/states-newstyle-opt-starttls.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    if (prepare_for_reply_payload (h, NBD_OPT_STARTTLS) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY_PAYLOAD);
  }
  return 0;

}

#line 2451 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STARTTLS.RECV_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STARTTLS.RECV_REPLY_PAYLOAD: Receive any newstyle
 * NBD_OPT_STARTTLS reply payload
 */
static int
enter_STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 66 "generator/states-newstyle-opt-starttls.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_CHECK_REPLY);
  }
  return 0;

}

#line 2493 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY_PAYLOAD;
  r = enter_STATE_NEWSTYLE_OPT_STARTTLS_RECV_REPLY_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STARTTLS.RECV_REPLY_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STARTTLS.CHECK_REPLY: Check newstyle NBD_OPT_STARTTLS reply */
static int
enter_STATE_NEWSTYLE_OPT_STARTTLS_CHECK_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 73 "generator/states-newstyle-opt-starttls.c"

  uint32_t reply;
  struct socket *new_sock;
  int err = ENOTSUP;

  reply = be32toh (h->sbuf.or.option_reply.reply);
  switch (reply) {
  case NBD_REP_ACK:
    if (h->tls_negotiated) {
      set_error (EPROTO,
                 "handshake: unable to support server accepting TLS twice");
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    nbd_internal_reset_size_and_flags (h);
    h->structured_replies = false;
    h->extended_headers = false;
    h->meta_valid = false;
    new_sock = nbd_internal_crypto_create_session (h, h->sock);
    if (new_sock == NULL) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    h->sock = new_sock;
    if (nbd_internal_crypto_is_reading (h))
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_READ);
    else
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_WRITE);
    return 0;

  case NBD_REP_ERR_INVALID:
    err = EINVAL;
    /* fallthrough */
  default:
    if (handle_reply_error (h) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }

    /* Server refused to upgrade to TLS.  If h->tls is not 'require' (2)
     * then we can continue unencrypted.
     */
    if (h->tls == LIBNBD_TLS_REQUIRE) {
      SET_NEXT_STATE (STATE_NEWSTYLE_PREPARE_OPT_ABORT);
      set_error (ENOTSUP, "handshake: server refused TLS, "
                 "but handle TLS setting is 'require' (2)");
      return 0;
    }

    debug (h, "server refused TLS (%s)",
           reply == NBD_REP_ERR_POLICY ? "policy" :
           reply == NBD_REP_ERR_INVALID ? "invalid request" : "not supported");
    CALL_CALLBACK (h->opt_cb.completion, &err);
    nbd_internal_free_option (h);
    if (h->opt_current == NBD_OPT_STARTTLS)
      SET_NEXT_STATE (STATE_NEGOTIATING);
    else {
      debug (h, "continuing with unencrypted connection");
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_START);
    }
    return 0;
  }
  return 0;

}

#line 2590 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STARTTLS_CHECK_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STARTTLS_CHECK_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_STARTTLS_CHECK_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STARTTLS.CHECK_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_READ: TLS handshake (reading) */
static int
enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_READ (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 137 "generator/states-newstyle-opt-starttls.c"

  int r;

  r = nbd_internal_crypto_handshake (h);
  if (r == -1) {
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }
  if (r == 0) {
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_DONE);
    return 0;
  }
  /* Continue handshake. */
  if (nbd_internal_crypto_is_reading (h))
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_READ);
  else
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_WRITE);
  return 0;

}

#line 2642 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_READ (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_READ;
  r = enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_READ (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_READ",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_WRITE: TLS handshake (writing) */
static int
enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_WRITE (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 156 "generator/states-newstyle-opt-starttls.c"

  int r;

  r = nbd_internal_crypto_handshake (h);
  if (r == -1) {
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }
  if (r == 0) {
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_DONE);
    return 0;
  }
  /* Continue handshake. */
  if (nbd_internal_crypto_is_reading (h))
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_READ);
  else
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_WRITE);
  return 0;

}

#line 2694 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_WRITE (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_WRITE;
  r = enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_WRITE (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_WRITE",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_DONE: TLS handshake complete */
static int
enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_DONE (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 175 "generator/states-newstyle-opt-starttls.c"

  int err = 0;

  /* Finished handshake. */
  h->tls_negotiated = true;
  nbd_internal_crypto_debug_tls_enabled (h);
  CALL_CALLBACK (h->opt_cb.completion, &err);
  nbd_internal_free_option (h);

  /* Continue with option negotiation. */
  if (h->opt_current == NBD_OPT_STARTTLS)
    SET_NEXT_STATE (STATE_NEGOTIATING);
  else
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_START);
  return 0;

}

#line 2743 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_DONE (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_DONE;
  r = enter_STATE_NEWSTYLE_OPT_STARTTLS_TLS_HANDSHAKE_DONE (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STARTTLS.TLS_HANDSHAKE_DONE",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXTENDED_HEADERS.START: Try to negotiate newstyle
 * NBD_OPT_EXTENDED_HEADERS
 */
static int
enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-newstyle-opt-extended-headers.c"

  assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
  if (h->opt_current == NBD_OPT_EXTENDED_HEADERS)
    assert (h->opt_mode);
  else {
    assert (CALLBACK_IS_NULL (h->opt_cb.completion));
    if (!h->request_eh || !h->request_sr) {
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_START);
      return 0;
    }
  }

  h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
  h->sbuf.option.option = htobe32 (NBD_OPT_EXTENDED_HEADERS);
  h->sbuf.option.optlen = htobe32 (0);
  h->chunks_sent++;
  h->wbuf = &h->sbuf;
  h->wlen = sizeof h->sbuf.option;
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_SEND);
  return 0;

}

#line 2799 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_START;
  r = enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXTENDED_HEADERS.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXTENDED_HEADERS.SEND: Send newstyle NBD_OPT_EXTENDED_HEADERS
 * negotiation request
 */
static int
enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_SEND (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 43 "generator/states-newstyle-opt-extended-headers.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->rbuf = &h->sbuf;
    h->rlen = sizeof h->sbuf.or.option_reply;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY);
  }
  return 0;

}

#line 2844 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_SEND (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_SEND;
  r = enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_SEND (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXTENDED_HEADERS.SEND",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXTENDED_HEADERS.RECV_REPLY: Receive newstyle
 * NBD_OPT_EXTENDED_HEADERS option reply
 */
static int
enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 53 "generator/states-newstyle-opt-extended-headers.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    if (prepare_for_reply_payload (h, NBD_OPT_EXTENDED_HEADERS) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY_PAYLOAD);
  }
  return 0;

}

#line 2891 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXTENDED_HEADERS.RECV_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXTENDED_HEADERS.RECV_REPLY_PAYLOAD: Receive any newstyle
 * NBD_OPT_EXTENDED_HEADERS reply payload
 */
static int
enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 65 "generator/states-newstyle-opt-extended-headers.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_CHECK_REPLY);
  }
  return 0;

}

#line 2933 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY_PAYLOAD;
  r = enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_RECV_REPLY_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXTENDED_HEADERS.RECV_REPLY_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXTENDED_HEADERS.CHECK_REPLY: Check newstyle
 * NBD_OPT_EXTENDED_HEADERS option reply
 */
static int
enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_CHECK_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 72 "generator/states-newstyle-opt-extended-headers.c"

  uint32_t reply;
  int err = ENOTSUP;

  reply = be32toh (h->sbuf.or.option_reply.reply);
  switch (reply) {
  case NBD_REP_ACK:
    debug (h, "negotiated extended headers on this connection");
    h->extended_headers = true;
    /* Extended headers trump structured replies, so skip ahead. */
    h->structured_replies = true;
    err = 0;
    break;
  case NBD_REP_ERR_INVALID:
    err = EINVAL;
    /* fallthrough */
  default:
    if (handle_reply_error (h) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }

    if (h->extended_headers)
      debug (h, "extended headers already negotiated");
    else
      debug (h, "extended headers are not supported by this server");
    break;
  }

  /* Next option. */
  if (h->opt_current == NBD_OPT_EXTENDED_HEADERS)
    SET_NEXT_STATE (STATE_NEGOTIATING);
  else
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_START);
  CALL_CALLBACK (h->opt_cb.completion, &err);
  nbd_internal_free_option (h);
  return 0;

}

#line 3006 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_CHECK_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_CHECK_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_EXTENDED_HEADERS_CHECK_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXTENDED_HEADERS.CHECK_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STRUCTURED_REPLY.START: Try to negotiate newstyle
 * NBD_OPT_STRUCTURED_REPLY
 */
static int
enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-newstyle-opt-structured-reply.c"

  assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
  if (h->opt_current == NBD_OPT_STRUCTURED_REPLY)
    assert (h->opt_mode);
  else {
    assert (CALLBACK_IS_NULL (h->opt_cb.completion));
    if (!h->request_sr || h->structured_replies) {
      if (h->opt_mode)
        SET_NEXT_STATE (STATE_NEGOTIATING);
      else
        SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_START);
      return 0;
    }
  }

  h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
  h->sbuf.option.option = htobe32 (NBD_OPT_STRUCTURED_REPLY);
  h->sbuf.option.optlen = htobe32 (0);
  h->chunks_sent++;
  h->wbuf = &h->sbuf;
  h->wlen = sizeof h->sbuf.option;
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_SEND);
  return 0;

}

#line 3065 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_START;
  r = enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STRUCTURED_REPLY.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STRUCTURED_REPLY.SEND: Send newstyle NBD_OPT_STRUCTURED_REPLY
 * negotiation request
 */
static int
enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_SEND (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 46 "generator/states-newstyle-opt-structured-reply.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->rbuf = &h->sbuf;
    h->rlen = sizeof h->sbuf.or.option_reply;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY);
  }
  return 0;

}

#line 3110 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_SEND (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_SEND;
  r = enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_SEND (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STRUCTURED_REPLY.SEND",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STRUCTURED_REPLY.RECV_REPLY: Receive newstyle
 * NBD_OPT_STRUCTURED_REPLY option reply
 */
static int
enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 56 "generator/states-newstyle-opt-structured-reply.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    if (prepare_for_reply_payload (h, NBD_OPT_STRUCTURED_REPLY) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY_PAYLOAD);
  }
  return 0;

}

#line 3157 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STRUCTURED_REPLY.RECV_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STRUCTURED_REPLY.RECV_REPLY_PAYLOAD: Receive any newstyle
 * NBD_OPT_STRUCTURED_REPLY reply payload
 */
static int
enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 68 "generator/states-newstyle-opt-structured-reply.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_CHECK_REPLY);
  }
  return 0;

}

#line 3199 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY_PAYLOAD;
  r = enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_RECV_REPLY_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STRUCTURED_REPLY.RECV_REPLY_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_STRUCTURED_REPLY.CHECK_REPLY: Check newstyle
 * NBD_OPT_STRUCTURED_REPLY option reply
 */
static int
enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_CHECK_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 75 "generator/states-newstyle-opt-structured-reply.c"

  uint32_t reply;
  int err = ENOTSUP;

  reply = be32toh (h->sbuf.or.option_reply.reply);
  switch (reply) {
  case NBD_REP_ACK:
    debug (h, "negotiated structured replies on this connection");
    h->structured_replies = true;
    err = 0;
    break;
  case NBD_REP_ERR_INVALID:
  case NBD_REP_ERR_EXT_HEADER_REQD:
    err = EINVAL;
    /* fallthrough */
  default:
    if (handle_reply_error (h) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }

    if (h->structured_replies)
      debug (h, "structured replies already negotiated");
    else
      debug (h, "structured replies are not supported by this server");
    break;
  }

  /* Next option. */
  if (h->opt_mode)
    SET_NEXT_STATE (STATE_NEGOTIATING);
  else
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_START);
  CALL_CALLBACK (h->opt_cb.completion, &err);
  nbd_internal_free_option (h);
  return 0;

}

#line 3271 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_CHECK_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_CHECK_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_STRUCTURED_REPLY_CHECK_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_STRUCTURED_REPLY.CHECK_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.START: Try to negotiate newstyle
 * NBD_OPT_SET_META_CONTEXT
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-newstyle-opt-meta-context.c"

  size_t i;
  uint32_t len, opt;

  /* This state group is reached from:
   * h->opt_mode == false (h->opt_current == 0):
   *   nbd_connect_*()
   *     -> conditionally use SET, next state OPT_GO for NBD_OPT_GO
   * h->opt_mode == true (h->opt_current matches calling API):
   *   nbd_opt_info()
   *     -> conditionally use SET, next state OPT_GO for NBD_OPT_INFO
   *   nbd_opt_go()
   *     -> conditionally use SET, next state OPT_GO for NBD_OPT_GO
   *   nbd_opt_list_meta_context()
   *     -> unconditionally use LIST, next state NEGOTIATING
   *   nbd_opt_set_meta_context()
   *     -> unconditionally use SET, next state NEGOTIATING
   *
   * If SET is conditional, we skip it if h->request_meta is false, if
   * structured replies were not negotiated, or if no contexts to request.
   * SET then manipulates h->meta_contexts, and sets h->meta_valid on
   * success, while LIST is stateless.
   * If OPT_GO is later successful, it populates h->exportsize and friends,
   * and also sets h->meta_valid if h->request_meta but we skipped SET here.
   * There is a callback if and only if the command is unconditional.
   */
  assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
  if (h->opt_current == NBD_OPT_LIST_META_CONTEXT) {
    assert (h->opt_mode);
    assert (CALLBACK_IS_NOT_NULL (h->opt_cb.fn.context));
    opt = h->opt_current;
  }
  else {
    if (h->opt_current == NBD_OPT_SET_META_CONTEXT)
      assert (CALLBACK_IS_NOT_NULL (h->opt_cb.fn.context));
    else
      assert (CALLBACK_IS_NULL (h->opt_cb.fn.context));
    opt = NBD_OPT_SET_META_CONTEXT;
    if (h->request_meta || h->opt_current == opt) {
      for (i = 0; i < h->meta_contexts.len; ++i)
        free (h->meta_contexts.ptr[i].name);
      meta_vector_reset (&h->meta_contexts);
      h->meta_valid = false;
    }
  }
  if (opt != h->opt_current) {
    if (!h->request_meta || !h->structured_replies ||
        h->request_meta_contexts.len == 0) {
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_START);
      return 0;
    }
    if (nbd_internal_set_querylist (h, NULL) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
  }

  /* Calculate the length of the option request data. */
  len = 4 /* exportname len */ + strlen (h->export_name) + 4 /* nr queries */;
  for (i = 0; i < h->querylist.len; ++i)
    len += 4 /* length of query */ + strlen (h->querylist.ptr[i]);

  h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
  h->sbuf.option.option = htobe32 (opt);
  h->sbuf.option.optlen = htobe32 (len);
  h->chunks_sent++;
  h->wbuf = &h->sbuf;
  h->wlen = sizeof (h->sbuf.option);
  h->wflags = MSG_MORE;
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_SEND);
  return 0;

}

#line 3378 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_START;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.SEND: Send newstyle NBD_OPT_SET_META_CONTEXT */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 94 "generator/states-newstyle-opt-meta-context.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->sbuf.len = htobe32 (strlen (h->export_name));
    h->wbuf = &h->sbuf.len;
    h->wlen = sizeof h->sbuf.len;
    h->wflags = MSG_MORE;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAMELEN);
  }
  return 0;

}

#line 3423 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_SEND;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.SEND",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.SEND_EXPORTNAMELEN: Send newstyle
 * NBD_OPT_SET_META_CONTEXT export name length
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAMELEN (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 106 "generator/states-newstyle-opt-meta-context.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->wbuf = h->export_name;
    h->wlen = strlen (h->export_name);
    h->wflags = MSG_MORE;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAME);
  }
  return 0;

}

#line 3469 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAMELEN (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAMELEN;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAMELEN (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.SEND_EXPORTNAMELEN",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.SEND_EXPORTNAME: Send newstyle
 * NBD_OPT_SET_META_CONTEXT export name
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAME (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 117 "generator/states-newstyle-opt-meta-context.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->sbuf.nrqueries = htobe32 (h->querylist.len);
    h->wbuf = &h->sbuf;
    h->wlen = sizeof h->sbuf.nrqueries;
    h->wflags = MSG_MORE;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_NRQUERIES);
  }
  return 0;

}

#line 3516 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAME (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAME;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_EXPORTNAME (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.SEND_EXPORTNAME",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.SEND_NRQUERIES: Send newstyle
 * NBD_OPT_SET_META_CONTEXT number of queries
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_NRQUERIES (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 129 "generator/states-newstyle-opt-meta-context.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->querynum = 0;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_NEXT_QUERY);
  }
  return 0;

}

#line 3560 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_NRQUERIES (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_NRQUERIES;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_NRQUERIES (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.SEND_NRQUERIES",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.PREPARE_NEXT_QUERY: Prepare to send newstyle
 * NBD_OPT_SET_META_CONTEXT query
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_NEXT_QUERY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 138 "generator/states-newstyle-opt-meta-context.c"

  if (h->querynum >= h->querylist.len) {
    /* end of list of requested meta contexts */
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_FOR_REPLY);
    return 0;
  }
  const char *query = h->querylist.ptr[h->querynum];

  h->sbuf.len = htobe32 (strlen (query));
  h->wbuf = &h->sbuf.len;
  h->wlen = sizeof h->sbuf.len;
  h->wflags = MSG_MORE;
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERYLEN);
  return 0;

}

#line 3610 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_NEXT_QUERY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_NEXT_QUERY;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_NEXT_QUERY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.PREPARE_NEXT_QUERY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.SEND_QUERYLEN: Send newstyle
 * NBD_OPT_SET_META_CONTEXT query length
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERYLEN (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 153 "generator/states-newstyle-opt-meta-context.c"

  const char *query = h->querylist.ptr[h->querynum];

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->wbuf = query;
    h->wlen = strlen (query);
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERY);
  }
  return 0;

}

#line 3657 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERYLEN (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERYLEN;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERYLEN (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.SEND_QUERYLEN",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.SEND_QUERY: Send newstyle NBD_OPT_SET_META_CONTEXT
 * query
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 165 "generator/states-newstyle-opt-meta-context.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->querynum++;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_NEXT_QUERY);
  }
  return 0;

}

#line 3701 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERY;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_SEND_QUERY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.SEND_QUERY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.PREPARE_FOR_REPLY: Prepare to receive newstyle
 * NBD_OPT_SET_META_CONTEXT option reply
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_FOR_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 174 "generator/states-newstyle-opt-meta-context.c"

  h->rbuf = &h->sbuf.or.option_reply;
  h->rlen = sizeof h->sbuf.or.option_reply;
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY);
  return 0;

}

#line 3742 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_FOR_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_FOR_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_FOR_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.PREPARE_FOR_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.RECV_REPLY: Receive newstyle
 * NBD_OPT_SET_META_CONTEXT option reply
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 180 "generator/states-newstyle-opt-meta-context.c"

  uint32_t opt;

  if (h->opt_current == NBD_OPT_LIST_META_CONTEXT)
    opt = h->opt_current;
  else
    opt = NBD_OPT_SET_META_CONTEXT;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    if (prepare_for_reply_payload (h, opt) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY_PAYLOAD);
  }
  return 0;

}

#line 3796 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.RECV_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.RECV_REPLY_PAYLOAD: Receive newstyle
 * NBD_OPT_SET_META_CONTEXT option reply payload
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 199 "generator/states-newstyle-opt-meta-context.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_CHECK_REPLY);
  }
  return 0;

}

#line 3838 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY_PAYLOAD;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_RECV_REPLY_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.RECV_REPLY_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_META_CONTEXT.CHECK_REPLY: Check newstyle
 * NBD_OPT_SET_META_CONTEXT option reply
 */
static int
enter_STATE_NEWSTYLE_OPT_META_CONTEXT_CHECK_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 206 "generator/states-newstyle-opt-meta-context.c"

  uint32_t reply;
  uint32_t len;
  const size_t maxpayload = sizeof h->sbuf.or.payload.context;
  struct meta_context meta_context;
  uint32_t opt;
  int err = 0;

  if (h->opt_current == NBD_OPT_LIST_META_CONTEXT)
    opt = h->opt_current;
  else
    opt = NBD_OPT_SET_META_CONTEXT;

  reply = be32toh (h->sbuf.or.option_reply.reply);
  len = be32toh (h->sbuf.or.option_reply.replylen);
  switch (reply) {
  case NBD_REP_ACK:           /* End of list of replies. */
    if (opt == NBD_OPT_SET_META_CONTEXT)
      h->meta_valid = true;
    if (opt == h->opt_current) {
      SET_NEXT_STATE (STATE_NEGOTIATING);
      CALL_CALLBACK (h->opt_cb.completion, &err);
      nbd_internal_free_option (h);
    }
    else
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_START);
    break;
  case NBD_REP_META_CONTEXT:  /* A context. */
    if (len > maxpayload)
      debug (h, "skipping too large meta context");
    else {
      assert (len > sizeof h->sbuf.or.payload.context.context.context_id);
      meta_context.context_id =
        be32toh (h->sbuf.or.payload.context.context.context_id);
      /* String payload is not NUL-terminated. */
      meta_context.name = strndup (h->sbuf.or.payload.context.str,
                                   len - sizeof meta_context.context_id);
      if (meta_context.name == NULL) {
        set_error (errno, "strdup");
        SET_NEXT_STATE (STATE_DEAD);
        return 0;
      }
      debug (h, "negotiated %s with context ID %" PRIu32,
             meta_context.name, meta_context.context_id);
      if (CALLBACK_IS_NOT_NULL (h->opt_cb.fn.context))
        CALL_CALLBACK (h->opt_cb.fn.context, meta_context.name);
      if (opt == NBD_OPT_LIST_META_CONTEXT)
        free (meta_context.name);
      else if (meta_vector_append (&h->meta_contexts, meta_context) == -1) {
        set_error (errno, "realloc");
        free (meta_context.name);
        SET_NEXT_STATE (STATE_DEAD);
        return 0;
      }
    }
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_META_CONTEXT_PREPARE_FOR_REPLY);
    break;
  default:
    /* Anything else is an error, report it for explicit LIST/SET, ignore it
     * for automatic progress (nbd_connect_*, nbd_opt_info, nbd_opt_go).
     */
    if (handle_reply_error (h) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }

    if (opt == h->opt_current) {
      debug (h, "unexpected response, possibly the server does not "
             "support meta contexts");
      err = ENOTSUP;
      CALL_CALLBACK (h->opt_cb.completion, &err);
      nbd_internal_free_option (h);
      SET_NEXT_STATE (STATE_NEGOTIATING);
    }
    else {
      /* Treat ignored error as success only if list is still empty */
      if (opt == NBD_OPT_SET_META_CONTEXT)
        h->meta_valid = h->meta_contexts.len == 0;
      debug (h, "handshake: ignoring unexpected error from "
             "NBD_OPT_SET_META_CONTEXT (%" PRIu32 ")", reply);
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_START);
    }
    break;
  }
  return 0;

}

#line 3959 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_META_CONTEXT_CHECK_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_META_CONTEXT_CHECK_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_META_CONTEXT_CHECK_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_META_CONTEXT.CHECK_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.START: Try to send newstyle NBD_OPT_GO to end handshake */
static int
enter_STATE_NEWSTYLE_OPT_GO_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-newstyle-opt-go.c"

  uint16_t nrinfos = 0;

  nbd_internal_reset_size_and_flags (h);
  if (h->request_block_size)
    nrinfos++;
  if (h->full_info)
    nrinfos += 2;

  assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
  if (h->opt_current == NBD_OPT_INFO)
    assert (h->opt_mode);
  else if (!h->opt_current) {
    assert (!h->opt_mode);
    assert (CALLBACK_IS_NULL (h->opt_cb.completion));
    h->opt_current = NBD_OPT_GO;
  }
  h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
  h->sbuf.option.option = htobe32 (h->opt_current);
  h->sbuf.option.optlen =
    htobe32 (/* exportnamelen */ 4 + strlen (h->export_name)
             + sizeof nrinfos + 2 * nrinfos);
  h->chunks_sent++;
  h->wbuf = &h->sbuf;
  h->wlen = sizeof h->sbuf.option;
  h->wflags = MSG_MORE;
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_SEND);
  return 0;

}

#line 4021 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_START;
  r = enter_STATE_NEWSTYLE_OPT_GO_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.SEND: Send newstyle NBD_OPT_GO to end handshake */
static int
enter_STATE_NEWSTYLE_OPT_GO_SEND (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 51 "generator/states-newstyle-opt-go.c"

  const uint32_t exportnamelen = strlen (h->export_name);

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->sbuf.len = htobe32 (exportnamelen);
    h->wbuf = &h->sbuf;
    h->wlen = 4;
    h->wflags = MSG_MORE;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_SEND_EXPORTNAMELEN);
  }
  return 0;

}

#line 4068 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_SEND (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_SEND;
  r = enter_STATE_NEWSTYLE_OPT_GO_SEND (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.SEND",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.SEND_EXPORTNAMELEN: Send newstyle NBD_OPT_GO export name
 * length
 */
static int
enter_STATE_NEWSTYLE_OPT_GO_SEND_EXPORTNAMELEN (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 65 "generator/states-newstyle-opt-go.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->wbuf = h->export_name;
    h->wlen = strlen (h->export_name);
    h->wflags = MSG_MORE;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_SEND_EXPORT);
  }
  return 0;

}

#line 4114 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_SEND_EXPORTNAMELEN (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_SEND_EXPORTNAMELEN;
  r = enter_STATE_NEWSTYLE_OPT_GO_SEND_EXPORTNAMELEN (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.SEND_EXPORTNAMELEN",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.SEND_EXPORT: Send newstyle NBD_OPT_GO export name */
static int
enter_STATE_NEWSTYLE_OPT_GO_SEND_EXPORT (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 76 "generator/states-newstyle-opt-go.c"

  uint16_t nrinfos = 0;

  if (h->request_block_size)
    nrinfos++;
  if (h->full_info)
    nrinfos += 2;

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->sbuf.nrinfos = htobe16 (nrinfos);
    h->wbuf = &h->sbuf;
    h->wlen = sizeof h->sbuf.nrinfos;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_SEND_NRINFOS);
  }
  return 0;

}

#line 4165 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_SEND_EXPORT (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_SEND_EXPORT;
  r = enter_STATE_NEWSTYLE_OPT_GO_SEND_EXPORT (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.SEND_EXPORT",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.SEND_NRINFOS: Send newstyle NBD_OPT_GO number of infos */
static int
enter_STATE_NEWSTYLE_OPT_GO_SEND_NRINFOS (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 94 "generator/states-newstyle-opt-go.c"

  uint16_t nrinfos = 0;

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    if (h->request_block_size)
      h->sbuf.info[nrinfos++] = htobe16 (NBD_INFO_BLOCK_SIZE);
    if (h->full_info) {
      h->sbuf.info[nrinfos++] = htobe16 (NBD_INFO_NAME);
      h->sbuf.info[nrinfos++] = htobe16 (NBD_INFO_DESCRIPTION);
    }
    h->wbuf = &h->sbuf;
    h->wlen = sizeof h->sbuf.info[0] * nrinfos;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_SEND_INFO);
  }
  return 0;

}

#line 4216 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_SEND_NRINFOS (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_SEND_NRINFOS;
  r = enter_STATE_NEWSTYLE_OPT_GO_SEND_NRINFOS (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.SEND_NRINFOS",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.SEND_INFO: Send newstyle NBD_OPT_GO request for
 * NBD_INFO_BLOCK_SIZE
 */
static int
enter_STATE_NEWSTYLE_OPT_GO_SEND_INFO (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 112 "generator/states-newstyle-opt-go.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->rbuf = &h->sbuf;
    h->rlen = sizeof h->sbuf.or.option_reply;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_RECV_REPLY);
  }
  return 0;

}

#line 4261 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_SEND_INFO (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_SEND_INFO;
  r = enter_STATE_NEWSTYLE_OPT_GO_SEND_INFO (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.SEND_INFO",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.RECV_REPLY: Receive newstyle NBD_OPT_GO reply */
static int
enter_STATE_NEWSTYLE_OPT_GO_RECV_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 122 "generator/states-newstyle-opt-go.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    if (prepare_for_reply_payload (h, h->opt_current) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_RECV_REPLY_PAYLOAD);
  }
  return 0;

}

#line 4306 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_RECV_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_RECV_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_GO_RECV_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.RECV_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.RECV_REPLY_PAYLOAD: Receive newstyle NBD_OPT_GO reply payload
 */
static int
enter_STATE_NEWSTYLE_OPT_GO_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 134 "generator/states-newstyle-opt-go.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_CHECK_REPLY);
  }
  return 0;

}

#line 4347 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_RECV_REPLY_PAYLOAD;
  r = enter_STATE_NEWSTYLE_OPT_GO_RECV_REPLY_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.RECV_REPLY_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_GO.CHECK_REPLY: Check newstyle NBD_OPT_GO reply */
static int
enter_STATE_NEWSTYLE_OPT_GO_CHECK_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 141 "generator/states-newstyle-opt-go.c"

  uint32_t reply;
  uint32_t len;
  const size_t maxpayload = sizeof h->sbuf.or.payload;
  int err;

  reply = be32toh (h->sbuf.or.option_reply.reply);
  len = be32toh (h->sbuf.or.option_reply.replylen);

  switch (reply) {
  case NBD_REP_INFO:
    if (len > maxpayload) {
      /* See prepare_for_reply_payload, used in RECV_REPLY */
      assert (h->rbuf == NULL);
      debug (h, "skipping large NBD_REP_INFO");
    }
    else {
      uint16_t info;
      uint64_t exportsize;
      uint16_t eflags;
      uint32_t min, pref, max;

      assert (len >= sizeof h->sbuf.or.payload.export.info);
      info = be16toh (h->sbuf.or.payload.export.info);
      switch (info) {
      case NBD_INFO_EXPORT:
        if (len != sizeof h->sbuf.or.payload.export) {
          SET_NEXT_STATE (STATE_DEAD);
          set_error (0, "handshake: incorrect NBD_INFO_EXPORT option reply "
                     "length");
          return 0;
        }
        exportsize = be64toh (h->sbuf.or.payload.export.exportsize);
        eflags = be16toh (h->sbuf.or.payload.export.eflags);
        if (nbd_internal_set_size_and_flags (h, exportsize, eflags) == -1) {
          SET_NEXT_STATE (STATE_DEAD);
          return 0;
        }
        break;
      case NBD_INFO_BLOCK_SIZE:
        if (len != sizeof h->sbuf.or.payload.block_size) {
          SET_NEXT_STATE (STATE_DEAD);
          set_error (0, "handshake: incorrect NBD_INFO_BLOCK_SIZE option "
                     "reply length");
          return 0;
        }
        min = be32toh (h->sbuf.or.payload.block_size.minimum);
        pref = be32toh (h->sbuf.or.payload.block_size.preferred);
        max = be32toh (h->sbuf.or.payload.block_size.maximum);
        if (nbd_internal_set_block_size (h, min, pref, max) == -1) {
          SET_NEXT_STATE (STATE_DEAD);
          return 0;
        }
        break;
      case NBD_INFO_NAME:
        if (len > sizeof h->sbuf.or.payload.name_desc.info + NBD_MAX_STRING ||
            len < sizeof h->sbuf.or.payload.name_desc.info) {
          SET_NEXT_STATE (STATE_DEAD);
          set_error (0, "handshake: incorrect NBD_INFO_NAME option reply "
                     "length");
          return 0;
        }
        free (h->canonical_name);
        h->canonical_name = strndup (h->sbuf.or.payload.name_desc.str, len - 2);
        if (h->canonical_name == NULL) {
          SET_NEXT_STATE (STATE_DEAD);
          set_error (errno, "strndup");
          return 0;
        }
        break;
      case NBD_INFO_DESCRIPTION:
        if (len > sizeof h->sbuf.or.payload.name_desc.info + NBD_MAX_STRING ||
            len < sizeof h->sbuf.or.payload.name_desc.info) {
          SET_NEXT_STATE (STATE_DEAD);
          set_error (0, "handshake: incorrect NBD_INFO_DESCRIPTION option "
                     "reply length");
          return 0;
        }
        free (h->description);
        h->description = strndup (h->sbuf.or.payload.name_desc.str, len - 2);
        if (h->description == NULL) {
          SET_NEXT_STATE (STATE_DEAD);
          set_error (errno, "strndup");
          return 0;
        }
        break;
      default:
        debug (h, "skipping unknown NBD_REP_INFO type %d",
               be16toh (h->sbuf.or.payload.export.info));
        break;
      }
    }
    /* Server is allowed to send any number of NBD_REP_INFO, read next one. */
    h->rbuf = &h->sbuf;
    h->rlen = sizeof (h->sbuf.or.option_reply);
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_GO_RECV_REPLY);
    return 0;
  case NBD_REP_ERR_UNSUP:
    if (h->opt_current == NBD_OPT_GO) {
      debug (h, "server is confused by NBD_OPT_GO, continuing anyway");
      SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXPORT_NAME_START);
      return 0;
    }
    /* fallthrough */
  default:
    if (handle_reply_error (h) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    if (reply == NBD_REP_ERR_UNSUP)
      assert (h->opt_current == NBD_OPT_INFO);

    nbd_internal_reset_size_and_flags (h);
    h->meta_valid = false;
    err = nbd_get_errno () ? : ENOTSUP;
    break;
  case NBD_REP_ACK:
    nbd_internal_set_payload (h);
    err = 0;
    break;
  }

  if (err == 0 && h->opt_current == NBD_OPT_GO)
    SET_NEXT_STATE (STATE_NEWSTYLE_FINISHED);
  else if (h->opt_mode)
    SET_NEXT_STATE (STATE_NEGOTIATING);
  else
    SET_NEXT_STATE (STATE_NEWSTYLE_PREPARE_OPT_ABORT);
  CALL_CALLBACK (h->opt_cb.completion, &err);
  nbd_internal_free_option (h);
  return 0;

}

#line 4512 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_GO_CHECK_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_GO_CHECK_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_GO_CHECK_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_GO.CHECK_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXPORT_NAME.START: Try to send newstyle NBD_OPT_EXPORT_NAME to
 * end handshake
 */
static int
enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-newstyle-opt-export-name.c"

  h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
  h->sbuf.option.option = htobe32 (NBD_OPT_EXPORT_NAME);
  h->sbuf.option.optlen = htobe32 (strlen (h->export_name));
  h->chunks_sent++;
  h->wbuf = &h->sbuf;
  h->wlen = sizeof h->sbuf.option;
  h->wflags = MSG_MORE;
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND);
  return 0;

}

#line 4558 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXPORT_NAME_START;
  r = enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXPORT_NAME.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXPORT_NAME.SEND: Send newstyle NBD_OPT_EXPORT_NAME to end
 * handshake
 */
static int
enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 33 "generator/states-newstyle-opt-export-name.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->wbuf = h->export_name;
    h->wlen = strlen (h->export_name);
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND_EXPORT);
  }
  return 0;

}

#line 4603 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND;
  r = enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXPORT_NAME.SEND",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXPORT_NAME.SEND_EXPORT: Send newstyle NBD_OPT_EXPORT_NAME
 * export name
 */
static int
enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND_EXPORT (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 43 "generator/states-newstyle-opt-export-name.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->rbuf = &h->sbuf;
    h->rlen = sizeof h->sbuf.export_name_reply;
    if ((h->gflags & LIBNBD_HANDSHAKE_FLAG_NO_ZEROES) != 0)
      h->rlen -= sizeof h->sbuf.export_name_reply.zeroes;
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXPORT_NAME_RECV_REPLY);
  }
  return 0;

}

#line 4650 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND_EXPORT (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND_EXPORT;
  r = enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_SEND_EXPORT (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXPORT_NAME.SEND_EXPORT",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXPORT_NAME.RECV_REPLY: Receive newstyle NBD_OPT_EXPORT_NAME
 * reply
 */
static int
enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_RECV_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 55 "generator/states-newstyle-opt-export-name.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_EXPORT_NAME_CHECK_REPLY);
  }
  return 0;

}

#line 4692 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_RECV_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXPORT_NAME_RECV_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_RECV_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXPORT_NAME.RECV_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_EXPORT_NAME.CHECK_REPLY: Check newstyle NBD_OPT_EXPORT_NAME
 * reply
 */
static int
enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_CHECK_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 62 "generator/states-newstyle-opt-export-name.c"

  uint64_t exportsize;
  uint16_t eflags;
  int err = 0;

  exportsize = be64toh (h->sbuf.export_name_reply.exportsize);
  eflags = be16toh (h->sbuf.export_name_reply.eflags);
  if (nbd_internal_set_size_and_flags (h, exportsize, eflags) == -1) {
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }
  nbd_internal_set_payload (h);
  SET_NEXT_STATE (STATE_NEWSTYLE_FINISHED);
  CALL_CALLBACK (h->opt_cb.completion, &err);
  nbd_internal_free_option (h);
  return 0;

}

#line 4744 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_CHECK_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_EXPORT_NAME_CHECK_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_EXPORT_NAME_CHECK_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_EXPORT_NAME.CHECK_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_LIST.START: Start listing exports if in list mode. */
static int
enter_STATE_NEWSTYLE_OPT_LIST_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 25 "generator/states-newstyle-opt-list.c"

  assert (h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE);
  assert (h->opt_mode && h->opt_current == NBD_OPT_LIST);
  assert (CALLBACK_IS_NOT_NULL (h->opt_cb.fn.list));
  h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
  h->sbuf.option.option = htobe32 (NBD_OPT_LIST);
  h->sbuf.option.optlen = 0;
  h->chunks_sent++;
  h->wbuf = &h->sbuf;
  h->wlen = sizeof (h->sbuf.option);
  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_LIST_SEND);
  return 0;

}

#line 4790 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_LIST_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_LIST_START;
  r = enter_STATE_NEWSTYLE_OPT_LIST_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_LIST.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_LIST.SEND: Send newstyle NBD_OPT_LIST to begin listing exports
 */
static int
enter_STATE_NEWSTYLE_OPT_LIST_SEND (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 38 "generator/states-newstyle-opt-list.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    h->rbuf = &h->sbuf;
    h->rlen = sizeof (h->sbuf.or.option_reply);
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_LIST_RECV_REPLY);
  }
  return 0;

}

#line 4834 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_LIST_SEND (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_LIST_SEND;
  r = enter_STATE_NEWSTYLE_OPT_LIST_SEND (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_LIST.SEND",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_LIST.RECV_REPLY: Receive NBD_REP_SERVER reply */
static int
enter_STATE_NEWSTYLE_OPT_LIST_RECV_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 48 "generator/states-newstyle-opt-list.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    if (prepare_for_reply_payload (h, NBD_OPT_LIST) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_LIST_RECV_REPLY_PAYLOAD);
  }
  return 0;

}

#line 4879 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_LIST_RECV_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_LIST_RECV_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_LIST_RECV_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_LIST.RECV_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_LIST.RECV_REPLY_PAYLOAD: Receive NBD_REP_SERVER reply payload */
static int
enter_STATE_NEWSTYLE_OPT_LIST_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 60 "generator/states-newstyle-opt-list.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_NEWSTYLE_OPT_LIST_CHECK_REPLY);
  }
  return 0;

}

#line 4919 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_LIST_RECV_REPLY_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_LIST_RECV_REPLY_PAYLOAD;
  r = enter_STATE_NEWSTYLE_OPT_LIST_RECV_REPLY_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_LIST.RECV_REPLY_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.OPT_LIST.CHECK_REPLY: Check NBD_REP_SERVER reply */
static int
enter_STATE_NEWSTYLE_OPT_LIST_CHECK_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 67 "generator/states-newstyle-opt-list.c"

  const size_t maxpayload = sizeof h->sbuf.or.payload.server;
  uint32_t reply;
  uint32_t len;
  char *tmp;
  int err;

  reply = be32toh (h->sbuf.or.option_reply.reply);
  len = be32toh (h->sbuf.or.option_reply.replylen);
  switch (reply) {
  case NBD_REP_SERVER:
    /* Got one export. */
    if (len >= maxpayload)
      debug (h, "skipping too large export name reply");
    else {
      uint32_t elen;
      const char *name;
      const char *desc;

      /* server.str is oversized for trailing NUL byte convenience */
      h->sbuf.or.payload.server.str[len - 4] = '\0';
      elen = be32toh (h->sbuf.or.payload.server.server.export_name_len);
      if (elen > len - 4 || elen > NBD_MAX_STRING ||
          len - 4 - elen > NBD_MAX_STRING) {
        set_error (0, "invalid export length");
        SET_NEXT_STATE (STATE_DEAD);
        return 0;
      }
      if (elen == len + 4) {
        tmp = NULL;
        name = h->sbuf.or.payload.server.str;
        desc = "";
      }
      else {
        tmp = strndup (h->sbuf.or.payload.server.str, elen);
        if (tmp == NULL) {
          set_error (errno, "strdup");
          SET_NEXT_STATE (STATE_DEAD);
          return 0;
        }
        name = tmp;
        desc = h->sbuf.or.payload.server.str + elen;
      }
      CALL_CALLBACK (h->opt_cb.fn.list, name, desc);
      free (tmp);
    }

    /* Wait for more replies. */
    h->rbuf = &h->sbuf;
    h->rlen = sizeof (h->sbuf.or.option_reply);
    SET_NEXT_STATE (STATE_NEWSTYLE_OPT_LIST_RECV_REPLY);
    return 0;

  case NBD_REP_ACK:
    /* Finished receiving the list. */
    err = 0;
    break;

  default:
    if (handle_reply_error (h) == -1) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    debug (h, "unexpected response, possibly the server does not "
           "support listing exports");
    err = ENOTSUP;
    break;
  }

  CALL_CALLBACK (h->opt_cb.completion, &err);
  nbd_internal_free_option (h);
  SET_NEXT_STATE (STATE_NEGOTIATING);
  return 0;

}

#line 5026 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_OPT_LIST_CHECK_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_OPT_LIST_CHECK_REPLY;
  r = enter_STATE_NEWSTYLE_OPT_LIST_CHECK_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.OPT_LIST.CHECK_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.PREPARE_OPT_ABORT: Prepare to send NBD_OPT_ABORT */
static int
enter_STATE_NEWSTYLE_PREPARE_OPT_ABORT (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 285 "generator/states-newstyle.c"

  assert ((h->gflags & LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE) != 0);
  h->sbuf.option.version = htobe64 (NBD_NEW_VERSION);
  h->sbuf.option.option = htobe32 (NBD_OPT_ABORT);
  h->sbuf.option.optlen = htobe32 (0);
  h->chunks_sent++;
  h->wbuf = &h->sbuf;
  h->wlen = sizeof h->sbuf.option;
  SET_NEXT_STATE (STATE_NEWSTYLE_SEND_OPT_ABORT);
  return 0;

}

#line 5070 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_PREPARE_OPT_ABORT (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_PREPARE_OPT_ABORT;
  r = enter_STATE_NEWSTYLE_PREPARE_OPT_ABORT (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.PREPARE_OPT_ABORT",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.SEND_OPT_ABORT: Send NBD_OPT_ABORT to end negotiation */
static int
enter_STATE_NEWSTYLE_SEND_OPT_ABORT (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 296 "generator/states-newstyle.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:
    SET_NEXT_STATE (STATE_NEWSTYLE_SEND_OPTION_SHUTDOWN);
  }
  return 0;

}

#line 5111 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_SEND_OPT_ABORT (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_SEND_OPT_ABORT;
  r = enter_STATE_NEWSTYLE_SEND_OPT_ABORT (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.SEND_OPT_ABORT",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.SEND_OPTION_SHUTDOWN: Sending write shutdown notification to the
 * remote server
 */
static int
enter_STATE_NEWSTYLE_SEND_OPTION_SHUTDOWN (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 304 "generator/states-newstyle.c"

  /* We don't care if the server replies to NBD_OPT_ABORT.  However,
   * unless we are in opt mode, we want to preserve the error message
   * from a failed OPT_GO by moving to DEAD instead.
   */
  if (h->sock->ops->shut_writes (h, h->sock)) {
    if (h->opt_mode)
      SET_NEXT_STATE (STATE_CLOSED);
    else
      SET_NEXT_STATE (STATE_DEAD);
  }
  return 0;

}

#line 5159 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_SEND_OPTION_SHUTDOWN (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_SEND_OPTION_SHUTDOWN;
  r = enter_STATE_NEWSTYLE_SEND_OPTION_SHUTDOWN (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.SEND_OPTION_SHUTDOWN",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEWSTYLE.FINISHED: Finish off newstyle negotiation */
static int
enter_STATE_NEWSTYLE_FINISHED (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 317 "generator/states-newstyle.c"

  SET_NEXT_STATE (STATE_READY);
  return 0;

}

#line 5196 "lib/states.c"
int
nbd_internal_enter_STATE_NEWSTYLE_FINISHED (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEWSTYLE_FINISHED;
  r = enter_STATE_NEWSTYLE_FINISHED (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEWSTYLE.FINISHED",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* NEGOTIATING: Connection is ready to negotiate an NBD option */
static int
enter_STATE_NEGOTIATING (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
  return 0;
}

#line 5229 "lib/states.c"
int
nbd_internal_enter_STATE_NEGOTIATING (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_NEGOTIATING;
  r = enter_STATE_NEGOTIATING (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "NEGOTIATING",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* READY: Connection is ready to process NBD commands */
static int
enter_STATE_READY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 183 "generator/states.c"

  if (h->cmds_to_issue)
    SET_NEXT_STATE (STATE_ISSUE_COMMAND_START);
  else {
    assert (h->sock);
    if (h->sock->ops->pending && h->sock->ops->pending (h->sock))
      SET_NEXT_STATE (STATE_REPLY_START);
  }
  return 0;

}

#line 5272 "lib/states.c"
int
nbd_internal_enter_STATE_READY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_READY;
  r = enter_STATE_READY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "READY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.START: Begin issuing a command to the remote server */
static int
enter_STATE_ISSUE_COMMAND_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-issue-command.c"

  struct command *cmd;

  assert (h->cmds_to_issue != NULL);
  cmd = h->cmds_to_issue;

  /* Were we interrupted by reading a reply to an earlier command? If
   * so, we can only get back here after a non-blocking jaunt through
   * the REPLY engine, which means we are unlikely to be unblocked for
   * writes yet; we want to advance back to the correct state but
   * without trying a send_from_wbuf that will likely return 1.
   */
  if (h->in_write_shutdown)
    SET_NEXT_STATE_AND_BLOCK (STATE_ISSUE_COMMAND_SEND_WRITE_SHUTDOWN);
  else if (h->wlen) {
    if (h->in_write_payload)
      SET_NEXT_STATE_AND_BLOCK (STATE_ISSUE_COMMAND_SEND_WRITE_PAYLOAD);
    else
      SET_NEXT_STATE_AND_BLOCK (STATE_ISSUE_COMMAND_SEND_REQUEST);
    return 0;
  }

  /* These fields are coincident between req.compact and req.extended */
  h->req.compact.flags = htobe16 (cmd->flags);
  h->req.compact.type = htobe16 (cmd->type);
  h->req.compact.cookie = htobe64 (cmd->cookie);
  h->req.compact.offset = htobe64 (cmd->offset);
  if (h->extended_headers) {
    h->req.extended.magic = htobe32 (NBD_EXTENDED_REQUEST_MAGIC);
    h->req.extended.count = htobe64 (cmd->count);
    h->wlen = sizeof (h->req.extended);
  }
  else {
    assert (cmd->count <= UINT32_MAX);
    h->req.compact.magic = htobe32 (NBD_REQUEST_MAGIC);
    h->req.compact.count = htobe32 (cmd->count);
    h->wlen = sizeof (h->req.compact);
  }
  h->chunks_sent++;
  h->wbuf = &h->req;
  if (cmd->type == NBD_CMD_WRITE || cmd->next)
    h->wflags = MSG_MORE;
  SET_NEXT_STATE (STATE_ISSUE_COMMAND_SEND_REQUEST);
  return 0;

}

#line 5350 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_START;
  r = enter_STATE_ISSUE_COMMAND_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.SEND_REQUEST: Sending a request to the remote server */
static int
enter_STATE_ISSUE_COMMAND_SEND_REQUEST (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 67 "generator/states-issue-command.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_ISSUE_COMMAND_PREPARE_WRITE_PAYLOAD);
  }
  return 0;

}

#line 5390 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_SEND_REQUEST (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_SEND_REQUEST;
  r = enter_STATE_ISSUE_COMMAND_SEND_REQUEST (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.SEND_REQUEST",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.PAUSE_SEND_REQUEST: Interrupt send request to receive an
 * earlier command's reply
 */
static int
enter_STATE_ISSUE_COMMAND_PAUSE_SEND_REQUEST (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 74 "generator/states-issue-command.c"

  assert (h->wlen);
  assert (h->cmds_to_issue != NULL);
  h->in_write_payload = false;
  SET_NEXT_STATE (STATE_REPLY_START);
  return 0;

}

#line 5432 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_PAUSE_SEND_REQUEST (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_PAUSE_SEND_REQUEST;
  r = enter_STATE_ISSUE_COMMAND_PAUSE_SEND_REQUEST (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.PAUSE_SEND_REQUEST",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.PREPARE_WRITE_PAYLOAD: Prepare the write payload to send to the
 * remote server
 */
static int
enter_STATE_ISSUE_COMMAND_PREPARE_WRITE_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 81 "generator/states-issue-command.c"

  struct command *cmd;

  assert (h->cmds_to_issue != NULL);
  cmd = h->cmds_to_issue;
  assert (cmd->cookie == be64toh (h->req.compact.cookie));
  if (cmd->type == NBD_CMD_WRITE ||
      (h->extended_headers && cmd->type == NBD_CMD_BLOCK_STATUS &&
       cmd->flags & NBD_CMD_FLAG_PAYLOAD_LEN)) {
    h->wbuf = cmd->data;
    h->wlen = cmd->count;
    if (cmd->next && cmd->count < 64 * 1024)
      h->wflags = MSG_MORE;
    SET_NEXT_STATE (STATE_ISSUE_COMMAND_SEND_WRITE_PAYLOAD);
  }
  else if (cmd->type == NBD_CMD_DISC) {
    h->in_write_shutdown = true;
    SET_NEXT_STATE (STATE_ISSUE_COMMAND_SEND_WRITE_SHUTDOWN);
  }
  else
    SET_NEXT_STATE (STATE_ISSUE_COMMAND_FINISH);
  return 0;

}

#line 5490 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_PREPARE_WRITE_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_PREPARE_WRITE_PAYLOAD;
  r = enter_STATE_ISSUE_COMMAND_PREPARE_WRITE_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.PREPARE_WRITE_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.SEND_WRITE_PAYLOAD: Sending the write payload to the remote
 * server
 */
static int
enter_STATE_ISSUE_COMMAND_SEND_WRITE_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 104 "generator/states-issue-command.c"

  switch (send_from_wbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 0:  SET_NEXT_STATE (STATE_ISSUE_COMMAND_FINISH);
  }
  return 0;

}

#line 5532 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_SEND_WRITE_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_SEND_WRITE_PAYLOAD;
  r = enter_STATE_ISSUE_COMMAND_SEND_WRITE_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.SEND_WRITE_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.PAUSE_WRITE_PAYLOAD: Interrupt write payload to receive an
 * earlier command's reply
 */
static int
enter_STATE_ISSUE_COMMAND_PAUSE_WRITE_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 111 "generator/states-issue-command.c"

  assert (h->wlen);
  assert (h->cmds_to_issue != NULL);
  h->in_write_payload = true;
  SET_NEXT_STATE (STATE_REPLY_START);
  return 0;

}

#line 5574 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_PAUSE_WRITE_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_PAUSE_WRITE_PAYLOAD;
  r = enter_STATE_ISSUE_COMMAND_PAUSE_WRITE_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.PAUSE_WRITE_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.SEND_WRITE_SHUTDOWN: Sending write shutdown notification to the
 * remote server
 */
static int
enter_STATE_ISSUE_COMMAND_SEND_WRITE_SHUTDOWN (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 118 "generator/states-issue-command.c"

  if (h->sock->ops->shut_writes (h, h->sock))
    SET_NEXT_STATE (STATE_ISSUE_COMMAND_FINISH);
  return 0;

}

#line 5614 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_SEND_WRITE_SHUTDOWN (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_SEND_WRITE_SHUTDOWN;
  r = enter_STATE_ISSUE_COMMAND_SEND_WRITE_SHUTDOWN (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.SEND_WRITE_SHUTDOWN",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.PAUSE_WRITE_SHUTDOWN: Interrupt write shutdown to receive an
 * earlier command's reply
 */
static int
enter_STATE_ISSUE_COMMAND_PAUSE_WRITE_SHUTDOWN (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 123 "generator/states-issue-command.c"

  assert (h->in_write_shutdown);
  SET_NEXT_STATE (STATE_REPLY_START);
  return 0;

}

#line 5654 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_PAUSE_WRITE_SHUTDOWN (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_PAUSE_WRITE_SHUTDOWN;
  r = enter_STATE_ISSUE_COMMAND_PAUSE_WRITE_SHUTDOWN (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.PAUSE_WRITE_SHUTDOWN",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* ISSUE_COMMAND.FINISH: Finish issuing a command */
static int
enter_STATE_ISSUE_COMMAND_FINISH (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 128 "generator/states-issue-command.c"

  struct command *cmd;

  assert (!h->wlen);
  assert (h->cmds_to_issue != NULL);
  cmd = h->cmds_to_issue;
  assert (cmd->cookie == be64toh (h->req.compact.cookie));
  h->cmds_to_issue = cmd->next;
  if (h->cmds_to_issue_tail == cmd)
    h->cmds_to_issue_tail = NULL;
  cmd->next = h->cmds_in_flight;
  h->cmds_in_flight = cmd;
  SET_NEXT_STATE (STATE_READY);
  return 0;

}

#line 5702 "lib/states.c"
int
nbd_internal_enter_STATE_ISSUE_COMMAND_FINISH (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_ISSUE_COMMAND_FINISH;
  r = enter_STATE_ISSUE_COMMAND_FINISH (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "ISSUE_COMMAND.FINISH",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.START: Prepare to receive a reply from the remote server */
static int
enter_STATE_REPLY_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 49 "generator/states-reply.c"

  /* If rlen is non-zero, we are resuming an earlier reply cycle. */
  if (h->rlen > 0) {
    if (h->reply_state != STATE_START) {
      assert (nbd_internal_is_state_processing (h->reply_state));
      SET_NEXT_STATE (h->reply_state);
      h->reply_state = STATE_START;
    }
    else
      SET_NEXT_STATE (STATE_REPLY_RECV_REPLY);
    return 0;
  }

  /* This state is entered when a read notification is received in the
   * READY state.  Therefore we know the socket is readable here.
   * Reading a zero length now would indicate that the socket has been
   * closed by the server and so we should jump to the CLOSED state.
   * However recv_into_rbuf will fail in this case, so test it as a
   * special case.
   */
  ssize_t r;

  /* With extended headers, there is only one size to read, so we can
   * do it all in one syscall.  But for older structured replies, we
   * don't know if we have a simple or structured reply until we read
   * the magic number, requiring a two-part read with
   * CHECK_REPLY_MAGIC below.  This works because the structured_reply
   * header is larger, and because the last member of a simple reply,
   * cookie, is coincident between all three structs (intentional
   * design decisions in the NBD spec when structured and extended
   * replies were added).
   */
  ASSERT_MEMBER_ALIAS (union reply_header, simple.magic, magic);
  ASSERT_MEMBER_ALIAS (union reply_header, simple.cookie, cookie);
  ASSERT_MEMBER_ALIAS (union reply_header, structured.magic, magic);
  ASSERT_MEMBER_ALIAS (union reply_header, structured.cookie, cookie);
  ASSERT_MEMBER_ALIAS (union reply_header, extended.magic, magic);
  ASSERT_MEMBER_ALIAS (union reply_header, extended.cookie, cookie);
  assert (h->reply_cmd == NULL);
  assert (h->rlen == 0);

  h->rbuf = &h->sbuf.reply.hdr;
  if (h->extended_headers)
    h->rlen = sizeof h->sbuf.reply.hdr.extended;
  else
    h->rlen = sizeof h->sbuf.reply.hdr.simple;

  r = h->sock->ops->recv (h, h->sock, h->rbuf, h->rlen);
  if (r == -1) {
    /* In theory this should never happen because when we enter this
     * state we should have notification that the socket is ready to
     * read.  However it can in fact happen when using TLS in
     * conjunction with a slow, remote server.  If it does happen,
     * ignore it - we will reenter this same state again next time the
     * socket is ready to read.
     */
    if (errno == EAGAIN || errno == EWOULDBLOCK)
      return 0;

    /* sock->ops->recv called set_error already. */
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }
  if (r == 0) {
    SET_NEXT_STATE (STATE_CLOSED);
    return 0;
  }
#ifdef DUMP_PACKETS
  nbd_internal_hexdump (h->rbuf, r, stderr);
#endif

  h->bytes_received += r;
  h->rbuf = (char *)h->rbuf + r;
  h->rlen -= r;
  SET_NEXT_STATE (STATE_REPLY_RECV_REPLY);
  return 0;

}

#line 5812 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_START;
  r = enter_STATE_REPLY_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.RECV_REPLY: Receive a reply from the remote server */
static int
enter_STATE_REPLY_RECV_REPLY (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 126 "generator/states-reply.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1: SET_NEXT_STATE (STATE_READY);
    /* Special case: if we have a short read, but got at least far
     * enough to decode the magic number, we can check if the server
     * is matching our expectations. This lets us avoid deadlocking if
     * we are blocked waiting for a 32-byte extended reply, while a
     * buggy server only sent a shorter simple or structured reply.
     * Magic number checks here must be repeated in CHECK_REPLY_MAGIC,
     * since we do not always encounter a short read.
     */
    if (h->extended_headers &&
        (char *)h->rbuf >=
        (char *)&h->sbuf.reply.hdr + sizeof h->sbuf.reply.hdr.magic) {
      uint32_t magic = be32toh (h->sbuf.reply.hdr.magic);
      if (magic != NBD_EXTENDED_REPLY_MAGIC) {
        SET_NEXT_STATE (STATE_DEAD); /* We've probably lost synchronization. */
        set_error (0, "invalid or unexpected reply magic 0x%" PRIx32, magic);
      }
    }
    return 0;
  case 0: SET_NEXT_STATE (STATE_REPLY_CHECK_REPLY_MAGIC);
  }
  return 0;

}

#line 5871 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_RECV_REPLY (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_RECV_REPLY;
  r = enter_STATE_REPLY_RECV_REPLY (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.RECV_REPLY",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHECK_REPLY_MAGIC: Check if the reply has expected magic */
static int
enter_STATE_REPLY_CHECK_REPLY_MAGIC (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 152 "generator/states-reply.c"

  struct command *cmd;
  uint32_t magic;
  uint64_t cookie;

  magic = be32toh (h->sbuf.reply.hdr.magic);
  switch (magic) {
  case NBD_SIMPLE_REPLY_MAGIC:
    if (h->extended_headers)
      /* Server is non-compliant, and we've already read more bytes
       * than a simple header contains; no recovery possible
       */
      goto invalid;

    /* All other payload checks handled in the simple payload engine */
    SET_NEXT_STATE (STATE_REPLY_SIMPLE_REPLY_START);
    break;

  case NBD_STRUCTURED_REPLY_MAGIC:
    if (h->extended_headers)
      /* Server is non-compliant, and we've already read more bytes
       * than a structured header contains; no recovery possible
       */
      goto invalid;

    /* We've only read the bytes that fill hdr.simple.  But
     * hdr.structured is longer, so prepare to read the remaining
     * bytes.  We depend on the memory aliasing in union sbuf to
     * overlay the two reply types.
     */
    STATIC_ASSERT (sizeof h->sbuf.reply.hdr.simple ==
                   offsetof (struct nbd_structured_reply, length),
                   simple_structured_overlap);
    assert (h->rbuf == (char *)&h->sbuf + sizeof h->sbuf.reply.hdr.simple);
    h->rlen = sizeof h->sbuf.reply.hdr.structured;
    h->rlen -= sizeof h->sbuf.reply.hdr.simple;
    SET_NEXT_STATE (STATE_REPLY_RECV_STRUCTURED_REMAINING);
    break;

  case NBD_EXTENDED_REPLY_MAGIC:
    if (!h->extended_headers)
      /* Server is non-compliant.  We could continue reading bytes up
       * to the length of an extended reply to regain sync, but old
       * servers are unlikely to send this magic, so it's just as easy
       * to punt.
       */
      goto invalid;

    /* All other payload checks handled in the chunk payload engine */
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_START);
    break;

  default:
    goto invalid;
  }

  /* NB: This works for all three reply types, even though we haven't
   * finished reading a structured header yet, because the cookie is
   * stored at the same offset.  See the ASSERT_MEMBER_ALIAS above in
   * state REPLY.START that confirmed this.
   */
  h->chunks_received++;
  cookie = be64toh (h->sbuf.reply.hdr.cookie);
  /* Find the command amongst the commands in flight. If the server sends
   * a reply for an unknown cookie, FINISH will diagnose that later.
   */
  for (cmd = h->cmds_in_flight; cmd != NULL; cmd = cmd->next) {
    if (cmd->cookie == cookie)
      break;
  }
  h->reply_cmd = cmd;
  return 0;

 invalid:
  SET_NEXT_STATE (STATE_DEAD); /* We've probably lost synchronization. */
  set_error (0, "invalid or unexpected reply magic 0x%" PRIx32, magic);
#if 0 /* uncomment to see desynchronized data */
  nbd_internal_hexdump (&h->sbuf.reply.hdr.simple,
                        sizeof (h->sbuf.reply.hdr.simple),
                        stderr);
#endif
  return 0;

}

#line 5987 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHECK_REPLY_MAGIC (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHECK_REPLY_MAGIC;
  r = enter_STATE_REPLY_CHECK_REPLY_MAGIC (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHECK_REPLY_MAGIC",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.RECV_STRUCTURED_REMAINING: Receiving the remaining part of a structured
 * reply header
 */
static int
enter_STATE_REPLY_RECV_STRUCTURED_REMAINING (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 235 "generator/states-reply.c"

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0: SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_START);
  }
  return 0;

}

#line 6033 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_RECV_STRUCTURED_REMAINING (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_RECV_STRUCTURED_REMAINING;
  r = enter_STATE_REPLY_RECV_STRUCTURED_REMAINING (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.RECV_STRUCTURED_REMAINING",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.SIMPLE_REPLY.START: Parse a simple reply from the server */
static int
enter_STATE_REPLY_SIMPLE_REPLY_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 22 "generator/states-reply-simple.c"

  struct command *cmd = h->reply_cmd;
  uint32_t error;

  error = be32toh (h->sbuf.reply.hdr.simple.error);

  if (cmd == NULL) {
    /* Unexpected reply.  If error was set or we have structured
     * replies, we know there should be no payload, so the next byte
     * on the wire (if any) will be another reply, and we can let
     * FINISH_COMMAND diagnose/ignore the server bug.  If not, we lack
     * context to know whether the server thinks it was responding to
     * NBD_CMD_READ, so it is safer to move to DEAD now than to risk
     * consuming a server's potential data payload as a reply stream
     * (even though we would be likely to produce a magic number
     * mismatch on the next pass that would also move us to DEAD).
     */
    if (error || h->structured_replies)
      SET_NEXT_STATE (STATE_REPLY_FINISH_COMMAND);
    else {
      uint64_t cookie = be64toh (h->sbuf.reply.hdr.simple.cookie);
      SET_NEXT_STATE (STATE_DEAD);
      set_error (EPROTO,
                 "no matching cookie %" PRIu64 " found for server reply, "
                 "this is probably a server bug", cookie);
    }
    return 0;
  }

  /* Although a server with structured replies negotiated is in error
   * for using a simple reply to NBD_CMD_READ, we can cope with the
   * packet, but diagnose it by failing the read with EPROTO.
   */
  if (cmd->type == NBD_CMD_READ && h->structured_replies) {
    debug (h, "server sent unexpected simple reply for read");
    if (cmd->error == 0)
      cmd->error = EPROTO;
  }

  error = nbd_internal_errno_of_nbd_error (error);
  if (cmd->error == 0)
    cmd->error = error;
  if (error == 0 && cmd->type == NBD_CMD_READ) {
    h->rbuf = cmd->data;
    h->rlen = cmd->count;
    cmd->data_seen += cmd->count;
    SET_NEXT_STATE (STATE_REPLY_SIMPLE_REPLY_RECV_READ_PAYLOAD);
  }
  else {
    SET_NEXT_STATE (STATE_REPLY_FINISH_COMMAND);
  }
  return 0;

}

#line 6119 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_SIMPLE_REPLY_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_SIMPLE_REPLY_START;
  r = enter_STATE_REPLY_SIMPLE_REPLY_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.SIMPLE_REPLY.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.SIMPLE_REPLY.RECV_READ_PAYLOAD: Receiving the read payload for a simple
 * reply
 */
static int
enter_STATE_REPLY_SIMPLE_REPLY_RECV_READ_PAYLOAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 75 "generator/states-reply-simple.c"

  struct command *cmd = h->reply_cmd;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    /* guaranteed by START */
    assert (cmd);
    if (CALLBACK_IS_NOT_NULL (cmd->cb.fn.chunk)) {
      int error = cmd->error;

      if (CALL_CALLBACK (cmd->cb.fn.chunk,
                         cmd->data, cmd->count,
                         cmd->offset, LIBNBD_READ_DATA,
                         &error) == -1)
        cmd->error = error ? error : EPROTO;
    }

    SET_NEXT_STATE (STATE_REPLY_FINISH_COMMAND);
  }
  return 0;

}

#line 6180 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_SIMPLE_REPLY_RECV_READ_PAYLOAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_SIMPLE_REPLY_RECV_READ_PAYLOAD;
  r = enter_STATE_REPLY_SIMPLE_REPLY_RECV_READ_PAYLOAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.SIMPLE_REPLY.RECV_READ_PAYLOAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.START: Start parsing a chunk reply payload from the server
 */
static int
enter_STATE_REPLY_CHUNK_REPLY_START (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 79 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint16_t flags, type;
  uint64_t length;
  uint64_t offset = -1;

  flags = be16toh (h->sbuf.reply.hdr.structured.flags);
  type = be16toh (h->sbuf.reply.hdr.structured.type);
  if (h->extended_headers) {
    length = be64toh (h->sbuf.reply.hdr.extended.length);
    offset = be64toh (h->sbuf.reply.hdr.extended.offset);
  }
  else
    length = be32toh (h->sbuf.reply.hdr.structured.length);

  /* Reject a server that replies with too much information, but don't
   * reject a single structured reply to NBD_CMD_READ on the largest
   * size we were willing to send. The most likely culprit is a server
   * that replies with block status with way too many extents, but any
   * oversized reply is going to take long enough to resync that it is
   * not worth keeping the connection alive.
   */
  if (length > MAX_REQUEST_SIZE + sizeof h->sbuf.reply.payload.offset_data) {
    set_error (0, "invalid server reply length %" PRIu64, length);
    SET_NEXT_STATE (STATE_DEAD);
    return 0;
  }

  /* Skip an unexpected structured reply, including to an unknown cookie. */
  if (cmd == NULL || !h->structured_replies ||
      (h->extended_headers && offset != cmd->offset))
    goto resync;
  h->payload_left = length;

  switch (type) {
  case NBD_REPLY_TYPE_NONE:
    if (length != 0 || !(flags & NBD_REPLY_FLAG_DONE))
      goto resync;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_FINISH);
    break;

  case NBD_REPLY_TYPE_OFFSET_DATA:
    /* The spec states that 0-length requests are unspecified, but
     * 0-length replies are broken. Still, it's easy enough to support
     * them as an extension, so we use < instead of <=.
     */
    if (cmd->type != NBD_CMD_READ ||
        length < sizeof h->sbuf.reply.payload.offset_data)
      goto resync;
    h->rbuf = &h->sbuf.reply.payload.offset_data;
    h->rlen = sizeof h->sbuf.reply.payload.offset_data;
    h->payload_left -= h->rlen;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA);
    break;

  case NBD_REPLY_TYPE_OFFSET_HOLE:
    if (cmd->type != NBD_CMD_READ ||
        length != sizeof h->sbuf.reply.payload.offset_hole)
      goto resync;
    h->rbuf = &h->sbuf.reply.payload.offset_hole;
    h->rlen = sizeof h->sbuf.reply.payload.offset_hole;
    h->payload_left -= h->rlen;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_HOLE);
    break;

  case NBD_REPLY_TYPE_BLOCK_STATUS:
  case NBD_REPLY_TYPE_BLOCK_STATUS_EXT:
    if (cmd->type != NBD_CMD_BLOCK_STATUS ||
        !h->meta_valid || h->meta_contexts.len == 0 ||
        !bs_reply_length_ok (type, length))
      goto resync;
    ASSERT_MEMBER_ALIAS (struct command_cb, fn.extent32, fn.extent64);
    assert (CALLBACK_IS_NOT_NULL (cmd->cb.fn.extent32));
    if (h->extended_headers != (type == NBD_REPLY_TYPE_BLOCK_STATUS_EXT)) {
      debug (h, "wrong block status reply type detected, "
             "this is probably a server bug");
      if (cmd->error == 0)
        cmd->error = EPROTO;
    }
    /* Start by reading the context ID. */
    h->rbuf = &h->sbuf.reply.payload;
    if (type == NBD_REPLY_TYPE_BLOCK_STATUS)
      h->rlen = sizeof h->sbuf.reply.payload.bs_hdr_32;
    else
      h->rlen = sizeof h->sbuf.reply.payload.bs_hdr_64;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RECV_BS_HEADER);
    break;

  default:
    if (NBD_REPLY_TYPE_IS_ERR (type)) {
      /* Any payload shorter than uint32_t cannot even carry an errno
       * value; anything longer, even if it is not long enough to be
       * compliant, will favor the wire error over EPROTO during more
       * length checks in RECV_ERROR_MESSAGE and RECV_ERROR_TAIL.
       */
      if (length < sizeof h->sbuf.reply.payload.error.error.error)
        goto resync;
      h->rbuf = &h->sbuf.reply.payload.error.error;
      h->rlen = MIN (length, sizeof h->sbuf.reply.payload.error.error);
      SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RECV_ERROR);
    }
    else
      goto resync;
    break;
  }
  return 0;

 resync:
  h->rbuf = NULL;
  h->rlen = h->payload_left;
  h->payload_left = 0;
  SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RESYNC);
  return 0;

}

#line 6328 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_START (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_START;
  r = enter_STATE_REPLY_CHUNK_REPLY_START (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.START",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RECV_ERROR: Receive a chunk reply error header */
static int
enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 193 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint32_t length, msglen, error;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    length = h->payload_left;
    h->payload_left -= MIN (length, sizeof h->sbuf.reply.payload.error.error);
    assert (length >= sizeof h->sbuf.reply.payload.error.error.error);
    assert (cmd);

    if (length < sizeof h->sbuf.reply.payload.error.error)
      goto resync;

    msglen = be16toh (h->sbuf.reply.payload.error.error.len);
    if (msglen > h->payload_left ||
        msglen > sizeof h->sbuf.reply.payload.error.msg)
      goto resync;

    h->rbuf = h->sbuf.reply.payload.error.msg;
    h->rlen = msglen;
    h->payload_left -= h->rlen;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RECV_ERROR_MESSAGE);
  }
  return 0;

 resync:
  /* Favor the error packet's errno over RESYNC's EPROTO. */
  error = be32toh (h->sbuf.reply.payload.error.error.error);
  if (cmd->error == 0)
    cmd->error = nbd_internal_errno_of_nbd_error (error);
  h->rbuf = NULL;
  h->rlen = h->payload_left;
  h->payload_left = 0;
  SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RESYNC);
  return 0;

}

#line 6403 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RECV_ERROR;
  r = enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RECV_ERROR",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RECV_ERROR_MESSAGE: Receive a chunk reply error message */
static int
enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR_MESSAGE (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 235 "generator/states-reply-chunk.c"

  uint32_t msglen;
  uint16_t type;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    msglen = be16toh (h->sbuf.reply.payload.error.error.len);
    type = be16toh (h->sbuf.reply.hdr.structured.type);

    if (msglen)
      debug (h, "structured error server message: %.*s", (int)msglen,
             h->sbuf.reply.payload.error.msg);

    /* Special case two specific errors; silently ignore tail for all others */
    h->rbuf = NULL;
    h->rlen = h->payload_left;
    switch (type) {
    case NBD_REPLY_TYPE_ERROR:
      if (h->payload_left != 0)
        debug (h, "ignoring unexpected slop after error message, "
               "the server may have a bug");
      break;
    case NBD_REPLY_TYPE_ERROR_OFFSET:
      if (h->payload_left != sizeof h->sbuf.reply.payload.error.offset)
        debug (h, "unable to safely extract error offset, "
               "the server may have a bug");
      else
        h->rbuf = &h->sbuf.reply.payload.error.offset;
      break;
    }
    h->payload_left = 0;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RECV_ERROR_TAIL);
  }
  return 0;

}

#line 6476 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR_MESSAGE (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RECV_ERROR_MESSAGE;
  r = enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR_MESSAGE (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RECV_ERROR_MESSAGE",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RECV_ERROR_TAIL: Receive a chunk reply error tail */
static int
enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR_TAIL (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 275 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint32_t error;
  uint16_t type;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    error = be32toh (h->sbuf.reply.payload.error.error.error);
    type = be16toh (h->sbuf.reply.hdr.structured.type);

    assert (cmd); /* guaranteed by CHECK */

    /* The spec requires the server to send a non-zero error */
    error = nbd_internal_errno_of_nbd_error (error);
    if (error == 0) {
      debug (h, "server forgot to set error; using EPROTO");
      error = EPROTO;
    }

    /* Sanity check that any error offset is in range, then invoke
     * user callback if present.  Ignore the offset if it was bogus.
     */
    if (type == NBD_REPLY_TYPE_ERROR_OFFSET && h->rbuf) {
      uint64_t offset = be64toh (h->sbuf.reply.payload.error.offset);
      if (structured_reply_in_bounds (offset, 0, cmd) &&
          cmd->type == NBD_CMD_READ &&
          CALLBACK_IS_NOT_NULL (cmd->cb.fn.chunk)) {
        int scratch = error;

        /* Different from successful reads: inform the callback about the
         * current error rather than any earlier one. If the callback fails
         * without setting errno, then use the server's error below.
         */
        if (CALL_CALLBACK (cmd->cb.fn.chunk,
                           (char *)cmd->data + (offset - cmd->offset),
                           0, offset, LIBNBD_READ_ERROR,
                           &scratch) == -1)
          if (cmd->error == 0)
            cmd->error = scratch;
      }
      else
        debug (h, "no use for error offset %" PRIu64, offset);
    }

    /* Preserve first error encountered */
    if (cmd->error == 0)
      cmd->error = error;

    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_FINISH);
  }
  return 0;

}

#line 6566 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR_TAIL (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RECV_ERROR_TAIL;
  r = enter_STATE_REPLY_CHUNK_REPLY_RECV_ERROR_TAIL (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RECV_ERROR_TAIL",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RECV_OFFSET_DATA: Receive a chunk reply offset-data header
 */
static int
enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 332 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint64_t offset;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    offset = be64toh (h->sbuf.reply.payload.offset_data.offset);

    assert (cmd); /* guaranteed by CHECK */
    assert (cmd->data && cmd->type == NBD_CMD_READ);

    /* Is the data within bounds? */
    if (! structured_reply_in_bounds (offset, h->payload_left, cmd)) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    if (cmd->data_seen <= cmd->count)
      cmd->data_seen += h->payload_left;
    /* Now this is the byte offset in the read buffer. */
    offset -= cmd->offset;

    /* Set up to receive the data directly to the user buffer. */
    h->rbuf = (char *)cmd->data + offset;
    h->rlen = h->payload_left;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA_DATA);
  }
  return 0;

}

#line 6633 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA;
  r = enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RECV_OFFSET_DATA",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RECV_OFFSET_DATA_DATA: Receive a chunk reply offset-data
 * block of data
 */
static int
enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA_DATA (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 365 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint64_t offset;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    offset = be64toh (h->sbuf.reply.payload.offset_data.offset);

    assert (cmd); /* guaranteed by CHECK */
    if (CALLBACK_IS_NOT_NULL (cmd->cb.fn.chunk)) {
      int error = cmd->error;

      if (CALL_CALLBACK (cmd->cb.fn.chunk,
                         (char *)cmd->data + (offset - cmd->offset),
                         h->payload_left, offset,
                         LIBNBD_READ_DATA, &error) == -1)
        if (cmd->error == 0)
          cmd->error = error ? error : EPROTO;
    }
    h->payload_left = 0;

    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_FINISH);
  }
  return 0;

}

#line 6698 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA_DATA (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA_DATA;
  r = enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_DATA_DATA (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RECV_OFFSET_DATA_DATA",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RECV_OFFSET_HOLE: Receive a chunk reply offset-hole header
 */
static int
enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_HOLE (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 395 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint64_t offset;
  uint32_t length;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    offset = be64toh (h->sbuf.reply.payload.offset_hole.offset);
    length = be32toh (h->sbuf.reply.payload.offset_hole.length);

    assert (cmd); /* guaranteed by CHECK */
    assert (cmd->data && cmd->type == NBD_CMD_READ);

    /* Is the data within bounds? */
    if (! structured_reply_in_bounds (offset, length, cmd)) {
      SET_NEXT_STATE (STATE_DEAD);
      return 0;
    }
    if (cmd->data_seen <= cmd->count)
      cmd->data_seen += length;
    /* Now this is the byte offset in the read buffer. */
    offset -= cmd->offset;

    /* The spec states that 0-length requests are unspecified, but
     * 0-length replies are broken. Still, it's easy enough to support
     * them as an extension, and this works even when length == 0.
     */
    if (!cmd->initialized)
      memset ((char *)cmd->data + offset, 0, length);
    if (CALLBACK_IS_NOT_NULL (cmd->cb.fn.chunk)) {
      int error = cmd->error;

      if (CALL_CALLBACK (cmd->cb.fn.chunk,
                         (char *)cmd->data + offset, length,
                         cmd->offset + offset,
                         LIBNBD_READ_HOLE, &error) == -1)
        if (cmd->error == 0)
          cmd->error = error ? error : EPROTO;
    }

    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_FINISH);
  }
  return 0;

}

#line 6781 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_HOLE (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_HOLE;
  r = enter_STATE_REPLY_CHUNK_REPLY_RECV_OFFSET_HOLE (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RECV_OFFSET_HOLE",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RECV_BS_HEADER: Receive header of a chunk reply
 * block-status payload
 */
static int
enter_STATE_REPLY_CHUNK_REPLY_RECV_BS_HEADER (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 444 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint16_t type;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    type = be16toh (h->sbuf.reply.hdr.structured.type);

    assert (cmd); /* guaranteed by CHECK */
    assert (cmd->type == NBD_CMD_BLOCK_STATUS);
    assert (bs_reply_length_ok (type, h->payload_left));
    STATIC_ASSERT (sizeof (struct nbd_block_descriptor_32) ==
                   2 * sizeof *h->bs_cooked.narrow,
                   _block_desc_is_multiple_of_bs_entry);
    ASSERT_MEMBER_ALIAS (union chunk_payload, bs_hdr_32.context_id,
                         bs_hdr_64.context_id);

    if (type == NBD_REPLY_TYPE_BLOCK_STATUS) {
      h->payload_left -= sizeof h->sbuf.reply.payload.bs_hdr_32;
      assert (h->payload_left % sizeof *h->bs_raw.narrow == 0);
      h->bs_count = h->payload_left / sizeof *h->bs_raw.narrow;
    }
    else {
      assert (type == NBD_REPLY_TYPE_BLOCK_STATUS_EXT);
      h->payload_left -= sizeof h->sbuf.reply.payload.bs_hdr_64;
      assert (h->payload_left % sizeof *h->bs_raw.wide == 0);
      h->bs_count = h->payload_left / sizeof *h->bs_raw.wide;
      if (h->bs_count != be32toh (h->sbuf.reply.payload.bs_hdr_64.count)) {
        h->rbuf = NULL;
        h->rlen = h->payload_left;
        h->payload_left = 0;
        SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RESYNC);
        return 0;
      }
    }

    free (h->bs_raw.storage);
    free (h->bs_cooked.storage);
    h->bs_raw.storage = malloc (h->payload_left);
    if (cmd->cb.wide)
      h->bs_cooked.storage = malloc (h->bs_count * sizeof *h->bs_cooked.wide);
    else
      h->bs_cooked.storage = malloc (2 * h->bs_count *
                                     sizeof *h->bs_cooked.narrow);
    if (h->bs_raw.storage == NULL || h->bs_cooked.storage == NULL) {
      SET_NEXT_STATE (STATE_DEAD);
      set_error (errno, "malloc");
      free (h->bs_raw.storage);
      free (h->bs_cooked.storage);
      h->bs_raw.storage = NULL;
      h->bs_cooked.storage = NULL;
      return 0;
    }

    h->rbuf = h->bs_raw.storage;
    h->rlen = h->payload_left;
    h->payload_left = 0;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_RECV_BS_ENTRIES);
  }
  return 0;

}

#line 6882 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RECV_BS_HEADER (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RECV_BS_HEADER;
  r = enter_STATE_REPLY_CHUNK_REPLY_RECV_BS_HEADER (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RECV_BS_HEADER",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RECV_BS_ENTRIES: Receive entries array of chunk reply
 * block-status payload
 */
static int
enter_STATE_REPLY_CHUNK_REPLY_RECV_BS_ENTRIES (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 510 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint16_t type;
  size_t i;
  uint32_t context_id;
  int error;
  const char *name;
  uint64_t orig_len, len, flags;
  uint64_t total, cap;
  bool stop;
  int ret;

  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    type = be16toh (h->sbuf.reply.hdr.structured.type);

    assert (cmd); /* guaranteed by CHECK */
    assert (cmd->type == NBD_CMD_BLOCK_STATUS);
    assert (CALLBACK_IS_NOT_NULL (cmd->cb.fn.extent32));
    assert (h->bs_count && h->bs_raw.storage);
    assert (h->meta_valid);

    /* Look up the context ID. Depends on ASSERT_MEMBER_ALIAS above. */
    context_id = be32toh (h->sbuf.reply.payload.bs_hdr_32.context_id);
    for (i = 0; i < h->meta_contexts.len; ++i)
      if (context_id == h->meta_contexts.ptr[i].context_id)
        break;

    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_FINISH);
    if (i == h->meta_contexts.len) {
      /* Emit a debug message, but ignore it. */
      debug (h, "server sent unexpected meta context ID %" PRIu32,
             context_id);
      break;
    }

    /* Be careful to avoid arithmetic overflow, even when the user
     * disabled LIBNBD_STRICT_BOUNDS to pass a suspect offset, or the
     * server returns suspect lengths or advertised exportsize larger
     * than 63 bits.  We guarantee that callbacks will not see a
     * length exceeding INT64_MAX or the advertised h->exportsize.
     */
    name = h->meta_contexts.ptr[i].name;
    total = cap = 0;
    if (cmd->offset <= h->exportsize)
      cap = h->exportsize - cmd->offset;

    /* Need to byte-swap the entries returned into the callback size
     * requested by the caller.  The NBD protocol allows truncation as
     * long as progress is made; the client cannot tell the difference
     * between a server's truncation or if we truncate on a length we
     * don't like.  We stop iterating on a zero-length extent (error
     * only if it is the first extent), on an extent beyond the
     * exportsize (unconditional error after truncating to
     * exportsize), and on an extent exceeding a callback length limit
     * (no error, and to simplify alignment, we truncate to 64M before
     * the limit); but we do not diagnose issues with the server's
     * length alignments, flag values, nor compliance with the REQ_ONE
     * command flag.
     */
    for (i = 0, stop = false; i < h->bs_count && !stop; ++i) {
      if (type == NBD_REPLY_TYPE_BLOCK_STATUS) {
        orig_len = len = be32toh (h->bs_raw.narrow[i].length);
        flags = be32toh (h->bs_raw.narrow[i].status_flags);
      }
      else {
        orig_len = len = be64toh (h->bs_raw.wide[i].length);
        if (len > INT64_MAX) {
          /* Pick an aligned value rather than overflowing 64-bit
           * callback; this does not require an error.
           */
          stop = true;
          len = INT64_MAX + 1ULL - MAX_REQUEST_SIZE;
        }
        if (len > UINT32_MAX && !cmd->cb.wide) {
          /* Pick an aligned value rather than overflowing 32-bit
           * callback; this does not require an error.
           */
          stop = true;
          len = (uint32_t)-MAX_REQUEST_SIZE;
        }
        flags = be64toh (h->bs_raw.wide[i].status_flags);
        if (flags > UINT32_MAX && !cmd->cb.wide) {
          stop = true;
          if (i > 0)
            break; /* Skip this and later extents; we already made progress */
          /* Expose this extent as an error; we made no progress */
          cmd->error = cmd->error ? : EOVERFLOW;
          flags = (uint32_t)flags;
        }
      }

      assert (total <= cap);
      if (len > cap - total) {
        /* Truncate and expose this extent as an error */
        len = cap - total;
        stop = true;
        cmd->error = cmd->error ? : EPROTO;
      }
      if (len == 0) {
        stop = true;
        if (i > 0)
          break; /* Skip this and later extents; we already made progress */
        /* Expose this extent as an error; we made no progress */
        cmd->error = cmd->error ? : EPROTO;
      }
      total += len;
      if (cmd->cb.wide) {
        h->bs_cooked.wide[i].length = len;
        h->bs_cooked.wide[i].flags = flags;
      }
      else {
        assert ((len | flags) <= UINT32_MAX);
        h->bs_cooked.narrow[i * 2] = len;
        h->bs_cooked.narrow[i * 2 + 1] = flags;
      }
    }

    /* Call the caller's extent function.  Yes, our 32-bit public API
     * foolishly tracks the number of uint32_t instead of block
     * descriptors; see _block_desc_is_multiple_of_bs_entry above.
     */
    if (stop)
      debug (h, "truncating server's response at unexpected extent length %"
             PRIu64 " and total %" PRIu64 " near extent %zu",
             orig_len, total, i);
    error = cmd->error;
    if (cmd->cb.wide)
      ret = CALL_CALLBACK (cmd->cb.fn.extent64, name, cmd->offset,
                           h->bs_cooked.wide, i, &error);
    else
      ret = CALL_CALLBACK (cmd->cb.fn.extent32, name, cmd->offset,
                           h->bs_cooked.narrow, i * 2, &error);
    if (ret == -1 && cmd->error == 0)
      cmd->error = error ? error : EPROTO;
  }
  return 0;

}

#line 7060 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RECV_BS_ENTRIES (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RECV_BS_ENTRIES;
  r = enter_STATE_REPLY_CHUNK_REPLY_RECV_BS_ENTRIES (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RECV_BS_ENTRIES",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.RESYNC: Ignore payload of an unexpected chunk reply */
static int
enter_STATE_REPLY_CHUNK_REPLY_RESYNC (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 653 "generator/states-reply-chunk.c"

  struct command *cmd = h->reply_cmd;
  uint16_t type;
  uint64_t length;
  uint64_t offset = -1;

  assert (h->rbuf == NULL);
  switch (recv_into_rbuf (h)) {
  case -1: SET_NEXT_STATE (STATE_DEAD); return 0;
  case 1:
    save_reply_state (h);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  case 0:
    /* If this reply is to an unknown command, FINISH_COMMAND will
     * diagnose and ignore the server bug.  Otherwise, ensure the
     * pending command sees a failure of EPROTO if it does not already
     * have an error.
     */
    if (cmd == NULL) {
      SET_NEXT_STATE (STATE_REPLY_FINISH_COMMAND);
      return 0;
    }
    type = be16toh (h->sbuf.reply.hdr.structured.type);
    if (h->extended_headers) {
      length = be64toh (h->sbuf.reply.hdr.extended.length);
      offset = be64toh (h->sbuf.reply.hdr.extended.offset);
      if (offset != cmd->offset)
        debug (h, "unexpected reply offset %" PRIu64 " for cookie %" PRIu64
               " and command %" PRIu32 ", this is probably a server bug",
               length, cmd->cookie, cmd->type);
      else
        offset = -1;
    }
    else
      length = be32toh (h->sbuf.reply.hdr.structured.length);
    if (offset == -1)
      debug (h, "unexpected reply type %u or payload length %" PRIu64
             " for cookie %" PRIu64 " and command %" PRIu32
             ", this is probably a server bug",
             type, length, cmd->cookie, cmd->type);
    if (cmd->error == 0)
      cmd->error = EPROTO;
    SET_NEXT_STATE (STATE_REPLY_CHUNK_REPLY_FINISH);
  }
  return 0;

}

#line 7140 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_RESYNC (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_RESYNC;
  r = enter_STATE_REPLY_CHUNK_REPLY_RESYNC (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.RESYNC",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.CHUNK_REPLY.FINISH: Finish receiving a chunk reply */
static int
enter_STATE_REPLY_CHUNK_REPLY_FINISH (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 700 "generator/states-reply-chunk.c"

  uint16_t flags;

  assert (h->payload_left == 0);
  flags = be16toh (h->sbuf.reply.hdr.structured.flags);
  if (flags & NBD_REPLY_FLAG_DONE) {
    SET_NEXT_STATE (STATE_REPLY_FINISH_COMMAND);
  }
  else {
    h->reply_cmd = NULL;
    SET_NEXT_STATE (STATE_READY);
  }
  return 0;

}

#line 7187 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_CHUNK_REPLY_FINISH (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_CHUNK_REPLY_FINISH;
  r = enter_STATE_REPLY_CHUNK_REPLY_FINISH (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.CHUNK_REPLY.FINISH",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* REPLY.FINISH_COMMAND: Finish receiving a command */
static int
enter_STATE_REPLY_FINISH_COMMAND (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 246 "generator/states-reply.c"

  struct command *prev_cmd, *cmd;
  uint64_t cookie;
  bool retire;

  /* NB: This works for both simple and structured replies because the
   * handle (our cookie) is stored at the same offset.  See the
   * STATIC_ASSERT above in state REPLY.START that confirmed this.
   */
  cookie = be64toh (h->sbuf.reply.hdr.cookie);
  /* Find the command amongst the commands in flight. */
  for (cmd = h->cmds_in_flight, prev_cmd = NULL;
       cmd != NULL;
       prev_cmd = cmd, cmd = cmd->next) {
    if (cmd->cookie == cookie)
      break;
  }
  assert (h->reply_cmd == cmd);
  if (cmd == NULL) {
    debug (h, "skipped reply for unexpected cookie %" PRIu64
           ", this is probably a bug in the server", cookie);
    SET_NEXT_STATE (STATE_READY);
    return 0;
  }

  retire = cmd->type == NBD_CMD_DISC;
  h->reply_cmd = NULL;

  /* Notify the user */
  if (CALLBACK_IS_NOT_NULL (cmd->cb.completion)) {
    int error = cmd->error;
    int r;

    assert (cmd->type != NBD_CMD_DISC);
    r = CALL_CALLBACK (cmd->cb.completion, &error);
    switch (r) {
    case -1:
      if (error)
        cmd->error = error;
      break;
    case 1:
      retire = true;
      break;
    }
  }

  /* Move it to the end of the cmds_done list. */
  if (prev_cmd != NULL)
    prev_cmd->next = cmd->next;
  else
    h->cmds_in_flight = cmd->next;
  cmd->next = NULL;
  if (retire)
    nbd_internal_retire_and_free_command (cmd);
  else {
    if (h->cmds_done_tail != NULL)
      h->cmds_done_tail = h->cmds_done_tail->next = cmd;
    else {
      assert (h->cmds_done == NULL);
      h->cmds_done = h->cmds_done_tail = cmd;
    }
  }
  h->in_flight--;
  assert (h->in_flight >= 0);

  SET_NEXT_STATE (STATE_READY);
  return 0;

}

#line 7288 "lib/states.c"
int
nbd_internal_enter_STATE_REPLY_FINISH_COMMAND (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_REPLY_FINISH_COMMAND;
  r = enter_STATE_REPLY_FINISH_COMMAND (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "REPLY.FINISH_COMMAND",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* DEAD: Connection is in an unrecoverable error state, can only be closed */
static int
enter_STATE_DEAD (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 193 "generator/states.c"

  const char *err = nbd_get_error ();

  /* The caller should have used set_error() before reaching here */
  assert (err != NULL);
  debug (h, "handle dead: %s", err);

  abort_option (h);
  nbd_internal_abort_commands (h, &h->cmds_to_issue);
  nbd_internal_abort_commands (h, &h->cmds_in_flight);
  h->in_flight = 0;
  if (h->sock) {
    h->sock->ops->close (h->sock);
    h->sock = NULL;
  }
  return -1;

}

#line 7338 "lib/states.c"
int
nbd_internal_enter_STATE_DEAD (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_DEAD;
  r = enter_STATE_DEAD (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "DEAD",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}

/* CLOSED: Connection is closed */
static int
enter_STATE_CLOSED (
  struct nbd_handle *h, enum state *next_state, bool *blocked
)
{
#line 210 "generator/states.c"

  abort_option (h);
  nbd_internal_abort_commands (h, &h->cmds_to_issue);
  nbd_internal_abort_commands (h, &h->cmds_in_flight);
  h->in_flight = 0;
  if (h->sock) {
    h->sock->ops->close (h->sock);
    h->sock = NULL;
  }
  return 0;

}

#line 7382 "lib/states.c"
int
nbd_internal_enter_STATE_CLOSED (
  struct nbd_handle *h, bool *blocked
)
{
  int r;
  enum state next;

  next = STATE_CLOSED;
  r = enter_STATE_CLOSED (
        h, &next, blocked
      );
  if (get_next_state (h) != next) {
#ifdef LIBNBD_STATE_VERBOSE
    debug (h, "transition: %s -> %s",
           "CLOSED",
           nbd_internal_state_short_string (next));
#endif
    set_next_state (h, next);
  }
  return r;
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         /* NBD client library in userspace
 * WARNING: THIS FILE IS GENERATED FROM
 * generator/generator
 * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
 *
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <errno.h>
#include <assert.h>

#include <pthread.h>

/* GCC will remove NULL checks from this file for any parameter
 * annotated with attribute((nonnull)).  See RHBZ#1041336.  To
 * avoid this, disable the attribute when including libnbd.h.
 */
#define LIBNBD_ATTRIBUTE_NONNULL(...)

#include "libnbd.h"
#include "internal.h"

int
nbd_set_debug (
  struct nbd_handle *h, bool debug
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_debug");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: debug=%s",
           debug ? "true" : "false");
  }

  ret = nbd_unlocked_set_debug (h, debug);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_debug (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_debug",
                  "enter:");
  }

  ret = nbd_unlocked_get_debug (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_debug", "leave: ret=%d", ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_set_debug_callback (
  struct nbd_handle *h, nbd_debug_callback debug_callback
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_debug_callback");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: debug=%s",
           "<fun>");
  }

  if (CALLBACK_IS_NULL (debug_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "debug");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_debug_callback (h, &debug_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (debug_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_clear_debug_callback (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_clear_debug_callback");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_clear_debug_callback (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

uint64_t
nbd_stats_bytes_sent (
  struct nbd_handle *h
)
{
  uint64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_stats_bytes_sent",
                  "enter:");
  }

  ret = nbd_unlocked_stats_bytes_sent (h);

  if_debug (h) {
    debug_direct (h, "nbd_stats_bytes_sent", "leave: ret=%" PRIu64, ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

uint64_t
nbd_stats_chunks_sent (
  struct nbd_handle *h
)
{
  uint64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_stats_chunks_sent",
                  "enter:");
  }

  ret = nbd_unlocked_stats_chunks_sent (h);

  if_debug (h) {
    debug_direct (h, "nbd_stats_chunks_sent", "leave: ret=%" PRIu64, ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

uint64_t
nbd_stats_bytes_received (
  struct nbd_handle *h
)
{
  uint64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_stats_bytes_received",
                  "enter:");
  }

  ret = nbd_unlocked_stats_bytes_received (h);

  if_debug (h) {
    debug_direct (h, "nbd_stats_bytes_received", "leave: ret=%" PRIu64, ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

uint64_t
nbd_stats_chunks_received (
  struct nbd_handle *h
)
{
  uint64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_stats_chunks_received",
                  "enter:");
  }

  ret = nbd_unlocked_stats_chunks_received (h);

  if_debug (h) {
    debug_direct (h, "nbd_stats_chunks_received", "leave: ret=%" PRIu64,
                  ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_set_handle_name (
  struct nbd_handle *h, const char *handle_name
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_handle_name");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *handle_name_printable =
        nbd_internal_printable_string (handle_name);
    debug (h,
           "enter: handle_name=%s",
           handle_name_printable ? handle_name_printable : "");
    free (handle_name_printable);
  }

  if (handle_name == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "handle_name");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_handle_name (h, handle_name);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

char *
nbd_get_handle_name (
  struct nbd_handle *h
)
{
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_handle_name");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_handle_name (h);

  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

uintptr_t
nbd_set_private_data (
  struct nbd_handle *h, uintptr_t private_data
)
{
  uintptr_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_set_private_data",
                  "enter: private_data=%"PRIuPTR"",
                  private_data);
  }

  ret = nbd_unlocked_set_private_data (h, private_data);

  if_debug (h) {
    debug_direct (h, "nbd_set_private_data", "leave: ret=%" PRIuPTR, ret);
  }

  return ret;
}

uintptr_t
nbd_get_private_data (
  struct nbd_handle *h
)
{
  uintptr_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_get_private_data",
                  "enter:");
  }

  ret = nbd_unlocked_get_private_data (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_private_data", "leave: ret=%" PRIuPTR, ret);
  }

  return ret;
}

static inline bool
set_export_name_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state) ||
        nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created, or negotiating");
    return false;
  }
  return true;
}

int
nbd_set_export_name (
  struct nbd_handle *h, const char *export_name
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_export_name");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *export_name_printable =
        nbd_internal_printable_string (export_name);
    debug (h,
           "enter: export_name=%s",
           export_name_printable ? export_name_printable : "");
    free (export_name_printable);
  }

  p = set_export_name_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (export_name == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "export_name");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_export_name (h, export_name);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

char *
nbd_get_export_name (
  struct nbd_handle *h
)
{
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_export_name");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_export_name (h);

  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_request_block_size_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state) ||
        nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created, or negotiating");
    return false;
  }
  return true;
}

int
nbd_set_request_block_size (
  struct nbd_handle *h, bool request
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_request_block_size");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: request=%s",
           request ? "true" : "false");
  }

  p = set_request_block_size_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_request_block_size (h, request);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_request_block_size (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_request_block_size");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_request_block_size (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_full_info_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state) ||
        nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created, or negotiating");
    return false;
  }
  return true;
}

int
nbd_set_full_info (
  struct nbd_handle *h, bool request
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_full_info");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: request=%s",
           request ? "true" : "false");
  }

  p = set_full_info_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_full_info (h, request);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_full_info (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_full_info");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_full_info (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
get_canonical_export_name_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

char *
nbd_get_canonical_export_name (
  struct nbd_handle *h
)
{
  bool p;
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_canonical_export_name");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = get_canonical_export_name_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = NULL;
    goto out;
  }
  ret = nbd_unlocked_get_canonical_export_name (h);

 out:
  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
get_export_description_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

char *
nbd_get_export_description (
  struct nbd_handle *h
)
{
  bool p;
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_export_description");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = get_export_description_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = NULL;
    goto out;
  }
  ret = nbd_unlocked_get_export_description (h);

 out:
  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_tls_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_tls (
  struct nbd_handle *h, int tls
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_tls");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: tls=%d",
           tls);
  }

  p = set_tls_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  switch (tls) {
  case LIBNBD_TLS_DISABLE:
  case LIBNBD_TLS_ALLOW:
  case LIBNBD_TLS_REQUIRE:
    break;
  default:
    set_error (EINVAL, "%s: invalid value for parameter: %d",
               "tls", tls);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_tls (h, tls);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_tls (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_tls",
                  "enter:");
  }

  ret = nbd_unlocked_get_tls (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_tls", "leave: ret=%d", ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
get_tls_negotiated_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_get_tls_negotiated (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_tls_negotiated");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = get_tls_negotiated_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_get_tls_negotiated (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_tls_certificates_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_tls_certificates (
  struct nbd_handle *h, const char *dir
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_tls_certificates");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *dir_printable =
        nbd_internal_printable_string (dir);
    debug (h,
           "enter: dir=%s",
           dir_printable ? dir_printable : "");
    free (dir_printable);
  }

  p = set_tls_certificates_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (dir == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "dir");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_tls_certificates (h, dir);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_tls_verify_peer_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_tls_verify_peer (
  struct nbd_handle *h, bool verify
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_tls_verify_peer");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: verify=%s",
           verify ? "true" : "false");
  }

  p = set_tls_verify_peer_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_tls_verify_peer (h, verify);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_tls_verify_peer (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_tls_verify_peer",
                  "enter:");
  }

  ret = nbd_unlocked_get_tls_verify_peer (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_tls_verify_peer", "leave: ret=%d", ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_tls_username_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_tls_username (
  struct nbd_handle *h, const char *username
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_tls_username");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *username_printable =
        nbd_internal_printable_string (username);
    debug (h,
           "enter: username=%s",
           username_printable ? username_printable : "");
    free (username_printable);
  }

  p = set_tls_username_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (username == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "username");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_tls_username (h, username);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

char *
nbd_get_tls_username (
  struct nbd_handle *h
)
{
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_tls_username");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_tls_username (h);

  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_tls_hostname_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_tls_hostname (
  struct nbd_handle *h, const char *hostname
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_tls_hostname");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *hostname_printable =
        nbd_internal_printable_string (hostname);
    debug (h,
           "enter: hostname=%s",
           hostname_printable ? hostname_printable : "");
    free (hostname_printable);
  }

  p = set_tls_hostname_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (hostname == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "hostname");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_tls_hostname (h, hostname);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

char *
nbd_get_tls_hostname (
  struct nbd_handle *h
)
{
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_tls_hostname");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_tls_hostname (h);

  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_tls_psk_file_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_tls_psk_file (
  struct nbd_handle *h, const char *filename
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_tls_psk_file");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *filename_printable =
        nbd_internal_printable_string (filename);
    debug (h,
           "enter: filename=%s",
           filename_printable ? filename_printable : "");
    free (filename_printable);
  }

  p = set_tls_psk_file_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (filename == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "filename");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_tls_psk_file (h, filename);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_request_extended_headers_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_request_extended_headers (
  struct nbd_handle *h, bool request
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_request_extended_headers");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: request=%s",
           request ? "true" : "false");
  }

  p = set_request_extended_headers_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_request_extended_headers (h, request);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_request_extended_headers (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_request_extended_headers",
                  "enter:");
  }

  ret = nbd_unlocked_get_request_extended_headers (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_request_extended_headers", "leave: ret=%d",
                  ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
get_extended_headers_negotiated_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_get_extended_headers_negotiated (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_extended_headers_negotiated");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = get_extended_headers_negotiated_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_get_extended_headers_negotiated (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_request_structured_replies_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_request_structured_replies (
  struct nbd_handle *h, bool request
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_request_structured_replies");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: request=%s",
           request ? "true" : "false");
  }

  p = set_request_structured_replies_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_request_structured_replies (h, request);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_request_structured_replies (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_request_structured_replies",
                  "enter:");
  }

  ret = nbd_unlocked_get_request_structured_replies (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_request_structured_replies", "leave: ret=%d",
                  ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
get_structured_replies_negotiated_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_get_structured_replies_negotiated (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_structured_replies_negotiated");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = get_structured_replies_negotiated_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_get_structured_replies_negotiated (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_request_meta_context_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state) ||
        nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created, or negotiating");
    return false;
  }
  return true;
}

int
nbd_set_request_meta_context (
  struct nbd_handle *h, bool request
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_request_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: request=%s",
           request ? "true" : "false");
  }

  p = set_request_meta_context_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_request_meta_context (h, request);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_request_meta_context (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_request_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_request_meta_context (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_handshake_flags_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_handshake_flags (
  struct nbd_handle *h, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_handshake_flags");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: flags=0x%x",
           flags);
  }

  p = set_handshake_flags_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~LIBNBD_HANDSHAKE_FLAG_MASK) != 0)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_handshake_flags (h, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

uint32_t
nbd_get_handshake_flags (
  struct nbd_handle *h
)
{
  uint32_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_handshake_flags",
                  "enter:");
  }

  ret = nbd_unlocked_get_handshake_flags (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_handshake_flags", "leave: ret=%u", ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_set_pread_initialize (
  struct nbd_handle *h, bool request
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_pread_initialize");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: request=%s",
           request ? "true" : "false");
  }

  ret = nbd_unlocked_set_pread_initialize (h, request);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_pread_initialize (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_pread_initialize",
                  "enter:");
  }

  ret = nbd_unlocked_get_pread_initialize (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_pread_initialize", "leave: ret=%d", ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_set_strict_mode (
  struct nbd_handle *h, uint32_t flags
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_strict_mode");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: flags=0x%x",
           flags);
  }

  if (unlikely ((flags & ~LIBNBD_STRICT_MASK) != 0)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_strict_mode (h, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

uint32_t
nbd_get_strict_mode (
  struct nbd_handle *h
)
{
  uint32_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_strict_mode",
                  "enter:");
  }

  ret = nbd_unlocked_get_strict_mode (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_strict_mode", "leave: ret=%u", ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_opt_mode_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_opt_mode (
  struct nbd_handle *h, bool enable
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_opt_mode");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: enable=%s",
           enable ? "true" : "false");
  }

  p = set_opt_mode_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_opt_mode (h, enable);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_get_opt_mode (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug_direct (h, "nbd_get_opt_mode",
                  "enter:");
  }

  ret = nbd_unlocked_get_opt_mode (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_opt_mode", "leave: ret=%d", ret);
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_go_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_go (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_go");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = opt_go_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_go (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_abort_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_abort (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_abort");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = opt_abort_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_abort (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_starttls_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_starttls (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_starttls");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = opt_starttls_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_starttls (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_extended_headers_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_extended_headers (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_extended_headers");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = opt_extended_headers_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_extended_headers (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_structured_reply_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_structured_reply (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_structured_reply");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = opt_structured_reply_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_structured_reply (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_list_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_list (
  struct nbd_handle *h, nbd_list_callback list_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_list");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: list=%s",
           "<fun>");
  }

  p = opt_list_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (list_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "list");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_list (h, &list_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (list_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_info_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_info (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_info");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = opt_info_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_info (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_list_meta_context_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_list_meta_context (
  struct nbd_handle *h, nbd_context_callback context_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_list_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: context=%s",
           "<fun>");
  }

  p = opt_list_meta_context_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (context_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "context");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_list_meta_context (h, &context_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (context_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_list_meta_context_queries_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_list_meta_context_queries (
  struct nbd_handle *h, char **queries,
  nbd_context_callback context_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_list_meta_context_queries");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *queries_printable =
        nbd_internal_printable_string_list (queries);
    debug (h,
           "enter: queries=%s context=%s",
           queries_printable ? queries_printable : "", "<fun>");
    free (queries_printable);
  }

  p = opt_list_meta_context_queries_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (queries == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "queries");
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (context_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "context");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_list_meta_context_queries (h, queries,
                                                    &context_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (context_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_set_meta_context_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_set_meta_context (
  struct nbd_handle *h, nbd_context_callback context_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_set_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: context=%s",
           "<fun>");
  }

  p = opt_set_meta_context_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (context_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "context");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_set_meta_context (h, &context_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (context_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
opt_set_meta_context_queries_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_opt_set_meta_context_queries (
  struct nbd_handle *h, char **queries,
  nbd_context_callback context_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_opt_set_meta_context_queries");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *queries_printable =
        nbd_internal_printable_string_list (queries);
    debug (h,
           "enter: queries=%s context=%s",
           queries_printable ? queries_printable : "", "<fun>");
    free (queries_printable);
  }

  p = opt_set_meta_context_queries_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (queries == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "queries");
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (context_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "context");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_opt_set_meta_context_queries (h, queries,
                                                   &context_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (context_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
add_meta_context_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state) ||
        nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created, or negotiating");
    return false;
  }
  return true;
}

int
nbd_add_meta_context (
  struct nbd_handle *h, const char *name
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_add_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *name_printable =
        nbd_internal_printable_string (name);
    debug (h,
           "enter: name=%s",
           name_printable ? name_printable : "");
    free (name_printable);
  }

  p = add_meta_context_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (name == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "name");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_add_meta_context (h, name);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

ssize_t
nbd_get_nr_meta_contexts (
  struct nbd_handle *h
)
{
  ssize_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_nr_meta_contexts");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_nr_meta_contexts (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%zd", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

char *
nbd_get_meta_context (
  struct nbd_handle *h, size_t i
)
{
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: i=%zu",
           i);
  }

  ret = nbd_unlocked_get_meta_context (h, i);

  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
clear_meta_contexts_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state) ||
        nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created, or negotiating");
    return false;
  }
  return true;
}

int
nbd_clear_meta_contexts (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_clear_meta_contexts");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = clear_meta_contexts_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_clear_meta_contexts (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_uri_allow_transports_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_uri_allow_transports (
  struct nbd_handle *h, uint32_t mask
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_uri_allow_transports");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: mask=0x%x",
           mask);
  }

  p = set_uri_allow_transports_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((mask & ~LIBNBD_ALLOW_TRANSPORT_MASK) != 0)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "mask", mask);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_uri_allow_transports (h, mask);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_uri_allow_tls_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_uri_allow_tls (
  struct nbd_handle *h, int tls
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_uri_allow_tls");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: tls=%d",
           tls);
  }

  p = set_uri_allow_tls_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  switch (tls) {
  case LIBNBD_TLS_DISABLE:
  case LIBNBD_TLS_ALLOW:
  case LIBNBD_TLS_REQUIRE:
    break;
  default:
    set_error (EINVAL, "%s: invalid value for parameter: %d",
               "tls", tls);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_uri_allow_tls (h, tls);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_uri_allow_local_file_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_uri_allow_local_file (
  struct nbd_handle *h, bool allow
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_uri_allow_local_file");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: allow=%s",
           allow ? "true" : "false");
  }

  p = set_uri_allow_local_file_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_uri_allow_local_file (h, allow);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
connect_uri_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_connect_uri (
  struct nbd_handle *h, const char *uri
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_connect_uri");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *uri_printable =
        nbd_internal_printable_string (uri);
    debug (h,
           "enter: uri=%s",
           uri_printable ? uri_printable : "");
    free (uri_printable);
  }

  p = connect_uri_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (uri == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "uri");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_connect_uri (h, uri);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
connect_unix_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_connect_unix (
  struct nbd_handle *h, const char *unixsocket
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_connect_unix");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *unixsocket_printable =
        nbd_internal_printable_string (unixsocket);
    debug (h,
           "enter: unixsocket=%s",
           unixsocket_printable ? unixsocket_printable : "");
    free (unixsocket_printable);
  }

  p = connect_unix_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unixsocket == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "unixsocket");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_connect_unix (h, unixsocket);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
connect_vsock_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_connect_vsock (
  struct nbd_handle *h, uint32_t cid, uint32_t port
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_connect_vsock");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: cid=%"PRIu32" port=%"PRIu32"",
           cid, port);
  }

  p = connect_vsock_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_connect_vsock (h, cid, port);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
connect_tcp_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_connect_tcp (
  struct nbd_handle *h, const char *hostname, const char *port
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_connect_tcp");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *hostname_printable =
        nbd_internal_printable_string (hostname);
    char *port_printable =
        nbd_internal_printable_string (port);
    debug (h,
           "enter: hostname=%s port=%s",
           hostname_printable ? hostname_printable : "",
           port_printable ? port_printable : "");
    free (hostname_printable);
    free (port_printable);
  }

  p = connect_tcp_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (hostname == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "hostname");
    ret = -1;
    goto out;
  }
  if (port == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "port");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_connect_tcp (h, hostname, port);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
connect_socket_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_connect_socket (
  struct nbd_handle *h, int sock
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_connect_socket");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: sock=%d",
           sock);
  }

  p = connect_socket_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_connect_socket (h, sock);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
connect_command_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_connect_command (
  struct nbd_handle *h, char **argv
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_connect_command");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *argv_printable =
        nbd_internal_printable_string_list (argv);
    debug (h,
           "enter: argv=%s",
           argv_printable ? argv_printable : "");
    free (argv_printable);
  }

  p = connect_command_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (argv == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "argv");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_connect_command (h, argv);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
connect_systemd_socket_activation_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_connect_systemd_socket_activation (
  struct nbd_handle *h, char **argv
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_connect_systemd_socket_activation");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *argv_printable =
        nbd_internal_printable_string_list (argv);
    debug (h,
           "enter: argv=%s",
           argv_printable ? argv_printable : "");
    free (argv_printable);
  }

  p = connect_systemd_socket_activation_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (argv == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "argv");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_connect_systemd_socket_activation (h, argv);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
set_socket_activation_name_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_set_socket_activation_name (
  struct nbd_handle *h, const char *socket_name
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_set_socket_activation_name");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *socket_name_printable =
        nbd_internal_printable_string (socket_name);
    debug (h,
           "enter: socket_name=%s",
           socket_name_printable ? socket_name_printable : "");
    free (socket_name_printable);
  }

  p = set_socket_activation_name_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (socket_name == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "socket_name");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_set_socket_activation_name (h, socket_name);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

char *
nbd_get_socket_activation_name (
  struct nbd_handle *h
)
{
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_socket_activation_name");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_socket_activation_name (h);

  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
is_read_only_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_is_read_only (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_is_read_only");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = is_read_only_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_is_read_only (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_flush_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_flush (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_flush");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_flush_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_flush (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_fua_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_fua (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_fua");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_fua_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_fua (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
is_rotational_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_is_rotational (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_is_rotational");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = is_rotational_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_is_rotational (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_trim_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_trim (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_trim");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_trim_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_trim (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_zero_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_zero (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_zero");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_zero_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_zero (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_fast_zero_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_fast_zero (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_fast_zero");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_fast_zero_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_fast_zero (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_block_status_payload_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_block_status_payload (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_block_status_payload");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_block_status_payload_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_block_status_payload (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_df_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_df (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_df");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_df_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_df (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_multi_conn_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_multi_conn (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_multi_conn");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_multi_conn_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_multi_conn (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_cache_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_cache (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_cache");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = can_cache_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_cache (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
can_meta_context_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int
nbd_can_meta_context (
  struct nbd_handle *h, const char *metacontext
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_can_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *metacontext_printable =
        nbd_internal_printable_string (metacontext);
    debug (h,
           "enter: metacontext=%s",
           metacontext_printable ? metacontext_printable : "");
    free (metacontext_printable);
  }

  p = can_meta_context_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (metacontext == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "metacontext");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_can_meta_context (h, metacontext);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
get_protocol_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

const char *
nbd_get_protocol (
  struct nbd_handle *h
)
{
  bool p;
  const char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_protocol");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = get_protocol_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = NULL;
    goto out;
  }
  ret = nbd_unlocked_get_protocol (h);

 out:
  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%s", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
get_size_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int64_t
nbd_get_size (
  struct nbd_handle *h
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_size");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = get_size_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_get_size (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
get_block_size_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server, or shut down");
    return false;
  }
  return true;
}

int64_t
nbd_get_block_size (
  struct nbd_handle *h, int size_type
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_block_size");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: size_type=%d",
           size_type);
  }

  p = get_block_size_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  switch (size_type) {
  case LIBNBD_SIZE_MINIMUM:
  case LIBNBD_SIZE_PREFERRED:
  case LIBNBD_SIZE_MAXIMUM:
  case LIBNBD_SIZE_PAYLOAD:
    break;
  default:
    set_error (EINVAL, "%s: invalid value for parameter: %d",
               "size_type", size_type);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_get_block_size (h, size_type);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
pread_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_pread (
  struct nbd_handle *h, void *buf, size_t count, uint64_t offset,
  uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_pread");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: buf=<buf> count=%zu offset=%"PRIu64" flags=0x%x",
           count, offset, flags);
  }

  if (h->pread_initialize)
    memset (buf, 0, count);
  p = pread_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (buf == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "buf");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_pread (h, buf, count, offset, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
pread_structured_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_pread_structured (
  struct nbd_handle *h, void *buf, size_t count, uint64_t offset,
  nbd_chunk_callback chunk_callback, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_pread_structured");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: buf=<buf> count=%zu offset=%"PRIu64" chunk=%s flags=0x%x",
           count, offset, "<fun>", flags);
  }

  if (h->pread_initialize)
    memset (buf, 0, count);
  p = pread_structured_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (buf == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "buf");
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (chunk_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "chunk");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x4) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_pread_structured (h, buf, count, offset,
                                       &chunk_callback, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (chunk_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
pwrite_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_pwrite (
  struct nbd_handle *h, const void *buf, size_t count, uint64_t offset,
  uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_pwrite");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *buf_printable =
        nbd_internal_printable_buffer (buf, count);
    debug (h,
           "enter: buf=\"%s\" count=%zu offset=%"PRIu64" flags=0x%x",
           buf_printable ? buf_printable : "", count, offset, flags);
    free (buf_printable);
  }

  p = pwrite_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (buf == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "buf");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x21) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_pwrite (h, buf, count, offset, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
shutdown_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating, or connected with the server");
    return false;
  }
  return true;
}

int
nbd_shutdown (
  struct nbd_handle *h, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_shutdown");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: flags=0x%x",
           flags);
  }

  p = shutdown_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~LIBNBD_SHUTDOWN_MASK) != 0)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_shutdown (h, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
flush_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_flush (
  struct nbd_handle *h, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_flush");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: flags=0x%x",
           flags);
  }

  p = flush_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_flush (h, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
trim_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_trim (
  struct nbd_handle *h, uint64_t count, uint64_t offset, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_trim");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" flags=0x%x",
           count, offset, flags);
  }

  p = trim_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x1) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_trim (h, count, offset, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
cache_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_cache (
  struct nbd_handle *h, uint64_t count, uint64_t offset, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_cache");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" flags=0x%x",
           count, offset, flags);
  }

  p = cache_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_cache (h, count, offset, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
zero_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_zero (
  struct nbd_handle *h, uint64_t count, uint64_t offset, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_zero");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" flags=0x%x",
           count, offset, flags);
  }

  p = zero_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x13) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_zero (h, count, offset, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
block_status_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_block_status (
  struct nbd_handle *h, uint64_t count, uint64_t offset,
  nbd_extent_callback extent_callback, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_block_status");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" extent=%s flags=0x%x",
           count, offset, "<fun>", flags);
  }

  p = block_status_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (extent_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "extent");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x8) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_block_status (h, count, offset, &extent_callback,
                                   flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (extent_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
block_status_64_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_block_status_64 (
  struct nbd_handle *h, uint64_t count, uint64_t offset,
  nbd_extent64_callback extent64_callback, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_block_status_64");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" extent64=%s flags=0x%x",
           count, offset, "<fun>", flags);
  }

  p = block_status_64_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (extent64_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "extent64");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x8) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_block_status_64 (h, count, offset, &extent64_callback,
                                      flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (extent64_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
block_status_filter_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_block_status_filter (
  struct nbd_handle *h, uint64_t count, uint64_t offset, char **contexts,
  nbd_extent64_callback extent64_callback, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_block_status_filter");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *contexts_printable =
        nbd_internal_printable_string_list (contexts);
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" contexts=%s "
           "extent64=%s flags=0x%x",
           count, offset, contexts_printable ? contexts_printable : "",
           "<fun>", flags);
    free (contexts_printable);
  }

  p = block_status_filter_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (contexts == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "contexts");
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (extent64_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "extent64");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x28) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_block_status_filter (h, count, offset, contexts,
                                          &extent64_callback, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (extent64_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_poll (
  struct nbd_handle *h, int timeout
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_poll");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: timeout=%d",
           timeout);
  }

  ret = nbd_unlocked_poll (h, timeout);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_poll2 (
  struct nbd_handle *h, int fd, int timeout
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_poll2");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: fd=%d timeout=%d",
           fd, timeout);
  }

  ret = nbd_unlocked_poll2 (h, fd, timeout);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_connect_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_aio_connect (
  struct nbd_handle *h, const struct sockaddr *addr, socklen_t addrlen
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_connect");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: addr=<sockaddr> addrlen=%d",
           (int) addrlen);
  }

  p = aio_connect_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (addr == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "addr");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_connect (h, addr, addrlen);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_connect_uri_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_aio_connect_uri (
  struct nbd_handle *h, const char *uri
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_connect_uri");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *uri_printable =
        nbd_internal_printable_string (uri);
    debug (h,
           "enter: uri=%s",
           uri_printable ? uri_printable : "");
    free (uri_printable);
  }

  p = aio_connect_uri_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (uri == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "uri");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_connect_uri (h, uri);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_connect_unix_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_aio_connect_unix (
  struct nbd_handle *h, const char *unixsocket
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_connect_unix");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *unixsocket_printable =
        nbd_internal_printable_string (unixsocket);
    debug (h,
           "enter: unixsocket=%s",
           unixsocket_printable ? unixsocket_printable : "");
    free (unixsocket_printable);
  }

  p = aio_connect_unix_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unixsocket == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "unixsocket");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_connect_unix (h, unixsocket);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_connect_vsock_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_aio_connect_vsock (
  struct nbd_handle *h, uint32_t cid, uint32_t port
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_connect_vsock");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: cid=%"PRIu32" port=%"PRIu32"",
           cid, port);
  }

  p = aio_connect_vsock_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_connect_vsock (h, cid, port);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_connect_tcp_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_aio_connect_tcp (
  struct nbd_handle *h, const char *hostname, const char *port
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_connect_tcp");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *hostname_printable =
        nbd_internal_printable_string (hostname);
    char *port_printable =
        nbd_internal_printable_string (port);
    debug (h,
           "enter: hostname=%s port=%s",
           hostname_printable ? hostname_printable : "",
           port_printable ? port_printable : "");
    free (hostname_printable);
    free (port_printable);
  }

  p = aio_connect_tcp_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (hostname == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "hostname");
    ret = -1;
    goto out;
  }
  if (port == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "port");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_connect_tcp (h, hostname, port);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_connect_socket_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_aio_connect_socket (
  struct nbd_handle *h, int sock
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_connect_socket");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: sock=%d",
           sock);
  }

  p = aio_connect_socket_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_connect_socket (h, sock);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_connect_command_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_aio_connect_command (
  struct nbd_handle *h, char **argv
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_connect_command");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *argv_printable =
        nbd_internal_printable_string_list (argv);
    debug (h,
           "enter: argv=%s",
           argv_printable ? argv_printable : "");
    free (argv_printable);
  }

  p = aio_connect_command_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (argv == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "argv");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_connect_command (h, argv);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_connect_systemd_socket_activation_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_created (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "newly created");
    return false;
  }
  return true;
}

int
nbd_aio_connect_systemd_socket_activation (
  struct nbd_handle *h, char **argv
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_connect_systemd_socket_activation");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *argv_printable =
        nbd_internal_printable_string_list (argv);
    debug (h,
           "enter: argv=%s",
           argv_printable ? argv_printable : "");
    free (argv_printable);
  }

  p = aio_connect_systemd_socket_activation_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (argv == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "argv");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_connect_systemd_socket_activation (h, argv);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_go_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_go (
  struct nbd_handle *h, nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_go");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: completion=%s",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
  }

  p = aio_opt_go_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_go (h, &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_abort_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_abort (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_abort");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = aio_opt_abort_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_abort (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_starttls_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_starttls (
  struct nbd_handle *h, nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_starttls");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: completion=%s",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
  }

  p = aio_opt_starttls_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_starttls (h, &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_extended_headers_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_extended_headers (
  struct nbd_handle *h, nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_extended_headers");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: completion=%s",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
  }

  p = aio_opt_extended_headers_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_extended_headers (h, &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_structured_reply_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_structured_reply (
  struct nbd_handle *h, nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_structured_reply");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: completion=%s",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
  }

  p = aio_opt_structured_reply_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_structured_reply (h, &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_list_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_list (
  struct nbd_handle *h, nbd_list_callback list_callback,
  nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_list");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: list=%s completion=%s",
           "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
  }

  p = aio_opt_list_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (list_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "list");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_list (h, &list_callback, &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (list_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_info_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_info (
  struct nbd_handle *h, nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_info");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: completion=%s",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
  }

  p = aio_opt_info_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_info (h, &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_list_meta_context_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_list_meta_context (
  struct nbd_handle *h, nbd_context_callback context_callback,
  nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_list_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: context=%s completion=%s",
           "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
  }

  p = aio_opt_list_meta_context_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (context_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "context");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_list_meta_context (h, &context_callback,
                                                &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (context_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_list_meta_context_queries_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_list_meta_context_queries (
  struct nbd_handle *h, char **queries,
  nbd_context_callback context_callback,
  nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_list_meta_context_queries");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *queries_printable =
        nbd_internal_printable_string_list (queries);
    debug (h,
           "enter: queries=%s context=%s completion=%s",
           queries_printable ? queries_printable : "", "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
    free (queries_printable);
  }

  p = aio_opt_list_meta_context_queries_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (queries == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "queries");
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (context_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "context");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_list_meta_context_queries (h, queries,
                                                        &context_callback,
                                                        &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (context_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_set_meta_context_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_set_meta_context (
  struct nbd_handle *h, nbd_context_callback context_callback,
  nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_set_meta_context");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: context=%s completion=%s",
           "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
  }

  p = aio_opt_set_meta_context_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (context_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "context");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_set_meta_context (h, &context_callback,
                                               &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (context_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_opt_set_meta_context_queries_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_negotiating (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "negotiating");
    return false;
  }
  return true;
}

int
nbd_aio_opt_set_meta_context_queries (
  struct nbd_handle *h, char **queries,
  nbd_context_callback context_callback,
  nbd_completion_callback completion_callback
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_opt_set_meta_context_queries");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *queries_printable =
        nbd_internal_printable_string_list (queries);
    debug (h,
           "enter: queries=%s context=%s completion=%s",
           queries_printable ? queries_printable : "", "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL");
    free (queries_printable);
  }

  p = aio_opt_set_meta_context_queries_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (queries == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "queries");
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (context_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "context");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_opt_set_meta_context_queries (h, queries,
                                                       &context_callback,
                                                       &completion_callback);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  FREE_CALLBACK (context_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_pread_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_pread (
  struct nbd_handle *h, void *buf, size_t count, uint64_t offset,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_pread");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: buf=<buf> count=%zu offset=%"PRIu64" completion=%s "
           "flags=0x%x",
           count, offset,
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
  }

  if (h->pread_initialize)
    memset (buf, 0, count);
  p = aio_pread_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (buf == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "buf");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_pread (h, buf, count, offset, &completion_callback,
                                flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_pread_structured_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_pread_structured (
  struct nbd_handle *h, void *buf, size_t count, uint64_t offset,
  nbd_chunk_callback chunk_callback,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_pread_structured");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: buf=<buf> count=%zu offset=%"PRIu64" chunk=%s "
           "completion=%s flags=0x%x",
           count, offset, "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
  }

  if (h->pread_initialize)
    memset (buf, 0, count);
  p = aio_pread_structured_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (buf == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "buf");
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (chunk_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "chunk");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x4) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_pread_structured (h, buf, count, offset,
                                           &chunk_callback,
                                           &completion_callback, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (chunk_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_pwrite_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_pwrite (
  struct nbd_handle *h, const void *buf, size_t count, uint64_t offset,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_pwrite");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *buf_printable =
        nbd_internal_printable_buffer (buf, count);
    debug (h,
           "enter: buf=\"%s\" count=%zu offset=%"PRIu64" completion=%s "
           "flags=0x%x",
           buf_printable ? buf_printable : "", count, offset,
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
    free (buf_printable);
  }

  p = aio_pwrite_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (buf == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "buf");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x21) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_pwrite (h, buf, count, offset,
                                 &completion_callback, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_disconnect_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int
nbd_aio_disconnect (
  struct nbd_handle *h, uint32_t flags
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_disconnect");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: flags=0x%x",
           flags);
  }

  p = aio_disconnect_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_disconnect (h, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_flush_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_flush (
  struct nbd_handle *h, nbd_completion_callback completion_callback,
  uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_flush");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: completion=%s flags=0x%x",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
  }

  p = aio_flush_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_flush (h, &completion_callback, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_trim_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_trim (
  struct nbd_handle *h, uint64_t count, uint64_t offset,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_trim");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" completion=%s "
           "flags=0x%x",
           count, offset,
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
  }

  p = aio_trim_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x1) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_trim (h, count, offset, &completion_callback,
                               flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_cache_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_cache (
  struct nbd_handle *h, uint64_t count, uint64_t offset,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_cache");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" completion=%s "
           "flags=0x%x",
           count, offset,
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
  }

  p = aio_cache_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_cache (h, count, offset, &completion_callback,
                                flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_zero_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_zero (
  struct nbd_handle *h, uint64_t count, uint64_t offset,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_zero");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" completion=%s "
           "flags=0x%x",
           count, offset,
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
  }

  p = aio_zero_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x13) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_zero (h, count, offset, &completion_callback,
                               flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_block_status_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_block_status (
  struct nbd_handle *h, uint64_t count, uint64_t offset,
  nbd_extent_callback extent_callback,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_block_status");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" extent=%s "
           "completion=%s flags=0x%x",
           count, offset, "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
  }

  p = aio_block_status_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (extent_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "extent");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x8) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_block_status (h, count, offset, &extent_callback,
                                       &completion_callback, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (extent_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_block_status_64_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_block_status_64 (
  struct nbd_handle *h, uint64_t count, uint64_t offset,
  nbd_extent64_callback extent64_callback,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_block_status_64");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" extent64=%s "
           "completion=%s flags=0x%x",
           count, offset, "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
  }

  p = aio_block_status_64_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (extent64_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "extent64");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x8) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_block_status_64 (h, count, offset,
                                          &extent64_callback,
                                          &completion_callback, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (extent64_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_block_status_filter_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server");
    return false;
  }
  return true;
}

int64_t
nbd_aio_block_status_filter (
  struct nbd_handle *h, uint64_t count, uint64_t offset, char **contexts,
  nbd_extent64_callback extent64_callback,
  nbd_completion_callback completion_callback, uint32_t flags
)
{
  bool p;
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_block_status_filter");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *contexts_printable =
        nbd_internal_printable_string_list (contexts);
    debug (h,
           "enter: count=%"PRIu64" offset=%"PRIu64" contexts=%s "
           "extent64=%s completion=%s flags=0x%x",
           count, offset, contexts_printable ? contexts_printable : "",
           "<fun>",
           CALLBACK_IS_NULL (completion_callback) ? "<fun>" : "NULL", flags);
    free (contexts_printable);
  }

  p = aio_block_status_filter_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  if (contexts == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "contexts");
    ret = -1;
    goto out;
  }
  if (CALLBACK_IS_NULL (extent64_callback)) {
    set_error (EFAULT, "%s cannot be NULL", "extent64");
    ret = -1;
    goto out;
  }
  if (unlikely ((flags & ~0x28) != 0) &&
      ((h->strict & LIBNBD_STRICT_FLAGS) || flags > UINT16_MAX)) {
    set_error (EINVAL, "%s: invalid value for flag: 0x%x",
               "flags", flags);
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_block_status_filter (h, count, offset, contexts,
                                              &extent64_callback,
                                              &completion_callback, flags);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  FREE_CALLBACK (extent64_callback);
  FREE_CALLBACK (completion_callback);
  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_aio_get_fd (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_get_fd");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_aio_get_fd (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

unsigned
nbd_aio_get_direction (
  struct nbd_handle *h
)
{
  unsigned ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_aio_get_direction",
                  "enter:");
  }

  ret = nbd_unlocked_aio_get_direction (h);

  if_debug (h) {
    debug_direct (h, "nbd_aio_get_direction", "leave: ret=%u", ret);
  }

  return ret;
}

int
nbd_aio_notify_read (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_notify_read");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_aio_notify_read (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_aio_notify_write (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_notify_write");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_aio_notify_write (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_aio_is_created (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_aio_is_created",
                  "enter:");
  }

  ret = nbd_unlocked_aio_is_created (h);

  if_debug (h) {
    debug_direct (h, "nbd_aio_is_created", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_aio_is_connecting (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_aio_is_connecting",
                  "enter:");
  }

  ret = nbd_unlocked_aio_is_connecting (h);

  if_debug (h) {
    debug_direct (h, "nbd_aio_is_connecting", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_aio_is_negotiating (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_aio_is_negotiating",
                  "enter:");
  }

  ret = nbd_unlocked_aio_is_negotiating (h);

  if_debug (h) {
    debug_direct (h, "nbd_aio_is_negotiating", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_aio_is_ready (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_aio_is_ready",
                  "enter:");
  }

  ret = nbd_unlocked_aio_is_ready (h);

  if_debug (h) {
    debug_direct (h, "nbd_aio_is_ready", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_aio_is_processing (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_aio_is_processing",
                  "enter:");
  }

  ret = nbd_unlocked_aio_is_processing (h);

  if_debug (h) {
    debug_direct (h, "nbd_aio_is_processing", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_aio_is_dead (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_aio_is_dead",
                  "enter:");
  }

  ret = nbd_unlocked_aio_is_dead (h);

  if_debug (h) {
    debug_direct (h, "nbd_aio_is_dead", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_aio_is_closed (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_aio_is_closed",
                  "enter:");
  }

  ret = nbd_unlocked_aio_is_closed (h);

  if_debug (h) {
    debug_direct (h, "nbd_aio_is_closed", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_aio_command_completed (
  struct nbd_handle *h, uint64_t cookie
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_command_completed");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: cookie=%"PRIu64"",
           cookie);
  }

  ret = nbd_unlocked_aio_command_completed (h, cookie);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int64_t
nbd_aio_peek_command_completed (
  struct nbd_handle *h
)
{
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_peek_command_completed");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_aio_peek_command_completed (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

static inline bool
aio_in_flight_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state) ||
        nbd_internal_is_state_dead (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connected with the server, or shut down, or dead");
    return false;
  }
  return true;
}

int
nbd_aio_in_flight (
  struct nbd_handle *h
)
{
  bool p;
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_aio_in_flight");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = aio_in_flight_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_aio_in_flight (h);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

const char *
nbd_connection_state (
  struct nbd_handle *h
)
{
  const char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_connection_state");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_connection_state (h);

  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%s", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

const char *
nbd_get_package_name (
  struct nbd_handle *h
)
{
  const char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_get_package_name",
                  "enter:");
  }

  ret = nbd_unlocked_get_package_name (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_package_name", "leave: ret=%s", ret);
  }

  return ret;
}

const char *
nbd_get_version (
  struct nbd_handle *h
)
{
  const char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_get_version",
                  "enter:");
  }

  ret = nbd_unlocked_get_version (h);

  if_debug (h) {
    debug_direct (h, "nbd_get_version", "leave: ret=%s", ret);
  }

  return ret;
}

int
nbd_kill_subprocess (
  struct nbd_handle *h, int signum
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_kill_subprocess");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter: signum=%d",
           signum);
  }

  ret = nbd_unlocked_kill_subprocess (h, signum);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int64_t
nbd_get_subprocess_pid (
  struct nbd_handle *h
)
{
  int64_t ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_subprocess_pid");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  ret = nbd_unlocked_get_subprocess_pid (h);

  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%" PRIi64, ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_supports_tls (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_supports_tls",
                  "enter:");
  }

  ret = nbd_unlocked_supports_tls (h);

  if_debug (h) {
    debug_direct (h, "nbd_supports_tls", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_supports_vsock (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_supports_vsock",
                  "enter:");
  }

  ret = nbd_unlocked_supports_vsock (h);

  if_debug (h) {
    debug_direct (h, "nbd_supports_vsock", "leave: ret=%d", ret);
  }

  return ret;
}

int
nbd_supports_uri (
  struct nbd_handle *h
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  /* This function must not call set_error. */
  if_debug (h) {
    debug_direct (h, "nbd_supports_uri",
                  "enter:");
  }

  ret = nbd_unlocked_supports_uri (h);

  if_debug (h) {
    debug_direct (h, "nbd_supports_uri", "leave: ret=%d", ret);
  }

  return ret;
}

static inline bool
get_uri_in_permitted_state (struct nbd_handle *h)
{
  const enum state state = get_public_state (h);

  if (!(nbd_internal_is_state_connecting (state) ||
        nbd_internal_is_state_negotiating (state) ||
        nbd_internal_is_state_ready (state) ||
        nbd_internal_is_state_processing (state) ||
        nbd_internal_is_state_closed (state) ||
        nbd_internal_is_state_dead (state))) {
    set_error (nbd_internal_is_state_created (state) ? ENOTCONN : EINVAL,
               "invalid state: %s: the handle must be %s",
               nbd_internal_state_short_string (state),
               "connecting, or negotiating, or connected with the server, "
               "or shut down, or dead");
    return false;
  }
  return true;
}

char *
nbd_get_uri (
  struct nbd_handle *h
)
{
  bool p;
  char * ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_get_uri");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    debug (h,
           "enter:");
  }

  p = get_uri_in_permitted_state (h);
  if (unlikely (!p)) {
    ret = NULL;
    goto out;
  }
  ret = nbd_unlocked_get_uri (h);

 out:
  if_debug (h) {
    if (ret == NULL)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      char *ret_printable =
          nbd_internal_printable_string (ret);
      debug (h, "leave: ret=%s", ret_printable ? ret_printable : "");
      free (ret_printable);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

int
nbd_is_uri (
  struct nbd_handle *h, const char *uri
)
{
  int ret;

  assert (h->magic == NBD_HANDLE_MAGIC);
  nbd_internal_set_error_context ("nbd_is_uri");

  pthread_mutex_lock (&h->lock);
  if_debug (h) {
    char *uri_printable =
        nbd_internal_printable_string (uri);
    debug (h,
           "enter: uri=%s",
           uri_printable ? uri_printable : "");
    free (uri_printable);
  }

  if (uri == NULL) {
    set_error (EFAULT, "%s cannot be NULL", "uri");
    ret = -1;
    goto out;
  }
  ret = nbd_unlocked_is_uri (h, uri);

 out:
  if_debug (h) {
    if (ret == -1)
      debug (h, "leave: error=\"%s\"", nbd_get_error ());
    else {
      debug (h, "leave: ret=%d", ret);
    }
  }

  if (h->public_state != get_next_state (h))
    h->public_state = get_next_state (h);
  pthread_mutex_unlock (&h->lock);
  return ret;
}

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           # NBD client library in userspace
# WARNING: THIS FILE IS GENERATED FROM
# generator/generator
# ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
#
# Copyright Red Hat
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

'''
Python bindings for libnbd

import nbd
h = nbd.NBD()
h.connect_tcp("localhost", "nbd")
buf = h.pread(512, 0)

Read the libnbd(3) man page to find out how to use the API.
'''

import contextlib
import libnbdmod

# Re-export Error exception as nbd.Error, adding some methods.
from libnbdmod import Error

Error.__doc__ = '''
Exception thrown when the underlying libnbd call fails.

This exception has three properties to query the error.  Use
the .string property to return a printable string containing
the error message.  Use the .errnum property for the associated
numeric error value (which may be 0 if the error did not
correspond to a system call failure), or the .errno property to
return a string containing the Python errno name if one is known
(which may be None if the numeric value does not correspond to
a known errno name).
'''

Error.string = property(lambda self: self.args[0])


def _errno(self):
    import errno
    try:
        return errno.errorcode[self.args[1]]
    except KeyError:
        return None


Error.errno = property(_errno)

Error.errnum = property(lambda self: self.args[1])


def _str(self):
    if self.errno:
        return "%s (%s)" % (self.string, self.errno)
    else:
        return "%s" % self.string


Error.__str__ = _str


class ClosedHandle(ValueError):
    '''This exception is thrown when any method is called on an
    nbd handle after you have called h.close() on the same handle.'''
    pass


@contextlib.contextmanager
def nbd():
    '''
    This is a context manager function.  Python will close the handle
    automatically even if the body throws an exception:

    with nbd.nbd() as h:
        # use the handle 'h'
    '''
    h = NBD()
    yield h
    h.close()


TLS_DISABLE = 0
TLS_ALLOW = 1
TLS_REQUIRE = 2

SIZE_MINIMUM = 0
SIZE_PREFERRED = 1
SIZE_MAXIMUM = 2
SIZE_PAYLOAD = 3

CMD_FLAG_FUA = 0x01
CMD_FLAG_NO_HOLE = 0x02
CMD_FLAG_DF = 0x04
CMD_FLAG_REQ_ONE = 0x08
CMD_FLAG_FAST_ZERO = 0x10
CMD_FLAG_PAYLOAD_LEN = 0x20
CMD_FLAG_MASK = 0x3f

HANDSHAKE_FLAG_FIXED_NEWSTYLE = 0x01
HANDSHAKE_FLAG_NO_ZEROES = 0x02
HANDSHAKE_FLAG_MASK = 0x03

STRICT_COMMANDS = 0x01
STRICT_FLAGS = 0x02
STRICT_BOUNDS = 0x04
STRICT_ZERO_SIZE = 0x08
STRICT_ALIGN = 0x10
STRICT_PAYLOAD = 0x20
STRICT_AUTO_FLAG = 0x40
STRICT_MASK = 0x7f

ALLOW_TRANSPORT_TCP = 0x01
ALLOW_TRANSPORT_UNIX = 0x02
ALLOW_TRANSPORT_VSOCK = 0x04
ALLOW_TRANSPORT_SSH = 0x08
ALLOW_TRANSPORT_MASK = 0x0f

SHUTDOWN_ABANDON_PENDING = 0x10000
SHUTDOWN_MASK = 0x10000

AIO_DIRECTION_READ = 1
AIO_DIRECTION_WRITE = 2
AIO_DIRECTION_BOTH = 3
READ_DATA = 1
READ_HOLE = 2
READ_ERROR = 3
NAMESPACE_BASE = "base:"
CONTEXT_BASE_ALLOCATION = "base:allocation"
STATE_HOLE = 1
STATE_ZERO = 2
NAMESPACE_QEMU = "qemu:"
CONTEXT_QEMU_DIRTY_BITMAP = "qemu:dirty-bitmap:"
STATE_DIRTY = 1
CONTEXT_QEMU_ALLOCATION_DEPTH = "qemu:allocation-depth"


class Buffer(object):
    '''Asynchronous I/O persistent buffer'''

    def __init__(self, len):
        '''Allocate an uninitialized AIO buffer used for nbd.aio_pread.'''
        self._o = libnbdmod.alloc_aio_buffer(len)

    @classmethod
    def from_buffer(cls, buf):
        '''Create an AIO buffer that shares an existing buffer-like object.

        Because the buffer is shared, changes to the original are visible
        to nbd.aio_pwrite, and changes in nbd.aio_pread are visible to the
        original.
        '''
        self = cls(0)
        # Ensure that buf is already buffer-like
        with memoryview(buf):
            self._o = buf
        self._init = True
        return self

    @classmethod
    def from_bytearray(cls, ba):
        '''Create an AIO buffer from a bytearray or other buffer-like object.

        If ba is not a buffer, it is tried as the parameter to the
        bytearray constructor.  Otherwise, ba is copied.  Either way, the
        resulting AIO buffer is independent from the original.
        '''
        return cls.from_buffer(bytearray(ba))

    def to_buffer(self):
        '''Return a shared view of the AIO buffer contents.

        This exposes the underlying buffer; changes to the buffer are
        visible to nbd.aio_pwrite, and changes from nbd.aio_pread are
        visible in the buffer.
        '''
        if not hasattr(self, '_init'):
            self._o = bytearray(len(self._o))
            self._init = True
        return self._o

    def to_bytearray(self):
        '''Copy an AIO buffer into a bytearray.

        This copies the contents of an AIO buffer to a new bytearray, which
        remains independent from the original.
        '''
        if not hasattr(self, '_init'):
            return bytearray(len(self._o))
        return bytearray(self._o)

    def size(self):
        '''Return the size of an AIO buffer.'''
        return len(self)

    def __len__(self):
        '''Return the size of an AIO buffer.'''
        return len(self._o)

    def is_zero(self, offset=0, size=-1):
        '''Returns true if and only if all bytes in the buffer are zeroes.

        Note that although a freshly allocated buffer is uninitialized,
        this will report it as all zeroes, as it will be force-initialized
        to zero before any code that can access the buffer's contents.

        By default this tests the whole buffer, but you can restrict
        the test to a sub-range of the buffer using the optional
        offset and size parameters.  If size = -1 then we check from
        offset to the end of the buffer.  If size = 0, the function
        always returns true.  If size > 0, we check the interval
        [offset..offset+size-1].
        '''
        return libnbdmod.aio_buffer_is_zero(self._o, offset, size,
                                            hasattr(self, '_init'))


class NBD(object):
    '''NBD handle'''

    def __init__(self):
        '''Create a new NBD handle.'''
        self._o = libnbdmod.create()

    def __del__(self):
        '''Close the NBD handle and underlying connection.'''
        if self._o:
            libnbdmod.close(self._o)
            self._o = None

    def _check_not_closed(self):
        if not self._o:
            raise ClosedHandle("libnbd: method called on closed handle")

    def close(self):
        '''Explicitly close the NBD handle and underlying connection.

        The handle is closed implicitly when its reference count goes
        to zero (eg. when it goes out of scope or the program ends).

        This call is only needed if you want to force the handle to
        close now.  After calling this, the program must not call
        any method on the handle (except the implicit call to
        __del__ which happens when the final reference is cleaned up).
        '''
        self._check_not_closed()
        libnbdmod.close(self._o)
        self._o = None

    def set_debug(self, debug):
        u'''▶ set or clear the debug flag

    Set or clear the debug flag. When debugging is enabled,
    debugging messages from the library are printed to
    stderr, unless a debugging callback has been defined too
    (see "nbd.set_debug_callback") in which case they are
    sent to that function. This flag defaults to false on
    newly created handles, except if "LIBNBD_DEBUG=1" is set
    in the environment in which case it defaults to true.
'''
        self._check_not_closed()
        return libnbdmod.set_debug(self._o, debug)

    def get_debug(self):
        u'''▶ return the state of the debug flag

    Return the state of the debug flag on this handle.
'''
        self._check_not_closed()
        return libnbdmod.get_debug(self._o)

    def set_debug_callback(self, debug):
        u'''▶ set the debug callback

    Set the debug callback. This function is called when the
    library emits debug messages, when debugging is enabled
    on a handle. The callback parameters are "user_data"
    passed to this function, the name of the libnbd function
    emitting the debug message ("context"), and the message
    itself ("msg"). If no debug callback is set on a handle
    then messages are printed on "stderr".

    The callback should not call "nbd_*" APIs on the same
    handle since it can be called while holding the handle
    lock and will cause a deadlock.
'''
        self._check_not_closed()
        return libnbdmod.set_debug_callback(self._o, debug)

    def clear_debug_callback(self):
        u'''▶ clear the debug callback

    Remove the debug callback if one was previously
    associated with the handle (with
    "nbd.set_debug_callback"). If no callback was associated
    this does nothing.
'''
        self._check_not_closed()
        return libnbdmod.clear_debug_callback(self._o)

    def stats_bytes_sent(self):
        u'''▶ statistics of bytes sent over connection so far

    Return the number of bytes that the client has sent to
    the server.

    This tracks the plaintext bytes utilized by the NBD
    protocol; it may differ from the number of bytes
    actually sent over the connection, particularly when TLS
    is in use.
'''
        self._check_not_closed()
        return libnbdmod.stats_bytes_sent(self._o)

    def stats_chunks_sent(self):
        u'''▶ statistics of chunks sent over connection so far

    Return the number of chunks that the client has sent to
    the server, where a chunk is a group of bytes delineated
    by a magic number that cannot be further subdivided
    without breaking the protocol.

    This number does not necessarily relate to the number of
    API calls made, nor to the number of TCP packets sent
    over the connection.
'''
        self._check_not_closed()
        return libnbdmod.stats_chunks_sent(self._o)

    def stats_bytes_received(self):
        u'''▶ statistics of bytes received over connection so far

    Return the number of bytes that the client has received
    from the server.

    This tracks the plaintext bytes utilized by the NBD
    protocol; it may differ from the number of bytes
    actually received over the connection, particularly when
    TLS is in use.
'''
        self._check_not_closed()
        return libnbdmod.stats_bytes_received(self._o)

    def stats_chunks_received(self):
        u'''▶ statistics of chunks received over connection so far

    Return the number of chunks that the client has received
    from the server, where a chunk is a group of bytes
    delineated by a magic number that cannot be further
    subdivided without breaking the protocol.

    This number does not necessarily relate to the number of
    API calls made, nor to the number of TCP packets
    received over the connection.
'''
        self._check_not_closed()
        return libnbdmod.stats_chunks_received(self._o)

    def set_handle_name(self, handle_name):
        u'''▶ set the handle name

    Handles have a name which is unique within the current
    process. The handle name is used in debug output.

    Handle names are normally generated automatically and
    have the form "nbd1", "nbd2", etc., but you can
    optionally use this call to give the handles a name
    which is meaningful for your application to make
    debugging output easier to understand.
'''
        self._check_not_closed()
        return libnbdmod.set_handle_name(self._o, handle_name)

    def get_handle_name(self):
        u'''▶ get the handle name

    Get the name of the handle. If it was previously set by
    calling "nbd.set_handle_name" then this returns the name
    that was set. Otherwise it will return a generic name
    like "nbd1", "nbd2", etc.
'''
        self._check_not_closed()
        return libnbdmod.get_handle_name(self._o)

    def set_private_data(self, private_data):
        u'''▶ set the per-handle private data

    Handles contain a private data field for applications to
    use for any purpose.

    When calling libnbd from C, the type of this field is
    "uintptr_t" so it can be used to store an unsigned
    integer or a pointer.

    In non-C bindings it can be used to store an unsigned
    integer.

    This function sets the value of this field and returns
    the old value (or 0 if it was not previously set).
'''
        self._check_not_closed()
        return libnbdmod.set_private_data(self._o, private_data)

    def get_private_data(self):
        u'''▶ get the per-handle private data

    Return the value of the private data field set
    previously by a call to "nbd.set_private_data" (or 0 if
    it was not previously set).
'''
        self._check_not_closed()
        return libnbdmod.get_private_data(self._o)

    def set_export_name(self, export_name):
        u'''▶ set the export name

    For servers which require an export name or can serve
    different content on different exports, set the
    "export_name" to connect to. The default is the empty
    string "".

    This is only relevant when connecting to servers using
    the newstyle protocol as the oldstyle protocol did not
    support export names. The NBD protocol limits export
    names to 4096 bytes, but servers may not support the
    full length. The encoding of export names is always
    UTF-8.

    When option mode is not in use, the export name must be
    set before beginning a connection. However, when
    "nbd.set_opt_mode" has enabled option mode, it is
    possible to change the export name prior to
    "nbd.opt_go". In particular, the use of "nbd.opt_list"
    during negotiation can be used to determine a name the
    server is likely to accept, and "nbd.opt_info" can be
    used to learn details about an export before connecting.

    This call may be skipped if using "nbd.connect_uri" to
    connect to a URI that includes an export name.
'''
        self._check_not_closed()
        return libnbdmod.set_export_name(self._o, export_name)

    def get_export_name(self):
        u'''▶ get the export name

    Get the export name associated with the handle. This is
    the name that libnbd requests; see
    "nbd.get_canonical_export_name" for determining if the
    server has a different canonical name for the given
    export (most common when requesting the default export
    name of an empty string "")
'''
        self._check_not_closed()
        return libnbdmod.get_export_name(self._o)

    def set_request_block_size(self, request):
        u'''▶ control whether NBD_OPT_GO requests block size

    By default, when connecting to an export, libnbd
    requests that the server report any block size
    restrictions. The NBD protocol states that a server may
    supply block sizes regardless of whether the client
    requests them, and libnbd will report those block sizes
    (see "nbd.get_block_size"); conversely, if a client does
    not request block sizes, the server may reject the
    connection instead of dealing with a client sending
    unaligned requests. This function makes it possible to
    test server behavior by emulating older clients.

    Note that even when block size is requested, the server
    is not obligated to provide any. Furthermore, if block
    sizes are provided (whether or not the client requested
    them), libnbd enforces alignment to those sizes unless
    "nbd.set_strict_mode" is used to bypass client-side
    safety checks.
'''
        self._check_not_closed()
        return libnbdmod.set_request_block_size(self._o, request)

    def get_request_block_size(self):
        u'''▶ see if NBD_OPT_GO requests block size

    Return the state of the block size request flag on this
    handle.
'''
        self._check_not_closed()
        return libnbdmod.get_request_block_size(self._o)

    def set_full_info(self, request):
        u'''▶ control whether NBD_OPT_GO requests extra details

    By default, when connecting to an export, libnbd only
    requests the details it needs to service data
    operations. The NBD protocol says that a server can
    supply optional information, such as a canonical name of
    the export (see "nbd.get_canonical_export_name") or a
    description of the export (see
    "nbd.get_export_description"), but that a hint from the
    client makes it more likely for this extra information
    to be provided. This function controls whether libnbd
    will provide that hint.

    Note that even when full info is requested, the server
    is not obligated to reply with all information that
    libnbd requested. Similarly, libnbd will ignore any
    optional server information that libnbd has not yet been
    taught to recognize. Furthermore, the hint to request
    block sizes is independently controlled via
    "nbd.set_request_block_size".
'''
        self._check_not_closed()
        return libnbdmod.set_full_info(self._o, request)

    def get_full_info(self):
        u'''▶ see if NBD_OPT_GO requests extra details

    Return the state of the full info request flag on this
    handle.
'''
        self._check_not_closed()
        return libnbdmod.get_full_info(self._o)

    def get_canonical_export_name(self):
        u'''▶ return the canonical export name, if the server has one

    The NBD protocol permits a server to report an optional
    canonical export name, which may differ from the
    client's request (as set by "nbd.set_export_name" or
    "nbd.connect_uri"). This function accesses any name
    returned by the server; it may be the same as the client
    request, but is more likely to differ when the client
    requested a connection to the default export name (an
    empty string "").

    Some servers are unlikely to report a canonical name
    unless the client specifically hinted about wanting it,
    via "nbd.set_full_info".
'''
        self._check_not_closed()
        return libnbdmod.get_canonical_export_name(self._o)

    def get_export_description(self):
        u'''▶ return the export description, if the server has one

    The NBD protocol permits a server to report an optional
    export description. This function reports any
    description returned by the server.

    Some servers are unlikely to report a description unless
    the client specifically hinted about wanting it, via
    "nbd.set_full_info". For qemu-nbd(8), a description is
    set with *-D*.
'''
        self._check_not_closed()
        return libnbdmod.get_export_description(self._o)

    def set_tls(self, tls):
        u'''▶ enable or require TLS (authentication and encryption)

    Enable or require TLS (authenticated and encrypted
    connections) to the NBD server. The possible settings
    are:

    "TLS_DISABLE"
        Disable TLS. (The default setting, unless using
        "nbd.connect_uri" with a URI that requires TLS).

        This setting is also necessary if you use
        "nbd.set_opt_mode" and want to interact in plaintext
        with a server that implements the NBD protocol's
        "SELECTIVETLS" mode, prior to enabling TLS with
        "nbd.opt_starttls". Most NBD servers with TLS
        support prefer the NBD protocol's "FORCEDTLS" mode,
        so this sort of manual interaction tends to be
        useful mainly during integration testing.

    "TLS_ALLOW"
        Enable TLS if possible.

        This option is insecure (or best effort) in that in
        some cases it will fall back to an unencrypted
        and/or unauthenticated connection if TLS could not
        be established. Use "TLS_REQUIRE" below if the
        connection must be encrypted.

        Some servers will drop the connection if TLS fails
        so fallback may not be possible.

    "TLS_REQUIRE"
        Require an encrypted and authenticated TLS
        connection. Always fail to connect if the connection
        is not encrypted and authenticated.

    As well as calling this you may also need to supply the
    path to the certificates directory
    ("nbd.set_tls_certificates"), the username
    ("nbd.set_tls_username") and/or the Pre-Shared Keys
    (PSK) file ("nbd.set_tls_psk_file"). For now, when using
    "nbd.connect_uri", any URI query parameters related to
    TLS are not handled automatically. Setting the level
    higher than zero will fail if libnbd was not compiled
    against gnutls; you can test whether this is the case
    with "nbd.supports_tls".
'''
        self._check_not_closed()
        return libnbdmod.set_tls(self._o, tls)

    def get_tls(self):
        u'''▶ get the TLS request setting

    Get the TLS request setting.

    Note: If you want to find out if TLS was actually
    negotiated on a particular connection use
    "nbd.get_tls_negotiated" instead.
'''
        self._check_not_closed()
        return libnbdmod.get_tls(self._o)

    def get_tls_negotiated(self):
        u'''▶ find out if TLS was negotiated on a connection

    After connecting you may call this to find out if the
    connection is using TLS.

    This is normally useful only if you set the TLS request
    mode to "TLS_ALLOW" (see "nbd.set_tls"), because in this
    mode we try to use TLS but fall back to unencrypted if
    it was not available. This function will tell you if TLS
    was negotiated or not.

    In "TLS_REQUIRE" mode (the most secure) the connection
    would have failed if TLS could not be negotiated. With
    "TLS_DISABLE" mode, TLS is not tried automatically; but
    if the NBD server uses the less-common "SELECTIVETLS"
    mode, this function reports whether a manual
    "nbd.opt_starttls" enabled TLS or if the connection is
    still plaintext.
'''
        self._check_not_closed()
        return libnbdmod.get_tls_negotiated(self._o)

    def set_tls_certificates(self, dir):
        u'''▶ set the path to the TLS certificates directory

    Set the path to the TLS certificates directory. If not
    set and TLS is used then a compiled in default is used.
    For root this is "/etc/pki/libnbd/". For non-root this
    is "$HOME/.pki/libnbd" and "$HOME/.config/pki/libnbd".
    If none of these directories can be found then the
    system trusted CAs are used.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless "nbd.set_tls"
    is also used to request or require TLS.
'''
        self._check_not_closed()
        return libnbdmod.set_tls_certificates(self._o, dir)

    def set_tls_verify_peer(self, verify):
        u'''▶ set whether we verify the identity of the server

    Set this flag to control whether libnbd will verify the
    identity of the server from the server's certificate and
    the certificate authority. This defaults to true when
    connecting to TCP servers using TLS certificate
    authentication, and false otherwise.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless "nbd.set_tls"
    is also used to request or require TLS.
'''
        self._check_not_closed()
        return libnbdmod.set_tls_verify_peer(self._o, verify)

    def get_tls_verify_peer(self):
        u'''▶ get whether we verify the identity of the server

    Get the verify peer flag.
'''
        self._check_not_closed()
        return libnbdmod.get_tls_verify_peer(self._o)

    def set_tls_username(self, username):
        u'''▶ set the TLS username

    Set the TLS client username. This is used if
    authenticating with PSK over TLS is enabled. If not set
    then the local username is used.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless "nbd.set_tls"
    is also used to request or require TLS.
'''
        self._check_not_closed()
        return libnbdmod.set_tls_username(self._o, username)

    def get_tls_username(self):
        u'''▶ get the current TLS username

    Get the current TLS username.
'''
        self._check_not_closed()
        return libnbdmod.get_tls_username(self._o)

    def set_tls_hostname(self, hostname):
        u'''▶ set the TLS hostname

    Set the TLS server hostname. This is used in preference
    to the hostname supplied when connecting (eg. through
    "nbd.connect_tcp"), or when there is no explicit
    hostname at all ("nbd.connect_unix"). It can be useful
    when you are connecting to a proxy which is forwarding
    the data to the final server, to specify the name of the
    final server so that the server's certificate can be
    checked.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless "nbd.set_tls"
    is also used to request or require TLS.
'''
        self._check_not_closed()
        return libnbdmod.set_tls_hostname(self._o, hostname)

    def get_tls_hostname(self):
        u'''▶ get the effective TLS hostname

    Get the TLS server hostname in effect. If not set, this
    returns the empty string (not an error).
'''
        self._check_not_closed()
        return libnbdmod.get_tls_hostname(self._o)

    def set_tls_psk_file(self, filename):
        u'''▶ set the TLS Pre-Shared Keys (PSK) filename

    Set the TLS Pre-Shared Keys (PSK) filename. This is used
    if trying to authenticate to the server using with a
    pre-shared key. There is no default so if this is not
    set then PSK authentication cannot be used to connect to
    the server.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless "nbd.set_tls"
    is also used to request or require TLS.
'''
        self._check_not_closed()
        return libnbdmod.set_tls_psk_file(self._o, filename)

    def set_request_extended_headers(self, request):
        u'''▶ control use of extended headers

    By default, libnbd tries to negotiate extended headers
    with the server, as this protocol extension permits the
    use of 64-bit zero, trim, and block status actions.
    However, for integration testing, it can be useful to
    clear this flag rather than find a way to alter the
    server to fail the negotiation request.

    For backwards compatibility, the setting of this knob is
    ignored if "nbd.set_request_structured_replies" is also
    set to false, since the use of extended headers implies
    structured replies.
'''
        self._check_not_closed()
        return libnbdmod.set_request_extended_headers(self._o, request)

    def get_request_extended_headers(self):
        u'''▶ see if extended headers are attempted

    Return the state of the request extended headers flag on
    this handle.

    Note: If you want to find out if extended headers were
    actually negotiated on a particular connection use
    "nbd.get_extended_headers_negotiated" instead.
'''
        self._check_not_closed()
        return libnbdmod.get_request_extended_headers(self._o)

    def get_extended_headers_negotiated(self):
        u'''▶ see if extended headers are in use

    After connecting you may call this to find out if the
    connection is using extended headers. Note that this
    setting is sticky; this can return true even after a
    second "nbd.opt_extended_headers" returns false because
    the server detected a duplicate request.

    When extended headers are not in use, commands are
    limited to a 32-bit length, even when the libnbd API
    uses a 64-bit parameter to express the length. But even
    when extended headers are supported, the server may
    enforce other limits, visible through
    "nbd.get_block_size".

    Note that when extended headers are negotiated, you
    should prefer the use of "nbd.block_status_64" instead
    of "nbd.block_status" if any of the meta contexts you
    requested via "nbd.add_meta_context" might return 64-bit
    status values; however, all of the well-known meta
    contexts covered by current "LIBNBD_CONTEXT_*" constants
    only return 32-bit status.
'''
        self._check_not_closed()
        return libnbdmod.get_extended_headers_negotiated(self._o)

    def set_request_structured_replies(self, request):
        u'''▶ control use of structured replies

    By default, libnbd tries to negotiate structured replies
    with the server, as this protocol extension must be in
    use before "nbd.can_meta_context" or "nbd.can_df" can
    return true. However, for integration testing, it can be
    useful to clear this flag rather than find a way to
    alter the server to fail the negotiation request. It is
    also useful to set this to false prior to using
    "nbd.set_opt_mode" if it is desired to control when to
    send "nbd.opt_structured_reply" during negotiation.

    Note that setting this knob to false also disables any
    automatic request for extended headers.
'''
        self._check_not_closed()
        return libnbdmod.set_request_structured_replies(self._o, request)

    def get_request_structured_replies(self):
        u'''▶ see if structured replies are attempted

    Return the state of the request structured replies flag
    on this handle.

    Note: If you want to find out if structured replies were
    actually negotiated on a particular connection use
    "nbd.get_structured_replies_negotiated" instead.
'''
        self._check_not_closed()
        return libnbdmod.get_request_structured_replies(self._o)

    def get_structured_replies_negotiated(self):
        u'''▶ see if structured replies are in use

    After connecting you may call this to find out if the
    connection is using structured replies. Note that this
    setting is sticky; this can return true even after a
    second "nbd.opt_structured_reply" returns false because
    the server detected a duplicate request.

    Note that if the connection negotiates extended headers,
    this function returns true (as extended headers imply
    structured replies) even if no explicit request for
    structured replies was attempted.
'''
        self._check_not_closed()
        return libnbdmod.get_structured_replies_negotiated(self._o)

    def set_request_meta_context(self, request):
        u'''▶ control whether connect automatically requests meta contexts

    This function controls whether the act of connecting to
    an export (all "nbd_connect_*" calls when
    "nbd.set_opt_mode" is false, or "nbd.opt_go" and
    "nbd.opt_info" when option mode is enabled) will also
    try to issue NBD_OPT_SET_META_CONTEXT when the server
    supports structured replies or extended headers and any
    contexts were registered by "nbd.add_meta_context". The
    default setting is true; however the extra step of
    negotiating meta contexts is not always desirable:
    performing both info and go on the same export works
    without needing to re-negotiate contexts on the second
    call; integration testing of other servers may benefit
    from manual invocation of "nbd.opt_set_meta_context" at
    other times in the negotiation sequence; and even when
    using just "nbd.opt_info", it can be faster to collect
    the server's results by relying on the callback function
    passed to "nbd.opt_list_meta_context" than a series of
    post-process calls to "nbd.can_meta_context".

    Note that this control has no effect if the server does
    not negotiate structured replies or extended headers, or
    if the client did not request any contexts via
    "nbd.add_meta_context". Setting this control to false
    may cause "nbd.block_status" to fail.
'''
        self._check_not_closed()
        return libnbdmod.set_request_meta_context(self._o, request)

    def get_request_meta_context(self):
        u'''▶ see if connect automatically requests meta contexts

    Return the state of the automatic meta context request
    flag on this handle.
'''
        self._check_not_closed()
        return libnbdmod.get_request_meta_context(self._o)

    def set_handshake_flags(self, flags):
        u'''▶ control use of handshake flags

    By default, libnbd tries to negotiate all possible
    handshake flags that are also supported by the server,
    since omitting a handshake flag can prevent the use of
    other functionality such as TLS encryption or structured
    replies. However, for integration testing, it can be
    useful to reduce the set of flags supported by the
    client to test that a particular server can handle
    various clients that were compliant to older versions of
    the NBD specification.

    The "flags" argument is a bitmask, including zero or
    more of the following handshake flags:

    "HANDSHAKE_FLAG_FIXED_NEWSTYLE" = 1
        The server gracefully handles unknown option
        requests from the client, rather than disconnecting.
        Without this flag, a client cannot safely request to
        use extensions such as TLS encryption or structured
        replies, as the request may cause an older server to
        drop the connection.

    "HANDSHAKE_FLAG_NO_ZEROES" = 2
        If the client is forced to use "NBD_OPT_EXPORT_NAME"
        instead of the preferred "NBD_OPT_GO", this flag
        allows the server to send fewer all-zero padding
        bytes over the connection.

    For convenience, the constant "HANDSHAKE_FLAG_MASK" is
    available to describe all flags supported by this build
    of libnbd. Future NBD extensions may add further flags,
    which in turn may be enabled by default in newer libnbd.
    As such, when attempting to disable only one specific
    bit, it is wiser to first call "nbd.get_handshake_flags"
    and modify that value, rather than blindly setting a
    constant value.
'''
        self._check_not_closed()
        return libnbdmod.set_handshake_flags(self._o, flags)

    def get_handshake_flags(self):
        u'''▶ see which handshake flags are supported

    Return the state of the handshake flags on this handle.
    When the handle has not yet completed a connection (see
    "nbd.aio_is_created"), this returns the flags that the
    client is willing to use, provided the server also
    advertises those flags. After the connection is ready
    (see "nbd.aio_is_ready"), this returns the flags that
    were actually agreed on between the server and client.
    If the NBD protocol defines new handshake flags, then
    the return value from a newer library version may
    include bits that were undefined at the time of
    compilation.
'''
        self._check_not_closed()
        return libnbdmod.get_handshake_flags(self._o)

    def set_pread_initialize(self, request):
        u'''▶ control whether libnbd pre-initializes read buffers

    By default, libnbd will pre-initialize the contents of a
    buffer passed to calls such as "nbd.pread" to all zeroes
    prior to checking for any other errors, so that even if
    a client application passed in an uninitialized buffer
    but fails to check for errors, it will not result in a
    potential security risk caused by an accidental leak of
    prior heap contents (see CVE-2022-0485 in
    libnbd-security(3) for an example of a security hole in
    an application built against an earlier version of
    libnbd that lacked consistent pre-initialization).
    However, for a client application that has audited that
    an uninitialized buffer is never dereferenced, or which
    performs its own pre-initialization, libnbd's
    sanitization efforts merely pessimize performance
    (although the time spent in pre-initialization may pale
    in comparison to time spent waiting on network packets).

    Calling this function with "request" set to false tells
    libnbd to skip the buffer initialization step in read
    commands.
'''
        self._check_not_closed()
        return libnbdmod.set_pread_initialize(self._o, request)

    def get_pread_initialize(self):
        u'''▶ see whether libnbd pre-initializes read buffers

    Return whether libnbd performs a pre-initialization of a
    buffer passed to "nbd.pread" and similar to all zeroes,
    as set by "nbd.set_pread_initialize".
'''
        self._check_not_closed()
        return libnbdmod.get_pread_initialize(self._o)

    def set_strict_mode(self, flags):
        u'''▶ control how strictly to follow NBD protocol

    By default, libnbd tries to detect requests that would
    trigger undefined behavior in the NBD protocol, and
    rejects them client side without causing any network
    traffic, rather than risking undefined server behavior.
    However, for integration testing, it can be handy to
    relax the strictness of libnbd, to coerce it into
    sending such requests over the network for testing the
    robustness of the server in dealing with such traffic.

    The "flags" argument is a bitmask, including zero or
    more of the following strictness flags:

    "STRICT_COMMANDS" = 0x1
        If set, this flag rejects client requests that do
        not comply with the set of advertised server flags
        (for example, attempting a write on a read-only
        server, or attempting to use "CMD_FLAG_FUA" when
        "nbd.can_fua" returned false). If clear, this flag
        relies on the server to reject unexpected commands.

    "STRICT_FLAGS" = 0x2
        If set, this flag rejects client requests that
        attempt to set a command flag not recognized by
        libnbd (those outside of "CMD_FLAG_MASK"), or a flag
        not normally associated with a command (such as
        using "CMD_FLAG_FUA" on a read command). If clear,
        all flags are sent on to the server, even if sending
        such a flag may cause the server to change its reply
        in a manner that confuses libnbd, perhaps causing
        deadlock or ending the connection.

        Flags that are known by libnbd as associated with a
        given command (such as "CMD_FLAG_DF" for
        "nbd.pread_structured" gated by "nbd.can_df") are
        controlled by "STRICT_COMMANDS" instead; and
        "CMD_FLAG_PAYLOAD_LEN" is managed automatically by
        libnbd unless "STRICT_AUTO_FLAG" is disabled.

        Note that the NBD protocol only supports 16 bits of
        command flags, even though the libnbd API uses
        "uint32_t"; bits outside of the range permitted by
        the protocol are always a client-side error.

    "STRICT_BOUNDS" = 0x4
        If set, this flag rejects client requests that would
        exceed the export bounds without sending any traffic
        to the server. If clear, this flag relies on the
        server to detect out-of-bounds requests.

    "STRICT_ZERO_SIZE" = 0x8
        If set, this flag rejects client requests with
        length 0. If clear, this permits zero-length
        requests to the server, which may produce undefined
        results.

    "STRICT_ALIGN" = 0x10
        If set, and the server provided minimum block sizes
        (see "SIZE_MINIMUM" for "nbd.get_block_size"), this
        flag rejects client requests that do not have length
        and offset aligned to the server's minimum
        requirements, except for an unaligned length that
        extends to the end of an image with an overall
        unaligned size. If clear, all unaligned requests are
        sent to the server, where it is up to the server
        whether to honor or reject the request.

    "STRICT_PAYLOAD" = 0x20
        If set, the client refuses to send a command to the
        server with more than libnbd's outgoing payload
        maximum (see "SIZE_PAYLOAD" for
        "nbd.get_block_size"), whether or not the server
        advertised a block size maximum. If clear, oversize
        requests up to 64MiB may be attempted, although
        requests larger than 32MiB are liable to cause some
        servers to disconnect.

    "STRICT_AUTO_FLAG" = 0x40
        If set, commands that accept the
        "CMD_FLAG_PAYLOAD_LEN" flag (such as "nbd.pwrite"
        and nbd_block_status_filter(3)) ignore the presence
        or absence of that flag from the caller, instead
        sending the value over the wire that matches the
        server's expectations based on whether extended
        headers were negotiated when the connection was
        made. If clear, the caller takes on the
        responsibility for whether the payload length flag
        is set or clear during the affected command, which
        can be useful during integration testing but is more
        likely to lead to undefined behavior.

    For convenience, the constant "STRICT_MASK" is available
    to describe all strictness flags supported by this build
    of libnbd. Future versions of libnbd may add further
    flags, which are likely to be enabled by default for
    additional client-side filtering. As such, when
    attempting to relax only one specific bit while keeping
    remaining checks at the client side, it is wiser to
    first call "nbd.get_strict_mode" and modify that value,
    rather than blindly setting a constant value.
'''
        self._check_not_closed()
        return libnbdmod.set_strict_mode(self._o, flags)

    def get_strict_mode(self):
        u'''▶ see which strictness flags are in effect

    Return flags indicating which protocol strictness items
    are being enforced locally by libnbd rather than the
    server. The return value from a newer library version
    may include bits that were undefined at the time of
    compilation.
'''
        self._check_not_closed()
        return libnbdmod.get_strict_mode(self._o)

    def set_opt_mode(self, enable):
        u'''▶ control option mode, for pausing during option negotiation

    Set this flag to true in order to request that a
    connection command "nbd_connect_*" will pause for
    negotiation options rather than proceeding all the way
    to the ready state, when communicating with a newstyle
    server. This setting has no effect when connecting to an
    oldstyle server.

    Note that libnbd defaults to attempting
    "NBD_OPT_STARTTLS", "NBD_OPT_EXTENDED_HEADERS", and
    "NBD_OPT_STRUCTURED_REPLY" before letting you control
    remaining negotiation steps; if you need control over
    these steps as well, first set "nbd.set_tls" to
    "TLS_DISABLE", and "nbd.set_request_extended_headers" or
    "nbd.set_request_structured_replies" to false, before
    starting the connection attempt.

    When option mode is enabled, you have fine-grained
    control over which options are negotiated, compared to
    the default of the server negotiating everything on your
    behalf using settings made before starting the
    connection. To leave the mode and proceed on to the
    ready state, you must use "nbd.opt_go" successfully; a
    failed "nbd.opt_go" returns to the negotiating state to
    allow a change of export name before trying again. You
    may also use "nbd.opt_abort" or "nbd.shutdown" to end
    the connection without finishing negotiation.
'''
        self._check_not_closed()
        return libnbdmod.set_opt_mode(self._o, enable)

    def get_opt_mode(self):
        u'''▶ return whether option mode was enabled

    Return true if option negotiation mode was enabled on
    this handle.
'''
        self._check_not_closed()
        return libnbdmod.get_opt_mode(self._o)

    def opt_go(self):
        u'''▶ end negotiation and move on to using an export

    Request that the server finish negotiation and move on
    to serving the export previously specified by the most
    recent "nbd.set_export_name" or "nbd.connect_uri". This
    can only be used if "nbd.set_opt_mode" enabled option
    mode.

    By default, libnbd will automatically request all meta
    contexts registered by "nbd.add_meta_context" as part of
    this call; but this can be suppressed with
    "nbd.set_request_meta_context", particularly if
    "nbd.opt_set_meta_context" was used earlier in the
    negotiation sequence.

    If this fails, the server may still be in negotiation,
    where it is possible to attempt another option such as a
    different export name; although older servers will
    instead have killed the connection.
'''
        self._check_not_closed()
        return libnbdmod.opt_go(self._o)

    def opt_abort(self):
        u'''▶ end negotiation and close the connection

    Request that the server finish negotiation, gracefully
    if possible, then close the connection. This can only be
    used if "nbd.set_opt_mode" enabled option mode.
'''
        self._check_not_closed()
        return libnbdmod.opt_abort(self._o)

    def opt_starttls(self):
        u'''▶ request the server to initiate TLS

    Request that the server initiate a secure TLS
    connection, by sending "NBD_OPT_STARTTLS". This can only
    be used if "nbd.set_opt_mode" enabled option mode;
    furthermore, if you use "nbd.set_tls" to request
    anything other than the default of "TLS_DISABLE", then
    libnbd will have already attempted a TLS connection
    prior to allowing you control over option negotiation.
    This command is disabled if "nbd.supports_tls" reports
    false.

    This function is mainly useful for integration testing
    of corner cases in server handling; in particular,
    misuse of this function when coupled with a server that
    is not careful about resetting stateful commands such as
    "nbd.opt_structured_reply" could result in a security
    hole (see CVE-2021-3716 against nbdkit, for example).
    Thus, when security is a concern, you should instead
    prefer to use "nbd.set_tls" with "TLS_REQUIRE" and let
    libnbd negotiate TLS automatically.

    This function returns true if the server replies with
    success, false if the server replies with an error, and
    fails only if the server does not reply (such as for a
    loss of connection, which can include when the server
    rejects credentials supplied during the TLS handshake).
    Note that the NBD protocol documents that requesting TLS
    after it is already enabled is a client error; most
    servers will gracefully fail a second request, but that
    does not downgrade a TLS session that has already been
    established, as reported by "nbd.get_tls_negotiated".
'''
        self._check_not_closed()
        return libnbdmod.opt_starttls(self._o)

    def opt_extended_headers(self):
        u'''▶ request the server to enable extended headers

    Request that the server use extended headers, by sending
    "NBD_OPT_EXTENDED_HEADERS". This can only be used if
    "nbd.set_opt_mode" enabled option mode; furthermore,
    libnbd defaults to automatically requesting this unless
    you use "nbd.set_request_extended_headers" or
    "nbd.set_request_structured_replies" prior to
    connecting. This function is mainly useful for
    integration testing of corner cases in server handling.

    This function returns true if the server replies with
    success, false if the server replies with an error, and
    fails only if the server does not reply (such as for a
    loss of connection). Note that some servers fail a
    second request as redundant; libnbd assumes that once
    one request has succeeded, then extended headers are
    supported (as visible by
    "nbd.get_extended_headers_negotiated") regardless if
    later calls to this function return false. If this
    function returns true, the use of structured replies is
    implied.
'''
        self._check_not_closed()
        return libnbdmod.opt_extended_headers(self._o)

    def opt_structured_reply(self):
        u'''▶ request the server to enable structured replies

    Request that the server use structured replies, by
    sending "NBD_OPT_STRUCTURED_REPLY". This can only be
    used if "nbd.set_opt_mode" enabled option mode;
    furthermore, libnbd defaults to automatically requesting
    this unless you use "nbd.set_request_structured_replies"
    prior to connecting. This function is mainly useful for
    integration testing of corner cases in server handling.

    This function returns true if the server replies with
    success, false if the server replies with an error, and
    fails only if the server does not reply (such as for a
    loss of connection). Note that some servers fail a
    second request as redundant; libnbd assumes that once
    one request has succeeded, then structured replies are
    supported (as visible by
    "nbd.get_structured_replies_negotiated") regardless if
    later calls to this function return false. Similarly, a
    server may fail this request if extended headers are
    already negotiated, since extended headers take
    priority.
'''
        self._check_not_closed()
        return libnbdmod.opt_structured_reply(self._o)

    def opt_list(self, list):
        u'''▶ request the server to list all exports during negotiation

    Request that the server list all exports that it
    supports. This can only be used if "nbd.set_opt_mode"
    enabled option mode.

    The "list" function is called once per advertised
    export, with any "user_data" passed to this function,
    and with "name" and "description" supplied by the
    server. Many servers omit descriptions, in which case
    "description" will be an empty string. Remember that it
    is not safe to call "nbd.set_export_name" from within
    the context of the callback function; rather, your code
    must copy any "name" needed for later use after this
    function completes. At present, the return value of the
    callback is ignored, although a return of -1 should be
    avoided.

    For convenience, when this function succeeds, it returns
    the number of exports that were advertised by the
    server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list to avoid being an information leak, may
    encounter a failure after delivering partial results, or
    may refuse to answer more than one query per connection
    in the interest of avoiding negotiation that does not
    resolve. Thus, this function may succeed even when no
    exports are reported, or may fail but have a non-empty
    list. Likewise, the NBD protocol does not specify an
    upper bound for the number of exports that might be
    advertised, so client code should be aware that a server
    may send a lengthy list.

    For nbd-server(1) you will need to allow clients to make
    list requests by adding "allowlist=true" to the
    "[generic]" section of /etc/nbd-server/config. For
    qemu-nbd(8), a description is set with *-D*.
'''
        self._check_not_closed()
        return libnbdmod.opt_list(self._o, list)

    def opt_info(self):
        u'''▶ request the server for information about an export

    Request that the server supply information about the
    export name previously specified by the most recent
    "nbd.set_export_name" or "nbd.connect_uri". This can
    only be used if "nbd.set_opt_mode" enabled option mode.

    If successful, functions like "nbd.is_read_only" and
    "nbd.get_size" will report details about that export. If
    "nbd.set_request_meta_context" is set (the default) and
    structured replies or extended headers were negotiated,
    it is also valid to use "nbd.can_meta_context" after
    this call. However, it may be more efficient to clear
    that setting and manually utilize
    "nbd.opt_list_meta_context" with its callback approach,
    for learning which contexts an export supports. In
    general, if "nbd.opt_go" is called next, that call will
    likely succeed with the details remaining the same,
    although this is not guaranteed by all servers.

    Not all servers understand this request, and even when
    it is understood, the server might fail the request even
    when a corresponding "nbd.opt_go" would succeed.
'''
        self._check_not_closed()
        return libnbdmod.opt_info(self._o)

    def opt_list_meta_context(self, context):
        u'''▶ list available meta contexts, using implicit query list

    Request that the server list available meta contexts
    associated with the export previously specified by the
    most recent "nbd.set_export_name" or "nbd.connect_uri",
    and with a list of queries from prior calls to
    "nbd.add_meta_context" (see
    "nbd.opt_list_meta_context_queries" if you want to
    supply an explicit query list instead). This can only be
    used if "nbd.set_opt_mode" enabled option mode.

    The NBD protocol allows a client to decide how many
    queries to ask the server. Rather than taking that list
    of queries as a parameter to this function, libnbd
    reuses the current list of requested meta contexts as
    set by "nbd.add_meta_context"; you can use
    "nbd.clear_meta_contexts" to set up a different list of
    queries. When the list is empty, a server will typically
    reply with all contexts that it supports; when the list
    is non-empty, the server will reply only with supported
    contexts that match the client's request. Note that a
    reply by the server might be encoded to represent
    several feasible contexts within one string, rather than
    multiple strings per actual context name that would
    actually succeed during "nbd.opt_go"; so it is still
    necessary to use "nbd.can_meta_context" after connecting
    to see which contexts are actually supported.

    The "context" function is called once per server reply,
    with any "user_data" passed to this function, and with
    "name" supplied by the server. Remember that it is not
    safe to call "nbd.add_meta_context" from within the
    context of the callback function; rather, your code must
    copy any "name" needed for later use after this function
    completes. At present, the return value of the callback
    is ignored, although a return of -1 should be avoided.

    For convenience, when this function succeeds, it returns
    the number of replies returned by the server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list because it does not support the requested
    context, or may encounter a failure after delivering
    partial results. Thus, this function may succeed even
    when no contexts are reported, or may fail but have a
    non-empty list. Likewise, the NBD protocol does not
    specify an upper bound for the number of replies that
    might be advertised, so client code should be aware that
    a server may send a lengthy list.
'''
        self._check_not_closed()
        return libnbdmod.opt_list_meta_context(self._o, context)

    def opt_list_meta_context_queries(self, queries, context):
        u'''▶ list available meta contexts, using explicit query list

    Request that the server list available meta contexts
    associated with the export previously specified by the
    most recent "nbd.set_export_name" or "nbd.connect_uri",
    and with an explicit list of queries provided as a
    parameter (see "nbd.opt_list_meta_context" if you want
    to reuse an implicit query list instead). This can only
    be used if "nbd.set_opt_mode" enabled option mode.

    The NBD protocol allows a client to decide how many
    queries to ask the server. For this function, the list
    is explicit in the "queries" parameter. When the list is
    empty, a server will typically reply with all contexts
    that it supports; when the list is non-empty, the server
    will reply only with supported contexts that match the
    client's request. Note that a reply by the server might
    be encoded to represent several feasible contexts within
    one string, rather than multiple strings per actual
    context name that would actually succeed during
    "nbd.opt_go"; so it is still necessary to use
    "nbd.can_meta_context" after connecting to see which
    contexts are actually supported.

    The "context" function is called once per server reply,
    with any "user_data" passed to this function, and with
    "name" supplied by the server. Remember that it is not
    safe to call "nbd.add_meta_context" from within the
    context of the callback function; rather, your code must
    copy any "name" needed for later use after this function
    completes. At present, the return value of the callback
    is ignored, although a return of -1 should be avoided.

    For convenience, when this function succeeds, it returns
    the number of replies returned by the server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list because it does not support the requested
    context, or may encounter a failure after delivering
    partial results. Thus, this function may succeed even
    when no contexts are reported, or may fail but have a
    non-empty list. Likewise, the NBD protocol does not
    specify an upper bound for the number of replies that
    might be advertised, so client code should be aware that
    a server may send a lengthy list.
'''
        self._check_not_closed()
        return libnbdmod.opt_list_meta_context_queries(self._o, queries,
                                                       context)

    def opt_set_meta_context(self, context):
        u'''▶ select specific meta contexts, using implicit query list

    Request that the server supply all recognized meta
    contexts registered through prior calls to
    "nbd.add_meta_context", in conjunction with the export
    previously specified by the most recent
    "nbd.set_export_name" or "nbd.connect_uri". This can
    only be used if "nbd.set_opt_mode" enabled option mode.
    Normally, this function is redundant, as "nbd.opt_go"
    automatically does the same task if structured replies
    or extended headers have already been negotiated. But
    manual control over meta context requests can be useful
    for fine-grained testing of how a server handles unusual
    negotiation sequences. Often, use of this function is
    coupled with "nbd.set_request_meta_context" to bypass
    the automatic context request normally performed by
    "nbd.opt_go".

    The NBD protocol allows a client to decide how many
    queries to ask the server. Rather than taking that list
    of queries as a parameter to this function, libnbd
    reuses the current list of requested meta contexts as
    set by "nbd.add_meta_context"; you can use
    "nbd.clear_meta_contexts" to set up a different list of
    queries (see "nbd.opt_set_meta_context_queries" to pass
    an explicit list of contexts instead). Since this
    function is primarily designed for testing servers,
    libnbd does not prevent the use of this function on an
    empty list or when "nbd.set_request_structured_replies"
    has disabled structured replies, in order to see how a
    server behaves.

    The "context" function is called once per server reply,
    with any "user_data" passed to this function, and with
    "name" supplied by the server. Additionally, each server
    name will remain visible through "nbd.can_meta_context"
    until the next attempt at "nbd.set_export_name" or
    "nbd.opt_set_meta_context", as well as "nbd.opt_go" or
    "nbd.opt_info" that trigger an automatic meta context
    request. Remember that it is not safe to call any
    "nbd_*" APIs from within the context of the callback
    function. At present, the return value of the callback
    is ignored, although a return of -1 should be avoided.

    For convenience, when this function succeeds, it returns
    the number of replies returned by the server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list because it does not support the requested
    context, or may encounter a failure after delivering
    partial results. Thus, this function may succeed even
    when no contexts are reported, or may fail but have a
    non-empty list.
'''
        self._check_not_closed()
        return libnbdmod.opt_set_meta_context(self._o, context)

    def opt_set_meta_context_queries(self, queries, context):
        u'''▶ select specific meta contexts, using explicit query list

    Request that the server supply all recognized meta
    contexts passed in through "queries", in conjunction
    with the export previously specified by the most recent
    "nbd.set_export_name" or "nbd.connect_uri". This can
    only be used if "nbd.set_opt_mode" enabled option mode.
    Normally, this function is redundant, as "nbd.opt_go"
    automatically does the same task if structured replies
    or extended headers have already been negotiated. But
    manual control over meta context requests can be useful
    for fine-grained testing of how a server handles unusual
    negotiation sequences. Often, use of this function is
    coupled with "nbd.set_request_meta_context" to bypass
    the automatic context request normally performed by
    "nbd.opt_go".

    The NBD protocol allows a client to decide how many
    queries to ask the server. This function takes an
    explicit list of queries; to instead reuse an implicit
    list, see "nbd.opt_set_meta_context". Since this
    function is primarily designed for testing servers,
    libnbd does not prevent the use of this function on an
    empty list or when "nbd.set_request_structured_replies"
    has disabled structured replies, in order to see how a
    server behaves.

    The "context" function is called once per server reply,
    with any "user_data" passed to this function, and with
    "name" supplied by the server. Additionally, each server
    name will remain visible through "nbd.can_meta_context"
    until the next attempt at "nbd.set_export_name" or
    "nbd.opt_set_meta_context", as well as "nbd.opt_go" or
    "nbd.opt_info" that trigger an automatic meta context
    request. Remember that it is not safe to call any
    "nbd_*" APIs from within the context of the callback
    function. At present, the return value of the callback
    is ignored, although a return of -1 should be avoided.

    For convenience, when this function succeeds, it returns
    the number of replies returned by the server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list because it does not support the requested
    context, or may encounter a failure after delivering
    partial results. Thus, this function may succeed even
    when no contexts are reported, or may fail but have a
    non-empty list.
'''
        self._check_not_closed()
        return libnbdmod.opt_set_meta_context_queries(self._o, queries,
                                                      context)

    def add_meta_context(self, name):
        u'''▶ ask server to negotiate metadata context

    During connection libnbd can negotiate zero or more
    metadata contexts with the server. Metadata contexts are
    features (such as "base:allocation") which describe
    information returned by the "nbd.block_status_64"
    command (for "base:allocation" this is whether blocks of
    data are allocated, zero or sparse).

    This call adds one metadata context to the list to be
    negotiated. You can call it as many times as needed. The
    list is initially empty when the handle is created; you
    can check the contents of the list with
    "nbd.get_nr_meta_contexts" and "nbd.get_meta_context",
    or clear it with "nbd.clear_meta_contexts".

    The NBD protocol limits meta context names to 4096
    bytes, but servers may not support the full length. The
    encoding of meta context names is always UTF-8.

    Not all servers support all metadata contexts. To learn
    if a context was actually negotiated, call
    "nbd.can_meta_context" after connecting.

    The single parameter is the name of the metadata
    context, for example "CONTEXT_BASE_ALLOCATION".
    <libnbd.h> includes defined constants beginning with
    "CONTEXT_" for some well-known contexts, but you are
    free to pass in other contexts.

    Other metadata contexts are server-specific, but include
    "qemu:dirty-bitmap:..." and "qemu:allocation-depth" for
    qemu-nbd (see qemu-nbd *-B* and *-A* options).
'''
        self._check_not_closed()
        return libnbdmod.add_meta_context(self._o, name)

    def get_nr_meta_contexts(self):
        u'''▶ return the current number of requested meta contexts

    During connection libnbd can negotiate zero or more
    metadata contexts with the server. Metadata contexts are
    features (such as "base:allocation") which describe
    information returned by the "nbd.block_status_64"
    command (for "base:allocation" this is whether blocks of
    data are allocated, zero or sparse).

    This command returns how many meta contexts have been
    added to the list to request from the server via
    "nbd.add_meta_context". The server is not obligated to
    honor all of the requests; to see what it actually
    supports, see "nbd.can_meta_context".
'''
        self._check_not_closed()
        return libnbdmod.get_nr_meta_contexts(self._o)

    def get_meta_context(self, i):
        u'''▶ return the i'th meta context request

    During connection libnbd can negotiate zero or more
    metadata contexts with the server. Metadata contexts are
    features (such as "base:allocation") which describe
    information returned by the "nbd.block_status_64"
    command (for "base:allocation" this is whether blocks of
    data are allocated, zero or sparse).

    This command returns the i'th meta context request, as
    added by "nbd.add_meta_context", and bounded by
    "nbd.get_nr_meta_contexts".
'''
        self._check_not_closed()
        return libnbdmod.get_meta_context(self._o, i)

    def clear_meta_contexts(self):
        u'''▶ reset the list of requested meta contexts

    During connection libnbd can negotiate zero or more
    metadata contexts with the server. Metadata contexts are
    features (such as "base:allocation") which describe
    information returned by the "nbd.block_status_64"
    command (for "base:allocation" this is whether blocks of
    data are allocated, zero or sparse).

    This command resets the list of meta contexts to request
    back to an empty list, for re-population by further use
    of "nbd.add_meta_context". It is primarily useful when
    option negotiation mode is selected (see
    "nbd.set_opt_mode"), for altering the list of attempted
    contexts between subsequent export queries.
'''
        self._check_not_closed()
        return libnbdmod.clear_meta_contexts(self._o)

    def set_uri_allow_transports(self, mask):
        u'''▶ set the allowed transports in NBD URIs

    Set which transports are allowed to appear in NBD URIs.
    The default is to allow any transport.

    The "mask" parameter may contain any of the following
    flags ORed together:

    "ALLOW_TRANSPORT_TCP" = 0x1
    "ALLOW_TRANSPORT_UNIX" = 0x2
    "ALLOW_TRANSPORT_VSOCK" = 0x4
    "ALLOW_TRANSPORT_SSH" = 0x8

    For convenience, the constant "ALLOW_TRANSPORT_MASK" is
    available to describe all transports recognized by this
    build of libnbd. A future version of the library may add
    new flags.
'''
        self._check_not_closed()
        return libnbdmod.set_uri_allow_transports(self._o, mask)

    def set_uri_allow_tls(self, tls):
        u'''▶ set the allowed TLS settings in NBD URIs

    Set which TLS settings are allowed to appear in NBD
    URIs. The default is to allow either non-TLS or TLS
    URIs.

    The "tls" parameter can be:

    "TLS_DISABLE"
        TLS URIs are not permitted, ie. a URI such as
        "nbds://..." will be rejected.

    "TLS_ALLOW"
        This is the default. TLS may be used or not,
        depending on whether the URI uses "nbds" or "nbd".

    "TLS_REQUIRE"
        TLS URIs are required. All URIs must use "nbds".
'''
        self._check_not_closed()
        return libnbdmod.set_uri_allow_tls(self._o, tls)

    def set_uri_allow_local_file(self, allow):
        u'''▶ set the allowed transports in NBD URIs

    Allow NBD URIs to reference local files. This is
    *disabled* by default.

    Currently this setting only controls whether the
    "tls-psk-file" parameter in NBD URIs is allowed.
'''
        self._check_not_closed()
        return libnbdmod.set_uri_allow_local_file(self._o, allow)

    def connect_uri(self, uri):
        u'''▶ connect to NBD URI

    Connect (synchronously) to an NBD server and export by
    specifying the NBD URI. NBD URIs are a standard way to
    specify a network block device endpoint, using a syntax
    like "nbd://example.com" which is convenient, well
    defined and future proof.

    This call works by parsing the URI parameter and calling
    "nbd.set_export_name" and "nbd.set_tls" and other calls
    as needed, followed by "nbd.connect_tcp",
    "nbd.connect_unix" or "nbd.connect_vsock".

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but "nbd.set_opt_mode" can be used for manual
    control over option negotiation performed before
    transmission phase.

  Example URIs supported
    "nbd://example.com"
        Connect over TCP, unencrypted, to "example.com" port
        10809.

    "nbds://example.com"
        Connect over TCP with TLS, to "example.com" port
        10809. If the server does not support TLS then this
        will fail.

    "nbd+unix:///foo?socket=/tmp/nbd.sock"
        Connect over the Unix domain socket /tmp/nbd.sock to
        an NBD server running locally. The export name is
        set to "foo" (note without any leading "/"
        character).

    "nbds+unix://alice@/?socket=/tmp/nbd.sock&tls-certificat
    es=certs"
        Connect over a Unix domain socket, enabling TLS and
        setting the path to a directory containing
        certificates and keys.

    "nbd+vsock:///"
        In this scenario libnbd is running in a virtual
        machine. Connect over "AF_VSOCK" to an NBD server
        running on the hypervisor.

    "nbd+ssh://server/"
        Connect to remote "server" using Secure Shell, and
        tunnel NBD to an NBD server listening on port 10809.

  Supported URI formats
    The following schemes are supported in the current
    version of libnbd:

    "nbd:"
        Connect over TCP without using TLS.

    "nbds:"
        Connect over TCP. TLS is required and the connection
        will fail if the server does not support TLS.

    "nbd+unix:"
    "nbds+unix:"
        Connect over a Unix domain socket, without or with
        TLS respectively. The "socket" parameter is
        required.

    "nbd+vsock:"
    "nbds+vsock:"
        Connect over the "AF_VSOCK" transport, without or
        with TLS respectively. You can use
        "nbd.supports_vsock" to see if this build of libnbd
        supports "AF_VSOCK".

    "nbd+ssh:"
    "nbds+ssh:"
        *Experimental*

        Tunnel NBD over a Secure Shell connection. This
        requires that ssh(1) is installed locally, and that
        nc(1) (from the nmap project) is installed on the
        remote server.

    The authority part of the URI
    ("[username@][servername][:port]") is parsed depending
    on the transport. For TCP it specifies the server to
    connect to and optional port number. For "+unix" it
    should not be present. For "+vsock" the server name is
    the numeric CID (eg. 2 to connect to the host), and the
    optional port number may be present. For "+ssh" the
    Secure Shell server and optional port. If the "username"
    is present it is used for TLS authentication.

    For all transports, an export name may be present,
    parsed in accordance with the NBD URI specification.

    Finally the query part of the URI can contain:

    socket=SOCKET
        Specifies the Unix domain socket to connect on. Must
        be present for the "+unix" transport, optional for
        "+ssh", and must not be present for the other
        transports.

    tls-certificates=DIR
        Set the certificates directory. See
        "nbd.set_tls_certificates". Note this is not allowed
        by default - see next section.

    tls-psk-file=PSKFILE
        Set the PSK file. See "nbd.set_tls_psk_file". Note
        this is not allowed by default - see next section.

    tls-hostname="SERVER"
        Set the TLS hostname. See "nbd.set_tls_hostname".

    tls-verify-peer=false
        Do not verify the server certificate. See
        "nbd.set_tls_verify_peer". The default is "true".

  Disable URI features
    For security reasons you might want to disable certain
    URI features. Pre-filtering URIs is error-prone and
    should not be attempted. Instead use the libnbd APIs
    below to control what can appear in URIs. Note you must
    call these functions on the same handle before calling
    "nbd.connect_uri" or "nbd.aio_connect_uri".

    TCP, Unix domain socket, "AF_VSOCK" or SSH transports
        Default: all allowed

        To select which transports are allowed call
        "nbd.set_uri_allow_transports".

    TLS Default: both non-TLS and TLS connections allowed

        To force TLS off or on in URIs call
        "nbd.set_uri_allow_tls".

    Connect to Unix domain socket in the local filesystem
        Default: allowed

        To prevent this you must disable the "+unix"
        transport using "nbd.set_uri_allow_transports".

    Read from local files
        Default: denied

        To allow URIs to contain references to local files
        (eg. for parameters like "tls-psk-file") call
        "nbd.set_uri_allow_local_file".

  Overriding the export name
    It is possible to override the export name portion of a
    URI by using "nbd.set_opt_mode" to enable option mode,
    then using "nbd.set_export_name" and "nbd.opt_go" as
    part of subsequent negotiation.

  Optional features
    This call will fail if libnbd was not compiled with
    libxml2; you can test whether this is the case with
    "nbd.supports_uri".

    Support for URIs that require TLS will fail if libnbd
    was not compiled with gnutls; you can test whether this
    is the case with "nbd.supports_tls".

  Constructing a URI from an existing connection
    See "nbd.get_uri".

  See if a string is an NBD URI
    See "nbd.is_uri".

  Differences from qemu and glib parsing of NBD URIs
    qemu(1) also supports NBD URIs and has a separate URI
    parser. In qemu ≤ 9.0 this was done using their own
    parser. In qemu ≥ 9.1 this is done using glib "g_uri"
    functions. The current (glib-based) parser does not
    parse the export name part of the URI in exactly the
    same way as libnbd, which may cause URIs to work in
    libnbd but not in qemu or *vice versa*. Only URIs using
    exportnames should be affected. For details see
    <https://gitlab.com/qemu-project/qemu/-/issues/2584>.

  Limitations on vsock port numbers
    The vsock(7) protocol allows 32 bit unsigned ports,
    reserving ports 0, 1 and 2 for special purposes. In
    Linux, ports < 1024 are reserved for privileged
    processes.

    libxml2 (used to parse the URI) imposes additional
    restrictions. libxml2 < 2.9 limited port numbers to
    99,999,999. libxml2 ≥ 2.9 limits port numbers to ≤
    0x7fff_ffff (31 bits).
'''
        self._check_not_closed()
        return libnbdmod.connect_uri(self._o, uri)

    def connect_unix(self, unixsocket):
        u'''▶ connect to NBD server over a Unix domain socket

    Connect (synchronously) over the named Unix domain
    socket ("unixsocket") to an NBD server running on the
    same machine.

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but "nbd.set_opt_mode" can be used for manual
    control over option negotiation performed before
    transmission phase.
'''
        self._check_not_closed()
        return libnbdmod.connect_unix(self._o, unixsocket)

    def connect_vsock(self, cid, port):
        u'''▶ connect to NBD server over AF_VSOCK protocol

    Connect (synchronously) over the "AF_VSOCK" protocol
    from a virtual machine to an NBD server, usually running
    on the host. The "cid" and "port" parameters specify the
    server address. Usually "cid" should be 2 (to connect to
    the host), and "port" might be 10809 or another port
    number assigned to you by the host administrator.

    Not all systems support "AF_VSOCK"; to determine if
    libnbd was built on a system with vsock support, see
    "nbd.supports_vsock".

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but "nbd.set_opt_mode" can be used for manual
    control over option negotiation performed before
    transmission phase.
'''
        self._check_not_closed()
        return libnbdmod.connect_vsock(self._o, cid, port)

    def connect_tcp(self, hostname, port):
        u'''▶ connect to NBD server over a TCP port

    Connect (synchronously) to the NBD server listening on
    "hostname:port". The "port" may be a port name such as
    "nbd", or it may be a port number as a string such as
    "10809".

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but "nbd.set_opt_mode" can be used for manual
    control over option negotiation performed before
    transmission phase.
'''
        self._check_not_closed()
        return libnbdmod.connect_tcp(self._o, hostname, port)

    def connect_socket(self, sock):
        u'''▶ connect directly to a connected socket

    Pass a connected socket "sock" through which libnbd will
    talk to the NBD server.

    The caller is responsible for creating and connecting
    this socket by some method, before passing it to libnbd.

    If this call returns without error then socket ownership
    is passed to libnbd. Libnbd will close the socket when
    the handle is closed. The caller must not use the socket
    in any way.

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but "nbd.set_opt_mode" can be used for manual
    control over option negotiation performed before
    transmission phase.
'''
        self._check_not_closed()
        return libnbdmod.connect_socket(self._o, sock)

    def connect_command(self, argv):
        u'''▶ connect to NBD server command

    Run the command as a subprocess and connect to it over
    stdin/stdout. This is for use with NBD servers which can
    behave like inetd clients, such as nbdkit(1) using the
    *-s*/*--single* flag, and nbd-server(1) with port number
    set to 0.

    To run qemu-nbd(1), use
    "nbd.connect_systemd_socket_activation" instead.

  Subprocess
    Libnbd will fork the "argv" command and pass the NBD
    socket to it using file descriptors 0 and 1
    (stdin/stdout):

     ┌─────────┬─────────┐    ┌────────────────┐
     │ program │ libnbd  │    │   NBD server   │
     │         │         │    │       (argv)   │
     │         │ socket ╍╍╍╍╍╍╍╍▶ stdin/stdout │
     └─────────┴─────────┘    └────────────────┘

    When the NBD handle is closed the server subprocess is
    killed.

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but "nbd.set_opt_mode" can be used for manual
    control over option negotiation performed before
    transmission phase.
'''
        self._check_not_closed()
        return libnbdmod.connect_command(self._o, argv)

    def connect_systemd_socket_activation(self, argv):
        u'''▶ connect using systemd socket activation

    Run the command as a subprocess and connect to it using
    systemd socket activation.

    This is especially useful for running qemu-nbd(1) as a
    subprocess of libnbd, for example to use it to open
    qcow2 files.

    To run nbdkit as a subprocess, this function can be
    used, or "nbd.connect_command".

    To run nbd-server(1) as a subprocess, this function
    cannot be used, you must use "nbd.connect_command".

  Socket activation
    Libnbd will fork the "argv" command and pass an NBD
    socket to it using special "LISTEN_*" environment
    variables (as defined by the systemd socket activation
    protocol).

     ┌─────────┬─────────┐    ┌───────────────┐
     │ program │ libnbd  │    │  qemu-nbd or  │
     │         │         │    │  other server │
     │         │ socket ╍╍╍╍╍╍╍╍▶             │
     └─────────┴─────────┘    └───────────────┘

    When the NBD handle is closed the server subprocess is
    killed.

   Socket name
    The socket activation protocol lets you optionally give
    the socket a name. If used, the name is passed to the
    NBD server using the "LISTEN_FDNAMES" environment
    variable. To provide a socket name, call
    "nbd.set_socket_activation_name" before calling the
    connect function.

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but "nbd.set_opt_mode" can be used for manual
    control over option negotiation performed before
    transmission phase.
'''
        self._check_not_closed()
        return libnbdmod.connect_systemd_socket_activation(self._o, argv)

    def set_socket_activation_name(self, socket_name):
        u'''▶ set the socket activation name

    When running an NBD server using
    "nbd.connect_systemd_socket_activation" you can
    optionally name the socket. Call this function before
    connecting to the server.

    Some servers such as qemu-storage-daemon(1) can use this
    information to associate the socket with a name used on
    the command line, but most servers will ignore it. The
    name is passed through the "LISTEN_FDNAMES" environment
    variable.

    The parameter "socket_name" can be a short alphanumeric
    string. If it is set to the empty string (also the
    default when the handle is created) then the name
    "unknown" will be seen by the server.
'''
        self._check_not_closed()
        return libnbdmod.set_socket_activation_name(self._o, socket_name)

    def get_socket_activation_name(self):
        u'''▶ get the socket activation name

    Return the socket name used when you call
    "nbd.connect_systemd_socket_activation" on the same
    handle. By default this will return the empty string
    meaning that the server will see the name "unknown".
'''
        self._check_not_closed()
        return libnbdmod.get_socket_activation_name(self._o)

    def is_read_only(self):
        u'''▶ is the NBD export read-only?

    Returns true if the NBD export is read-only; writes and
    write-like operations will fail.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.is_read_only(self._o)

    def can_flush(self):
        u'''▶ does the server support the flush command?

    Returns true if the server supports the flush command
    (see "nbd.flush", "nbd.aio_flush"). Returns false if the
    server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_flush(self._o)

    def can_fua(self):
        u'''▶ does the server support the FUA flag?

    Returns true if the server supports the FUA flag on
    certain commands (see "nbd.pwrite").

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_fua(self._o)

    def is_rotational(self):
        u'''▶ is the NBD disk rotational (like a disk)?

    Returns true if the disk exposed over NBD is rotational
    (like a traditional floppy or hard disk). Returns false
    if the disk has no penalty for random access (like an
    SSD or RAM disk).

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.is_rotational(self._o)

    def can_trim(self):
        u'''▶ does the server support the trim command?

    Returns true if the server supports the trim command
    (see "nbd.trim", "nbd.aio_trim"). Returns false if the
    server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_trim(self._o)

    def can_zero(self):
        u'''▶ does the server support the zero command?

    Returns true if the server supports the zero command
    (see "nbd.zero", "nbd.aio_zero"). Returns false if the
    server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_zero(self._o)

    def can_fast_zero(self):
        u'''▶ does the server support the fast zero flag?

    Returns true if the server supports the use of the
    "CMD_FLAG_FAST_ZERO" flag to the zero command (see
    "nbd.zero", "nbd.aio_zero"). Returns false if the server
    does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_fast_zero(self._o)

    def can_block_status_payload(self):
        u'''▶ does the server support the block status payload flag?

    Returns true if the server supports the use of the
    "CMD_FLAG_PAYLOAD_LEN" flag to allow filtering of the
    block status command (see "nbd.block_status_filter").
    Returns false if the server does not. Note that this
    will never return true if
    "nbd.get_extended_headers_negotiated" is false.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_block_status_payload(self._o)

    def can_df(self):
        u'''▶ does the server support the don't fragment flag to pread?

    Returns true if the server supports structured reads
    with an ability to request a non-fragmented read (see
    "nbd.pread_structured", "nbd.aio_pread_structured").
    Returns false if the server either lacks structured
    reads or if it does not support a non-fragmented read
    request.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_df(self._o)

    def can_multi_conn(self):
        u'''▶ does the server support multi-conn?

    Returns true if the server supports multi-conn. Returns
    false if the server does not.

    It is not safe to open multiple handles connecting to
    the same server if you will write to the server and the
    server does not advertise multi-conn support. The safe
    way to check for this is to open one connection, check
    this flag is true, then open further connections as
    required.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_multi_conn(self._o)

    def can_cache(self):
        u'''▶ does the server support the cache command?

    Returns true if the server supports the cache command
    (see "nbd.cache", "nbd.aio_cache"). Returns false if the
    server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_cache(self._o)

    def can_meta_context(self, metacontext):
        u'''▶ does the server support a specific meta context?

    Returns true if the server supports the given meta
    context (see "nbd.add_meta_context"). Returns false if
    the server does not. It is possible for this command to
    fail if meta contexts were requested but there is a
    missing or failed attempt at NBD_OPT_SET_META_CONTEXT
    during option negotiation.

    If the server supports block status filtering (see
    "nbd.can_block_status_payload", this function must
    return true for any filter name passed to
    "nbd.block_status_filter".

    The single parameter is the name of the metadata
    context, for example "CONTEXT_BASE_ALLOCATION".
    <libnbd.h> includes defined constants for well-known
    namespace contexts beginning with "CONTEXT_", but you
    are free to pass in other contexts.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.can_meta_context(self._o, metacontext)

    def get_protocol(self):
        u'''▶ return the NBD protocol variant

    Return the NBD protocol variant in use on the
    connection. At the moment this returns one of the
    strings "oldstyle", "newstyle" or "newstyle-fixed".
    Other strings might be returned in the future. Most
    modern NBD servers use "newstyle-fixed".

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.get_protocol(self._o)

    def get_size(self):
        u'''▶ return the export size

    Returns the size in bytes of the NBD export.

    Note that this call fails with "EOVERFLOW" for an
    unlikely server that advertises a size which cannot fit
    in a 64-bit signed integer.

    nbdinfo(1) *--size* option is a way to access this API
    from shell scripts.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.get_size(self._o)

    def get_block_size(self, size_type):
        u'''▶ return a specific server block size constraint

    Returns a specific block size constraint advertised by
    the server. If zero is returned it means the server did
    not advertise a constraint.

    Constraints are hints. Servers differ in their behaviour
    as to whether they enforce constraints or not.

    The "size_type" parameter selects which constraint to
    read. It can be one of:

    "SIZE_MINIMUM" = 0
        If non-zero, this will be a power of 2 between 1 and
        64k; any client request that is not aligned in
        length or offset to this size is likely to fail with
        "EINVAL". The image size will generally also be a
        multiple of this value (if not, the final few bytes
        are inaccessible while obeying alignment
        constraints).

        If zero (meaning no information was returned by the
        server), it is safest to assume a minimum block size
        of 512, although many servers support a minimum
        block size of 1.

        If the server provides a constraint, then libnbd
        defaults to honoring that constraint client-side
        unless "STRICT_ALIGN" is cleared in
        nbd_set_strict_mode(3).

    "SIZE_PREFERRED" = 1
        If non-zero, this is a power of 2 representing the
        preferred size for efficient I/O. Smaller requests
        may incur overhead such as read-modify-write cycles
        that will not be present when using I/O that is a
        multiple of this value. This value may be larger
        than the size of the export.

        If zero (meaning no information was returned by the
        server), using 4k as a preferred block size tends to
        give decent performance.

    "SIZE_MAXIMUM" = 2
        If non-zero, this represents the maximum length that
        the server is willing to handle during "nbd.pread"
        or "nbd.pwrite". Other functions like "nbd.zero" may
        still be able to use larger sizes. Note that this
        function returns what the server advertised, but
        libnbd itself imposes a maximum of 64M.

        If zero (meaning no information was returned by the
        server), some NBD servers will abruptly disconnect
        if a transaction sends or receives more than 32M of
        data.

    "SIZE_PAYLOAD" = 3
        This value is not advertised by the server, but
        rather represents the maximum outgoing payload size
        for a given connection that libnbd will enforce
        unless "STRICT_PAYLOAD" is cleared in
        nbd_set_strict_mode(3). It is always non-zero: never
        smaller than 1M, never larger than 64M, and matches
        "SIZE_MAXIMUM" when possible.

    Future NBD extensions may result in additional
    "size_type" values. Note that by default, libnbd
    requests all available block sizes, but that a server
    may differ in what sizes it chooses to report if
    "nbd.set_request_block_size" alters whether the client
    requests sizes.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
'''
        self._check_not_closed()
        return libnbdmod.get_block_size(self._o, size_type)

    def pread(self, count, offset, flags=0):
        u'''▶ read from the NBD server

    Issue a read command to the NBD server for the range
    starting at "offset" and ending at "offset" + "count" -
    1. NBD can only read all or nothing using this call. The
    call returns when the data has been read fully into
    "buf" or there is an error. See also
    "nbd.pread_structured", if finer visibility is required
    into the server's replies, or if you want to use
    "CMD_FLAG_DF".

    Note that libnbd currently enforces a maximum read
    buffer of 64MiB, even if the server would permit a
    larger buffer in a single transaction; attempts to
    exceed this will result in an "ERANGE" error. The server
    may enforce a smaller limit, which can be learned with
    "nbd.get_block_size".

    The "flags" parameter must be 0 for now (it exists for
    future NBD protocol extensions).

    Note that if this command fails, and
    "nbd.get_pread_initialize" returns true, then libnbd
    sanitized "buf", but it is unspecified whether the
    contents of "buf" will read as zero or as partial
    results from the server. If "nbd.get_pread_initialize"
    returns false, then libnbd did not sanitize "buf", and
    the contents are undefined on failure.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.pread(self._o, count, offset, flags)

    def pread_structured(self, count, offset, chunk, flags=0):
        u'''▶ read from the NBD server

    Issue a read command to the NBD server for the range
    starting at "offset" and ending at "offset" + "count" -
    1. The server's response may be subdivided into chunks
    which may arrive out of order before reassembly into the
    original buffer; the "chunk" callback is used for
    notification after each chunk arrives, and may perform
    additional sanity checking on the server's reply. The
    callback cannot call "nbd_*" APIs on the same handle
    since it holds the handle lock and will cause a
    deadlock. If the callback returns -1, and no earlier
    error has been detected, then the overall read command
    will fail with any non-zero value stored into the
    callback's "error" parameter (with a default of
    "EPROTO"); but any further chunks will still invoke the
    callback.

    The "chunk" function is called once per chunk of data
    received, with the "user_data" passed to this function.
    The "subbuf" and "count" parameters represent the subset
    of the original buffer which has just been populated by
    results from the server (in C, "subbuf" always points
    within the original "buf"; but this guarantee may not
    extend to other language bindings). The "offset"
    parameter represents the absolute offset at which
    "subbuf" begins within the image (note that this is not
    the relative offset of "subbuf" within the original
    buffer "buf"). Changes to "error" on output are ignored
    unless the callback fails. The input meaning of the
    "error" parameter is controlled by the "status"
    parameter, which is one of

    "READ_DATA" = 1
        "subbuf" was populated with "count" bytes of data.
        On input, "error" contains the errno value of any
        earlier detected error, or zero.

    "READ_HOLE" = 2
        "subbuf" represents a hole, and contains "count" NUL
        bytes. On input, "error" contains the errno value of
        any earlier detected error, or zero.

    "READ_ERROR" = 3
        "count" is 0, so "subbuf" is unusable. On input,
        "error" contains the errno value reported by the
        server as occurring while reading that "offset",
        regardless if any earlier error has been detected.

    Future NBD extensions may permit other values for
    "status", but those will not be returned to a client
    that has not opted in to requesting such extensions. If
    the server is non-compliant, it is possible for the
    "chunk" function to be called more times than you expect
    or with "count" 0 for "READ_DATA" or "READ_HOLE". It is
    also possible that the "chunk" function is not called at
    all (in particular, "READ_ERROR" is used only when an
    error is associated with a particular offset, and not
    when the server reports a generic error), but you are
    guaranteed that the callback was called at least once if
    the overall read succeeds. Libnbd does not validate that
    the server obeyed the requirement that a read call must
    not have overlapping chunks and must not succeed without
    enough chunks to cover the entire request.

    Note that libnbd currently enforces a maximum read
    buffer of 64MiB, even if the server would permit a
    larger buffer in a single transaction; attempts to
    exceed this will result in an "ERANGE" error. The server
    may enforce a smaller limit, which can be learned with
    "nbd.get_block_size".

    The "flags" parameter may be 0 for no flags, or may
    contain "CMD_FLAG_DF" meaning that the server should not
    reply with more than one fragment (if that is supported
    - some servers cannot do this, see "nbd.can_df"). Libnbd
    does not validate that the server actually obeys the
    flag.

    Note that if this command fails, and
    "nbd.get_pread_initialize" returns true, then libnbd
    sanitized "buf", but it is unspecified whether the
    contents of "buf" will read as zero or as partial
    results from the server. If "nbd.get_pread_initialize"
    returns false, then libnbd did not sanitize "buf", and
    the contents are undefined on failure.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.pread_structured(self._o, count, offset, chunk,
                                          flags)

    def pwrite(self, buf, offset, flags=0):
        u'''▶ write to the NBD server

    Issue a write command to the NBD server, writing the
    data in "buf" to the range starting at "offset" and
    ending at "offset" + "count" - 1. NBD can only write all
    or nothing using this call. The call returns when the
    command has been acknowledged by the server, or there is
    an error. Note this will generally return an error if
    "nbd.is_read_only" is true.

    Note that libnbd defaults to enforcing a maximum write
    buffer of the lesser of 64MiB or any maximum payload
    size advertised by the server; attempts to exceed this
    will generally result in a client-side "ERANGE" error,
    rather than a server-side disconnection. The actual
    limit can be learned with "nbd.get_block_size".

    The "flags" parameter may be 0 for no flags, or may
    contain "CMD_FLAG_FUA" meaning that the server should
    not return until the data has been committed to
    permanent storage (if that is supported - some servers
    cannot do this, see "nbd.can_fua"). For convenience,
    unless nbd_set_strict_flags(3) was used to disable
    "STRICT_AUTO_FLAG", libnbd ignores the presence or
    absence of the flag "CMD_FLAG_PAYLOAD_LEN" in "flags",
    while correctly using the flag over the wire according
    to whether extended headers were negotiated.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.pwrite(self._o, buf, offset, flags)

    def shutdown(self, flags=0):
        u'''▶ disconnect from the NBD server

    Issue the disconnect command to the NBD server. This is
    a nice way to tell the server we are going away, but
    from the client's point of view has no advantage over
    abruptly closing the connection (see "nbd.close").

    This function works whether or not the handle is ready
    for transmission of commands. If more fine-grained
    control is needed, see "nbd.aio_opt_abort" and
    "nbd.aio_disconnect".

    The "flags" argument is a bitmask, including zero or
    more of the following shutdown flags:

    "SHUTDOWN_ABANDON_PENDING" = 0x10000
        If there are any pending requests which have not yet
        been sent to the server (see "nbd.aio_in_flight"),
        abandon them without sending them to the server,
        rather than the usual practice of issuing those
        commands before informing the server of the intent
        to disconnect.

    For convenience, the constant "SHUTDOWN_MASK" is
    available to describe all shutdown flags recognized by
    this build of libnbd. A future version of the library
    may add new flags.
'''
        self._check_not_closed()
        return libnbdmod.shutdown(self._o, flags)

    def flush(self, flags=0):
        u'''▶ send flush command to the NBD server

    Issue the flush command to the NBD server. The function
    should return when all write commands which have
    completed have been committed to permanent storage on
    the server. Note this will generally return an error if
    "nbd.can_flush" is false.

    The "flags" parameter must be 0 for now (it exists for
    future NBD protocol extensions).

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.flush(self._o, flags)

    def trim(self, count, offset, flags=0):
        u'''▶ send trim command to the NBD server

    Issue a trim command to the NBD server, which if
    supported by the server causes a hole to be punched in
    the backing store starting at "offset" and ending at
    "offset" + "count" - 1. The call returns when the
    command has been acknowledged by the server, or there is
    an error. Note this will generally return an error if
    "nbd.can_trim" is false or "nbd.is_read_only" is true.

    Note that not all servers can support a "count" of 4GiB
    or larger; "nbd.get_extended_headers_negotiated"
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum trim size, although a future extension
    may add a constraint visible in "nbd.get_block_size".

    The "flags" parameter may be 0 for no flags, or may
    contain "CMD_FLAG_FUA" meaning that the server should
    not return until the data has been committed to
    permanent storage (if that is supported - some servers
    cannot do this, see "nbd.can_fua").

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.trim(self._o, count, offset, flags)

    def cache(self, count, offset, flags=0):
        u'''▶ send cache (prefetch) command to the NBD server

    Issue the cache (prefetch) command to the NBD server,
    which if supported by the server causes data to be
    prefetched into faster storage by the server, speeding
    up a subsequent "nbd.pread" call. The server can also
    silently ignore this command. Note this will generally
    return an error if "nbd.can_cache" is false.

    Note that not all servers can support a "count" of 4GiB
    or larger; "nbd.get_extended_headers_negotiated"
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum cache size, although a future extension
    may add a constraint visible in "nbd.get_block_size".

    The "flags" parameter must be 0 for now (it exists for
    future NBD protocol extensions).

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.cache(self._o, count, offset, flags)

    def zero(self, count, offset, flags=0):
        u'''▶ send write zeroes command to the NBD server

    Issue a write zeroes command to the NBD server, which if
    supported by the server causes a zeroes to be written
    efficiently starting at "offset" and ending at "offset"
    + "count" - 1. The call returns when the command has
    been acknowledged by the server, or there is an error.
    Note this will generally return an error if
    "nbd.can_zero" is false or "nbd.is_read_only" is true.

    Note that not all servers can support a "count" of 4GiB
    or larger; "nbd.get_extended_headers_negotiated"
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum zero size, although a future extension
    may add a constraint visible in "nbd.get_block_size".
    Also, some servers may permit a larger zero request only
    when the "CMD_FLAG_FAST_ZERO" is in use.

    The "flags" parameter may be 0 for no flags, or may
    contain "CMD_FLAG_FUA" meaning that the server should
    not return until the data has been committed to
    permanent storage (if that is supported - some servers
    cannot do this, see "nbd.can_fua"), "CMD_FLAG_NO_HOLE"
    meaning that the server should favor writing actual
    allocated zeroes over punching a hole, and/or
    "CMD_FLAG_FAST_ZERO" meaning that the server must fail
    quickly if writing zeroes is no faster than a normal
    write (if that is supported - some servers cannot do
    this, see "nbd.can_fast_zero").

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.zero(self._o, count, offset, flags)

    def block_status(self, count, offset, extent, flags=0):
        u'''▶ send block status command, with 32-bit callback

    Issue the block status command to the NBD server. If
    supported by the server, this causes metadata context
    information about blocks beginning from the specified
    offset to be returned. The "count" parameter is a hint:
    the server may choose to return less status, or the
    final block may extend beyond the requested range. If
    multiple contexts are supported, the number of blocks
    and cumulative length of those blocks need not be
    identical between contexts.

    Note that not all servers can support a "count" of 4GiB
    or larger; "nbd.get_extended_headers_negotiated"
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum block status size, although a future
    extension may add a constraint visible in
    "nbd.get_block_size". Furthermore, this function is
    inherently limited to 32-bit values. If the server
    replies with a larger extent, the length of that extent
    will be truncated to just below 32 bits and any further
    extents from the server will be ignored. If the server
    replies with a status value larger than 32 bits (only
    possible when extended headers are in use), the callback
    function will be passed an "EOVERFLOW" error. To get the
    full extent information from a server that supports
    64-bit extents, you must use "nbd.block_status_64".

    Depending on which metadata contexts were enabled before
    connecting (see "nbd.add_meta_context") and which are
    supported by the server (see "nbd.can_meta_context")
    this call returns information about extents by calling
    back to the "extent" function. The callback cannot call
    "nbd_*" APIs on the same handle since it holds the
    handle lock and will cause a deadlock. If the callback
    returns -1, and no earlier error has been detected, then
    the overall block status command will fail with any
    non-zero value stored into the callback's "error"
    parameter (with a default of "EPROTO"); but any further
    contexts will still invoke the callback.

    The "extent" function is called once per type of
    metadata available, with the "user_data" passed to this
    function. The "metacontext" parameter is a string such
    as "base:allocation". The "entries" array is an array of
    pairs of integers with the first entry in each pair
    being the length (in bytes) of the block and the second
    entry being a status/flags field which is specific to
    the metadata context. The number of pairs passed to the
    function is "nr_entries/2". The NBD protocol document in
    the section about "NBD_REPLY_TYPE_BLOCK_STATUS"
    describes the meaning of this array; for contexts known
    to libnbd, <libnbd.h> contains constants beginning with
    "STATE_" that may help decipher the values. On entry to
    the callback, the "error" parameter contains the errno
    value of any previously detected error, but even if an
    earlier error was detected, the current "metacontext"
    and "entries" are valid.

    It is possible for the extent function to be called more
    times than you expect (if the server is buggy), so
    always check the "metacontext" field to ensure you are
    receiving the data you expect. It is also possible that
    the extent function is not called at all, even for
    metadata contexts that you requested. This indicates
    either that the server doesn't support the context or
    for some other reason cannot return the data.

    The "flags" parameter may be 0 for no flags, or may
    contain "CMD_FLAG_REQ_ONE" meaning that the server
    should return only one extent per metadata context where
    that extent does not exceed "count" bytes; however,
    libnbd does not validate that the server obeyed the
    flag.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.block_status(self._o, count, offset, extent, flags)

    def block_status_64(self, count, offset, extent64, flags=0):
        u'''▶ send block status command, with 64-bit callback

    Issue the block status command to the NBD server. If
    supported by the server, this causes metadata context
    information about blocks beginning from the specified
    offset to be returned. The "count" parameter is a hint:
    the server may choose to return less status, or the
    final block may extend beyond the requested range. When
    multiple contexts are supported, the number of blocks
    and cumulative length of those blocks need not be
    identical between contexts; this command generally
    returns the status of all negotiated contexts, while
    some servers also support a filtered request (see
    "nbd.can_block_status_payload",
    "nbd.block_status_filter").

    Note that not all servers can support a "count" of 4GiB
    or larger; "nbd.get_extended_headers_negotiated"
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum block status size, although a future
    extension may add a constraint visible in
    "nbd.get_block_size".

    Depending on which metadata contexts were enabled before
    connecting (see "nbd.add_meta_context") and which are
    supported by the server (see "nbd.can_meta_context")
    this call returns information about extents by calling
    back to the "extent64" function. The callback cannot
    call "nbd_*" APIs on the same handle since it holds the
    handle lock and will cause a deadlock. If the callback
    returns -1, and no earlier error has been detected, then
    the overall block status command will fail with any
    non-zero value stored into the callback's "error"
    parameter (with a default of "EPROTO"); but any further
    contexts will still invoke the callback.

    The "extent64" function is called once per type of
    metadata available, with the "user_data" passed to this
    function. The "metacontext" parameter is a string such
    as "base:allocation". The "entries" array is an array of
    nbd_extent structs, containing length (in bytes) of the
    block and a status/flags field which is specific to the
    metadata context. The number of array entries passed to
    the function is "nr_entries". The NBD protocol document
    in the section about "NBD_REPLY_TYPE_BLOCK_STATUS"
    describes the meaning of this array; for contexts known
    to libnbd, <libnbd.h> contains constants beginning with
    "STATE_" that may help decipher the values. On entry to
    the callback, the "error" parameter contains the errno
    value of any previously detected error.

    It is possible for the extent function to be called more
    times than you expect (if the server is buggy), so
    always check the "metacontext" field to ensure you are
    receiving the data you expect. It is also possible that
    the extent function is not called at all, even for
    metadata contexts that you requested. This indicates
    either that the server doesn't support the context or
    for some other reason cannot return the data.

    The "flags" parameter may be 0 for no flags, or may
    contain "CMD_FLAG_REQ_ONE" meaning that the server
    should return only one extent per metadata context where
    that extent does not exceed "count" bytes; however,
    libnbd does not validate that the server obeyed the
    flag.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.block_status_64(self._o, count, offset, extent64,
                                         flags)

    def block_status_filter(self, count, offset, contexts, extent64,
                            flags=0):
        u'''▶ send filtered block status command, with 64-bit callback

    Issue a filtered block status command to the NBD server.
    If supported by the server (see
    "nbd.can_block_status_payload"), this causes metadata
    context information about blocks beginning from the
    specified offset to be returned, and with the result
    limited to just the contexts specified in "filter". Note
    that all strings in "filter" must be supported by
    "nbd.can_meta_context".

    All other parameters to this function have the same
    semantics as in "nbd.block_status_64"; except that for
    convenience, unless <nbd_set_strict_flags(3)> was used
    to disable "STRICT_AUTO_FLAG", libnbd ignores the
    presence or absence of the flag "CMD_FLAG_PAYLOAD_LEN"
    in "flags", while correctly using the flag over the
    wire.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.block_status_filter(self._o, count, offset,
                                             contexts, extent64, flags)

    def poll(self, timeout):
        u'''▶ poll the handle once

    This is a simple implementation of poll(2) which is used
    internally by synchronous API calls. On success, it
    returns 0 if the "timeout" (in milliseconds) occurs, or
    1 if the poll completed and the state machine
    progressed. Set "timeout" to -1 to block indefinitely
    (but be careful that eventual action is actually
    expected - for example, if the connection is established
    but there are no commands in flight, using an infinite
    timeout will permanently block).

    This function is mainly useful as an example of how you
    might integrate libnbd with your own main loop, rather
    than being intended as something you would use.
'''
        self._check_not_closed()
        return libnbdmod.poll(self._o, timeout)

    def poll2(self, fd, timeout):
        u'''▶ poll the handle once, with fd

    This is the same as "nbd.poll", but an additional file
    descriptor parameter is passed. The additional fd is
    also polled (using "POLLIN"). One use for this is to
    wait for an eventfd(2).
'''
        self._check_not_closed()
        return libnbdmod.poll2(self._o, fd, timeout)

    def aio_connect(self, addr):
        u'''▶ connect to the NBD server

    Begin connecting to the NBD server. The "addr" and
    "addrlen" parameters specify the address of the socket
    to connect to.

    You can check if the connection attempt is still
    underway by calling "nbd.aio_is_connecting". If
    "nbd.set_opt_mode" is enabled, the connection is ready
    for manual option negotiation once
    "nbd.aio_is_negotiating" returns true; otherwise, the
    connection attempt will include the NBD handshake, and
    is ready for use once "nbd.aio_is_ready" returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_connect(self._o, addr)

    def aio_connect_uri(self, uri):
        u'''▶ connect to an NBD URI

    Begin connecting to the NBD URI "uri". Parameters behave
    as documented in "nbd.connect_uri".

    You can check if the connection attempt is still
    underway by calling "nbd.aio_is_connecting". If
    "nbd.set_opt_mode" is enabled, the connection is ready
    for manual option negotiation once
    "nbd.aio_is_negotiating" returns true; otherwise, the
    connection attempt will include the NBD handshake, and
    is ready for use once "nbd.aio_is_ready" returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_connect_uri(self._o, uri)

    def aio_connect_unix(self, unixsocket):
        u'''▶ connect to the NBD server over a Unix domain socket

    Begin connecting to the NBD server over Unix domain
    socket ("unixsocket"). Parameters behave as documented
    in "nbd.connect_unix".

    You can check if the connection attempt is still
    underway by calling "nbd.aio_is_connecting". If
    "nbd.set_opt_mode" is enabled, the connection is ready
    for manual option negotiation once
    "nbd.aio_is_negotiating" returns true; otherwise, the
    connection attempt will include the NBD handshake, and
    is ready for use once "nbd.aio_is_ready" returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_connect_unix(self._o, unixsocket)

    def aio_connect_vsock(self, cid, port):
        u'''▶ connect to the NBD server over AF_VSOCK socket

    Begin connecting to the NBD server over the "AF_VSOCK"
    protocol to the server "cid:port". Parameters behave as
    documented in "nbd.connect_vsock".

    You can check if the connection attempt is still
    underway by calling "nbd.aio_is_connecting". If
    "nbd.set_opt_mode" is enabled, the connection is ready
    for manual option negotiation once
    "nbd.aio_is_negotiating" returns true; otherwise, the
    connection attempt will include the NBD handshake, and
    is ready for use once "nbd.aio_is_ready" returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_connect_vsock(self._o, cid, port)

    def aio_connect_tcp(self, hostname, port):
        u'''▶ connect to the NBD server over a TCP port

    Begin connecting to the NBD server listening on
    "hostname:port". Parameters behave as documented in
    "nbd.connect_tcp".

    You can check if the connection attempt is still
    underway by calling "nbd.aio_is_connecting". If
    "nbd.set_opt_mode" is enabled, the connection is ready
    for manual option negotiation once
    "nbd.aio_is_negotiating" returns true; otherwise, the
    connection attempt will include the NBD handshake, and
    is ready for use once "nbd.aio_is_ready" returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_connect_tcp(self._o, hostname, port)

    def aio_connect_socket(self, sock):
        u'''▶ connect directly to a connected socket

    Begin connecting to the connected socket "fd".
    Parameters behave as documented in "nbd.connect_socket".

    You can check if the connection attempt is still
    underway by calling "nbd.aio_is_connecting". If
    "nbd.set_opt_mode" is enabled, the connection is ready
    for manual option negotiation once
    "nbd.aio_is_negotiating" returns true; otherwise, the
    connection attempt will include the NBD handshake, and
    is ready for use once "nbd.aio_is_ready" returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_connect_socket(self._o, sock)

    def aio_connect_command(self, argv):
        u'''▶ connect to the NBD server

    Run the command as a subprocess and begin connecting to
    it over stdin/stdout. Parameters behave as documented in
    "nbd.connect_command".

    You can check if the connection attempt is still
    underway by calling "nbd.aio_is_connecting". If
    "nbd.set_opt_mode" is enabled, the connection is ready
    for manual option negotiation once
    "nbd.aio_is_negotiating" returns true; otherwise, the
    connection attempt will include the NBD handshake, and
    is ready for use once "nbd.aio_is_ready" returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_connect_command(self._o, argv)

    def aio_connect_systemd_socket_activation(self, argv):
        u'''▶ connect using systemd socket activation

    Run the command as a subprocess and begin connecting to
    it using systemd socket activation. Parameters behave as
    documented in "nbd.connect_systemd_socket_activation".

    You can check if the connection attempt is still
    underway by calling "nbd.aio_is_connecting". If
    "nbd.set_opt_mode" is enabled, the connection is ready
    for manual option negotiation once
    "nbd.aio_is_negotiating" returns true; otherwise, the
    connection attempt will include the NBD handshake, and
    is ready for use once "nbd.aio_is_ready" returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_connect_systemd_socket_activation(self._o,
                                                               argv)

    def aio_opt_go(self, completion=None):
        u'''▶ end negotiation and move on to using an export

    Request that the server finish negotiation and move on
    to serving the export previously specified by the most
    recent "nbd.set_export_name" or "nbd.connect_uri". This
    can only be used if "nbd.set_opt_mode" enabled option
    mode.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that directly detecting whether the server
    returns an error (as is done by the return value of the
    synchronous counterpart) is only possible with a
    completion callback; however it is also possible to
    indirectly detect an error when "nbd.aio_is_negotiating"
    returns true.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_go(self._o, completion)

    def aio_opt_abort(self):
        u'''▶ end negotiation and close the connection

    Request that the server finish negotiation, gracefully
    if possible, then close the connection. This can only be
    used if "nbd.set_opt_mode" enabled option mode.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_abort(self._o)

    def aio_opt_starttls(self, completion=None):
        u'''▶ request the server to initiate TLS

    Request that the server initiate a secure TLS
    connection, by sending "NBD_OPT_STARTTLS". This behaves
    like the synchronous counterpart "nbd.opt_starttls",
    except that it does not wait for the server's response.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_starttls(self._o, completion)

    def aio_opt_extended_headers(self, completion=None):
        u'''▶ request the server to enable extended headers

    Request that the server use extended headers, by sending
    "NBD_OPT_EXTENDED_HEADERS". This behaves like the
    synchronous counterpart "nbd.opt_extended_headers",
    except that it does not wait for the server's response.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_extended_headers(self._o, completion)

    def aio_opt_structured_reply(self, completion=None):
        u'''▶ request the server to enable structured replies

    Request that the server use structured replies, by
    sending "NBD_OPT_STRUCTURED_REPLY". This behaves like
    the synchronous counterpart "nbd.opt_structured_reply",
    except that it does not wait for the server's response.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_structured_reply(self._o, completion)

    def aio_opt_list(self, list, completion=None):
        u'''▶ request the server to list all exports during negotiation

    Request that the server list all exports that it
    supports. This can only be used if "nbd.set_opt_mode"
    enabled option mode.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_list(self._o, list, completion)

    def aio_opt_info(self, completion=None):
        u'''▶ request the server for information about an export

    Request that the server supply information about the
    export name previously specified by the most recent
    "nbd.set_export_name" or "nbd.connect_uri". This can
    only be used if "nbd.set_opt_mode" enabled option mode.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_info(self._o, completion)

    def aio_opt_list_meta_context(self, context, completion=None):
        u'''▶ request list of available meta contexts, using implicit query

    Request that the server list available meta contexts
    associated with the export previously specified by the
    most recent "nbd.set_export_name" or "nbd.connect_uri",
    and with a list of queries from prior calls to
    "nbd.add_meta_context" (see
    "nbd.aio_opt_list_meta_context_queries" if you want to
    supply an explicit query list instead). This can only be
    used if "nbd.set_opt_mode" enabled option mode.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_list_meta_context(self._o, context,
                                                   completion)

    def aio_opt_list_meta_context_queries(self, queries, context,
                                          completion=None):
        u'''▶ request list of available meta contexts, using explicit query

    Request that the server list available meta contexts
    associated with the export previously specified by the
    most recent "nbd.set_export_name" or "nbd.connect_uri",
    and with an explicit list of queries provided as a
    parameter (see "nbd.aio_opt_list_meta_context" if you
    want to reuse an implicit query list instead). This can
    only be used if "nbd.set_opt_mode" enabled option mode.

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_list_meta_context_queries(self._o, queries,
                                                           context,
                                                           completion)

    def aio_opt_set_meta_context(self, context, completion=None):
        u'''▶ select specific meta contexts, with implicit query list

    Request that the server supply all recognized meta
    contexts registered through prior calls to
    "nbd.add_meta_context", in conjunction with the export
    previously specified by the most recent
    "nbd.set_export_name" or "nbd.connect_uri". This can
    only be used if "nbd.set_opt_mode" enabled option mode.
    Normally, this function is redundant, as "nbd.opt_go"
    automatically does the same task if structured replies
    or extended headers have already been negotiated. But
    manual control over meta context requests can be useful
    for fine-grained testing of how a server handles unusual
    negotiation sequences. Often, use of this function is
    coupled with "nbd.set_request_meta_context" to bypass
    the automatic context request normally performed by
    "nbd.opt_go".

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_set_meta_context(self._o, context,
                                                  completion)

    def aio_opt_set_meta_context_queries(self, queries, context,
                                         completion=None):
        u'''▶ select specific meta contexts, with explicit query list

    Request that the server supply all recognized meta
    contexts passed in through "queries", in conjunction
    with the export previously specified by the most recent
    "nbd.set_export_name" or "nbd.connect_uri". This can
    only be used if "nbd.set_opt_mode" enabled option mode.
    Normally, this function is redundant, as "nbd.opt_go"
    automatically does the same task if structured replies
    or extended headers have already been negotiated. But
    manual control over meta context requests can be useful
    for fine-grained testing of how a server handles unusual
    negotiation sequences. Often, use of this function is
    coupled with "nbd.set_request_meta_context" to bypass
    the automatic context request normally performed by
    "nbd.opt_go".

    To determine when the request completes, wait for
    "nbd.aio_is_connecting" to return false. Or supply the
    optional "completion_callback" which will be invoked as
    described in "Completion callbacks" in libnbd(3), except
    that it is automatically retired regardless of return
    value. Note that detecting whether the server returns an
    error (as is done by the return value of the synchronous
    counterpart) is only possible with a completion
    callback.
'''
        self._check_not_closed()
        return libnbdmod.aio_opt_set_meta_context_queries(self._o, queries,
                                                          context,
                                                          completion)

    def aio_pread(self, buf, offset, completion=None, flags=0):
        u'''▶ read from the NBD server

    Issue a read command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Note that you must ensure "buf" is valid until the
    command has completed. Furthermore, if the "error"
    parameter to "completion_callback" is set or if
    "nbd.aio_command_completed" reports failure, and if
    "nbd.get_pread_initialize" returns true, then libnbd
    sanitized "buf", but it is unspecified whether the
    contents of "buf" will read as zero or as partial
    results from the server. If "nbd.get_pread_initialize"
    returns false, then libnbd did not sanitize "buf", and
    the contents are undefined on failure.

    Other parameters behave as documented in "nbd.pread".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_pread(self._o, buf, offset, completion, flags)

    def aio_pread_structured(self, buf, offset, chunk, completion=None,
                             flags=0):
        u'''▶ read from the NBD server

    Issue a read command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Note that you must ensure "buf" is valid until the
    command has completed. Furthermore, if the "error"
    parameter to "completion_callback" is set or if
    "nbd.aio_command_completed" reports failure, and if
    "nbd.get_pread_initialize" returns true, then libnbd
    sanitized "buf", but it is unspecified whether the
    contents of "buf" will read as zero or as partial
    results from the server. If "nbd.get_pread_initialize"
    returns false, then libnbd did not sanitize "buf", and
    the contents are undefined on failure.

    Other parameters behave as documented in
    "nbd.pread_structured".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_pread_structured(self._o, buf, offset, chunk,
                                              completion, flags)

    def aio_pwrite(self, buf, offset, completion=None, flags=0):
        u'''▶ write to the NBD server

    Issue a write command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Note that you must ensure "buf" is valid until the
    command has completed. Other parameters behave as
    documented in "nbd.pwrite".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_pwrite(self._o, buf, offset, completion, flags)

    def aio_disconnect(self, flags=0):
        u'''▶ disconnect from the NBD server

    Issue the disconnect command to the NBD server. This is
    not a normal command because NBD servers are not obliged
    to send a reply. Instead you should wait for
    "nbd.aio_is_closed" to become true on the connection.
    Once this command is issued, you cannot issue any
    further commands.

    Although libnbd does not prevent you from issuing this
    command while still waiting on the replies to previous
    commands, the NBD protocol recommends that you wait
    until there are no other commands in flight (see
    "nbd.aio_in_flight"), to give the server a better chance
    at a clean shutdown.

    The "flags" parameter must be 0 for now (it exists for
    future NBD protocol extensions). There is no direct
    synchronous counterpart; however, "nbd.shutdown" will
    call this function if appropriate.
'''
        self._check_not_closed()
        return libnbdmod.aio_disconnect(self._o, flags)

    def aio_flush(self, completion=None, flags=0):
        u'''▶ send flush command to the NBD server

    Issue the flush command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Other parameters behave as documented in "nbd.flush".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_flush(self._o, completion, flags)

    def aio_trim(self, count, offset, completion=None, flags=0):
        u'''▶ send trim command to the NBD server

    Issue a trim command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Other parameters behave as documented in "nbd.trim".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_trim(self._o, count, offset, completion, flags)

    def aio_cache(self, count, offset, completion=None, flags=0):
        u'''▶ send cache (prefetch) command to the NBD server

    Issue the cache (prefetch) command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Other parameters behave as documented in "nbd.cache".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_cache(self._o, count, offset, completion,
                                   flags)

    def aio_zero(self, count, offset, completion=None, flags=0):
        u'''▶ send write zeroes command to the NBD server

    Issue a write zeroes command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Other parameters behave as documented in "nbd.zero".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_zero(self._o, count, offset, completion, flags)

    def aio_block_status(self, count, offset, extent, completion=None,
                         flags=0):
        u'''▶ send block status command, with 32-bit callback

    Send the block status command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Other parameters behave as documented in
    "nbd.block_status".

    This function is inherently limited to 32-bit values. If
    the server replies with a larger extent, the length of
    that extent will be truncated to just below 32 bits and
    any further extents from the server will be ignored. If
    the server replies with a status value larger than 32
    bits (only possible when extended headers are in use),
    the callback function will be passed an "EOVERFLOW"
    error. To get the full extent information from a server
    that supports 64-bit extents, you must use
    "nbd.aio_block_status_64".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_block_status(self._o, count, offset, extent,
                                          completion, flags)

    def aio_block_status_64(self, count, offset, extent64, completion=None,
                            flags=0):
        u'''▶ send block status command, with 64-bit callback

    Send the block status command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Other parameters behave as documented in
    "nbd.block_status_64".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_block_status_64(self._o, count, offset,
                                             extent64, completion, flags)

    def aio_block_status_filter(self, count, offset, contexts, extent64,
                                completion=None, flags=0):
        u'''▶ send filtered block status command to the NBD server

    Send a filtered block status command to the NBD server.

    To check if the command completed, call
    "nbd.aio_command_completed". Or supply the optional
    "completion_callback" which will be invoked as described
    in "Completion callbacks" in libnbd(3).

    Other parameters behave as documented in
    "nbd.block_status_filter".

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The "nbd.set_strict_mode" function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
'''
        self._check_not_closed()
        return libnbdmod.aio_block_status_filter(self._o, count, offset,
                                                 contexts, extent64,
                                                 completion, flags)

    def aio_get_fd(self):
        u'''▶ return file descriptor associated with this connection

    Return the underlying file descriptor associated with
    this connection. You can use this to check if the file
    descriptor is ready for reading or writing and call
    "nbd.aio_notify_read" or "nbd.aio_notify_write". See
    also "nbd.aio_get_direction". Do not do anything else
    with the file descriptor.
'''
        self._check_not_closed()
        return libnbdmod.aio_get_fd(self._o)

    def aio_get_direction(self):
        u'''▶ return the read or write direction

    Return the current direction of this connection, which
    means whether we are next expecting to read data from
    the server, write data to the server, or both. It
    returns

    0   We are not expected to interact with the server file
        descriptor from the current state. It is not worth
        attempting to use poll(2); if the connection is not
        dead, then state machine progress must instead come
        from some other means such as "nbd.aio_connect".

    "AIO_DIRECTION_READ" = 1
        We are expected next to read from the server. If
        using poll(2) you would set "events = POLLIN". If
        "revents" returns "POLLIN" or "POLLHUP" you would
        then call "nbd.aio_notify_read".

        Note that once libnbd reaches "nbd.aio_is_ready",
        this direction is returned even when there are no
        commands in flight (see "nbd.aio_in_flight"). In a
        single-threaded use of libnbd, it is not worth
        polling until after issuing a command, as otherwise
        the server will never wake up the poll. In a
        multi-threaded scenario, you can have one thread
        begin a polling loop prior to any commands, but any
        other thread that issues a command will need a way
        to kick the polling thread out of poll in case
        issuing the command changes the needed polling
        direction. Possible ways to do this include polling
        for activity on a pipe-to-self, or using
        pthread_kill(3) to send a signal that is masked
        except during ppoll(2).

    "AIO_DIRECTION_WRITE" = 2
        We are expected next to write to the server. If
        using poll(2) you would set "events = POLLOUT". If
        "revents" returns "POLLOUT" you would then call
        "nbd.aio_notify_write".

    "AIO_DIRECTION_BOTH" = 3
        We are expected next to either read or write to the
        server. If using poll(2) you would set "events =
        POLLIN|POLLOUT". If only one of "POLLIN" or
        "POLLOUT" is returned, then see above. However, if
        both are returned, it is better to call only
        "nbd.aio_notify_read", as processing the server's
        reply may change the state of the connection and
        invalidate the need to write more commands.
'''
        self._check_not_closed()
        return libnbdmod.aio_get_direction(self._o)

    def aio_notify_read(self):
        u'''▶ notify that the connection is readable

    Send notification to the state machine that the
    connection is readable. Typically this is called after
    your main loop has detected that the file descriptor
    associated with this connection is readable.
'''
        self._check_not_closed()
        return libnbdmod.aio_notify_read(self._o)

    def aio_notify_write(self):
        u'''▶ notify that the connection is writable

    Send notification to the state machine that the
    connection is writable. Typically this is called after
    your main loop has detected that the file descriptor
    associated with this connection is writable.
'''
        self._check_not_closed()
        return libnbdmod.aio_notify_write(self._o)

    def aio_is_created(self):
        u'''▶ check if the connection has just been created

    Return true if this connection has just been created.
    This is the state before the handle has started
    connecting to a server. In this state the handle can
    start to be connected by calling functions such as
    "nbd.aio_connect".
'''
        self._check_not_closed()
        return libnbdmod.aio_is_created(self._o)

    def aio_is_connecting(self):
        u'''▶ check if the connection is connecting or handshaking

    Return true if this connection is connecting to the
    server or in the process of handshaking and negotiating
    options which happens before the handle becomes ready to
    issue commands (see "nbd.aio_is_ready").
'''
        self._check_not_closed()
        return libnbdmod.aio_is_connecting(self._o)

    def aio_is_negotiating(self):
        u'''▶ check if connection is ready to send handshake option

    Return true if this connection is ready to start another
    option negotiation command while handshaking with the
    server. An option command will move back to the
    connecting state (see "nbd.aio_is_connecting"). Note
    that this state cannot be reached unless requested by
    "nbd.set_opt_mode", and even then it only works with
    newstyle servers; an oldstyle server will skip straight
    to "nbd.aio_is_ready".
'''
        self._check_not_closed()
        return libnbdmod.aio_is_negotiating(self._o)

    def aio_is_ready(self):
        u'''▶ check if the connection is in the ready state

    Return true if this connection is connected to the NBD
    server, the handshake has completed, and the connection
    is idle or waiting for a reply. In this state the handle
    is ready to issue commands.
'''
        self._check_not_closed()
        return libnbdmod.aio_is_ready(self._o)

    def aio_is_processing(self):
        u'''▶ check if the connection is processing a command

    Return true if this connection is connected to the NBD
    server, the handshake has completed, and the connection
    is processing commands (either writing out a request or
    reading a reply).

    Note the ready state ("nbd.aio_is_ready") is not
    included. In the ready state commands may be *in flight*
    (the *server* is processing them), but libnbd is not
    processing them.
'''
        self._check_not_closed()
        return libnbdmod.aio_is_processing(self._o)

    def aio_is_dead(self):
        u'''▶ check if the connection is dead

    Return true if the connection has encountered a fatal
    error and is dead. In this state the handle may only be
    closed. There is no way to recover a handle from the
    dead state.
'''
        self._check_not_closed()
        return libnbdmod.aio_is_dead(self._o)

    def aio_is_closed(self):
        u'''▶ check if the connection is closed

    Return true if the connection has closed. There is no
    way to reconnect a closed connection. Instead you must
    close the whole handle.
'''
        self._check_not_closed()
        return libnbdmod.aio_is_closed(self._o)

    def aio_command_completed(self, cookie):
        u'''▶ check if the command completed

    Return true if the command completed. If this function
    returns true then the command was successful and it has
    been retired. Return false if the command is still in
    flight. This can also fail with an error in case the
    command failed (in this case the command is also
    retired). A command is retired either via this command,
    or by using a completion callback which returns 1.

    The "cookie" parameter is the positive unique 64 bit
    cookie for the command, as returned by a call such as
    "nbd.aio_pread".
'''
        self._check_not_closed()
        return libnbdmod.aio_command_completed(self._o, cookie)

    def aio_peek_command_completed(self):
        u'''▶ check if any command has completed

    Return the unique positive 64 bit cookie of the first
    non-retired but completed command, 0 if there are
    in-flight commands but none of them are awaiting
    retirement, or -1 on error including when there are no
    in-flight commands. Any cookie returned by this function
    must still be passed to "nbd.aio_command_completed" to
    actually retire the command and learn whether the
    command was successful.
'''
        self._check_not_closed()
        return libnbdmod.aio_peek_command_completed(self._o)

    def aio_in_flight(self):
        u'''▶ check how many aio commands are still in flight

    Return the number of in-flight aio commands that are
    still awaiting a response from the server before they
    can be retired. If this returns a non-zero value when
    requesting a disconnect from the server (see
    "nbd.aio_disconnect" and "nbd.shutdown"), libnbd does
    not try to wait for those commands to complete
    gracefully; if the server strands commands while
    shutting down, "nbd.aio_command_completed" will report
    those commands as failed with a status of "ENOTCONN".
'''
        self._check_not_closed()
        return libnbdmod.aio_in_flight(self._o)

    def connection_state(self):
        u'''▶ return string describing the state of the connection

    Returns a descriptive string for the state of the
    connection. This can be used for debugging or
    troubleshooting, but you should not rely on the state of
    connections since it may change in future versions.
'''
        self._check_not_closed()
        return libnbdmod.connection_state(self._o)

    def get_package_name(self):
        u'''▶ return the name of the library

    Returns the name of the library, always "libnbd" unless
    the library was modified with another name at compile
    time.
'''
        self._check_not_closed()
        return libnbdmod.get_package_name(self._o)

    def get_version(self):
        u'''▶ return the version of the library

    Return the version of libnbd. This is returned as a
    string in the form "major.minor.release" where each of
    major, minor and release is a small positive integer.
    For example:

         minor
           ↓
        "1.0.3"
         ↑   ↑
     major   release

    major = 0
        The major number was 0 for the early experimental
        versions of libnbd where we still had an unstable
        API.

    major = 1
        The major number is 1 for the versions of libnbd
        with a long-term stable API and ABI. It is not
        anticipated that major will be any number other than
        1.

    minor = 0, 2, ... (even)
        The minor number is even for stable releases.

    minor = 1, 3, ... (odd)
        The minor number is odd for development versions.
        Note that new APIs added in a development version
        remain experimental and subject to change in that
        branch until they appear in a stable release.

    release
        The release number is incremented for each release
        along a particular branch.
'''
        self._check_not_closed()
        return libnbdmod.get_version(self._o)

    def kill_subprocess(self, signum):
        u'''▶ kill server running as a subprocess

    This call may be used to kill the server running as a
    subprocess that was previously created using
    "nbd.connect_command". You do not need to use this call.
    It is only needed if the server does not exit when the
    socket is closed.

    The "signum" parameter is the optional signal number to
    send (see signal(7)). If "signum" is 0 then "SIGTERM" is
    sent.
'''
        self._check_not_closed()
        return libnbdmod.kill_subprocess(self._o, signum)

    def get_subprocess_pid(self):
        u'''▶ get the process ID of the subprocess

    For connections which create a subprocess such as
    "nbd.connect_command", this returns the process ID (PID)
    of the subprocess. This is only supported on some
    platforms.

    This is mainly useful in debugging cases. For example,
    this could be used to learn where to attach gdb(1) to
    diagnose a crash in the NBD server subprocess.
'''
        self._check_not_closed()
        return libnbdmod.get_subprocess_pid(self._o)

    def supports_tls(self):
        u'''▶ true if libnbd was compiled with support for TLS

    Returns true if libnbd was compiled with gnutls which is
    required to support TLS encryption, or false if not.
'''
        self._check_not_closed()
        return libnbdmod.supports_tls(self._o)

    def supports_vsock(self):
        u'''▶ true if libnbd was compiled with support for AF_VSOCK

    Returns true if libnbd was compiled with support for the
    "AF_VSOCK" family of sockets, or false if not.

    Note that on the Linux operating system, this returns
    true if there is compile-time support, but you may still
    need runtime support for some aspects of AF_VSOCK usage;
    for example, use of "VMADDR_CID_LOCAL" as the server
    name requires that the *vsock_loopback* kernel module is
    loaded.
'''
        self._check_not_closed()
        return libnbdmod.supports_vsock(self._o)

    def supports_uri(self):
        u'''▶ true if libnbd was compiled with support for NBD URIs

    Returns true if libnbd was compiled with libxml2 which
    is required to support NBD URIs, or false if not.
'''
        self._check_not_closed()
        return libnbdmod.supports_uri(self._o)

    def get_uri(self):
        u'''▶ construct an NBD URI for a connection

    This makes a best effort attempt to construct an NBD URI
    which could be used to connect back to the same server
    (using "nbd.connect_uri").

    In some cases there is not enough information in the
    handle to successfully create a URI (eg. if you
    connected with "nbd.connect_socket"). In such cases the
    call returns "NULL" and further diagnostic information
    is available via "nbd.get_errno" and "nbd.get_error" as
    usual.

    Even if a URI is returned it is not guaranteed to work,
    and it may not be optimal.

    nbdinfo(1) *--uri* option is a way to access this API
    from shell scripts.
'''
        self._check_not_closed()
        return libnbdmod.get_uri(self._o)

    def is_uri(self, uri):
        u'''▶ detect if a string could be an NBD URI

    Detect if the parameter "uri" could be an NBD URI or
    not. The function returns true if "uri" is likely to be
    an NBD URI, or false if not.

    This can be used to write programs that take either a
    URI or something else like a filename as a parameter.
    nbdcopy(1) is one such program.

    The current test is heuristic. In particular it *does
    not* guarantee that "nbd.connect_uri" will work.
'''
        self._check_not_closed()
        return libnbdmod.is_uri(self._o, uri)


package_name = NBD().get_package_name()
__version__ = NBD().get_version()

if __name__ == "__main__":
    import nbdsh

    nbdsh.shell()
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (* NBD client library in userspace
 * WARNING: THIS FILE IS GENERATED FROM
 * generator/generator
 * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
 *
 * Copyright Red Hat
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *)

(** OCaml bindings for libnbd.

    For full documentation see libnbd-ocaml(3) and libnbd(3).

    For examples written in OCaml see the libnbd source code
    [ocaml/examples] subdirectory.
*)

exception Error of string * Unix.error option
(** Exception thrown when an API call fails.

    The string is the error message, and the int is the {!Unix.error}
    (if available).
*)

exception Closed of string
(** Exception thrown if you call a closed handle. *)

type cookie = int64

type extent = int64 * int64
(** Length and flags of an extent in {!block_status_64} callback. *)

module TLS : sig
  type t =
  | DISABLE
  | ALLOW
  | REQUIRE
  | UNKNOWN of int
end

module SIZE : sig
  type t =
  | MINIMUM
  | PREFERRED
  | MAXIMUM
  | PAYLOAD
  | UNKNOWN of int
end

module CMD_FLAG : sig
  type t =
  | FUA
  | NO_HOLE
  | DF
  | REQ_ONE
  | FAST_ZERO
  | PAYLOAD_LEN
  | UNKNOWN of int

  val mask : t list
end

module HANDSHAKE_FLAG : sig
  type t =
  | FIXED_NEWSTYLE
  | NO_ZEROES
  | UNKNOWN of int

  val mask : t list
end

module STRICT : sig
  type t =
  | COMMANDS
  | FLAGS
  | BOUNDS
  | ZERO_SIZE
  | ALIGN
  | PAYLOAD
  | AUTO_FLAG
  | UNKNOWN of int

  val mask : t list
end

module ALLOW_TRANSPORT : sig
  type t =
  | TCP
  | UNIX
  | VSOCK
  | SSH
  | UNKNOWN of int

  val mask : t list
end

module SHUTDOWN : sig
  type t =
  | ABANDON_PENDING
  | UNKNOWN of int

  val mask : t list
end

val aio_direction_read : int32
val aio_direction_write : int32
val aio_direction_both : int32
val read_data : int32
val read_hole : int32
val read_error : int32
val namespace_base : string
val context_base_allocation : string
val state_hole : int32
val state_zero : int32
val namespace_qemu : string
val context_qemu_dirty_bitmap : string
val state_dirty : int32
val context_qemu_allocation_depth : string

module Buffer : sig
  type t =
    (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
  (** A buffer that persists across calls, used in {!aio_pread},
      {!aio_pwrite} and similar.

      In libnbd ≤ 1.18 this was a specially implemented type.
      This was inefficient as zero copy was not possible.

      In libnbd ≥ 1.20 this is just an alias for a {!Bigarray},
      so you can use functions from {!Bigarray.Array1} directly
      if you prefer.  This also allows zero copy.

      This type is compatible with the
      {{:https://v3.ocaml.org/p/bigstring/latest}[bigstring]} and
      {{:https://v3.ocaml.org/p/bigstringaf/latest}[bigstringaf]}
      libraries. *)

  val alloc : int -> t
  (** Allocate an uninitialized buffer.  The parameter is the size
      in bytes.

      In libnbd ≥ 1.20 this is an alias for {!Bigarray.Array1.create}. *)

  val to_bytes : t -> bytes
  (** Copy buffer to an OCaml [bytes] object.

      In libnbd ≥ 1.20 you can read from the bigarray directly to avoid
      copying if you want. *)

  val to_string : t -> string
  (** Same as {!to_bytes} but returns a [string] instead. *)

  val of_bytes : bytes -> t
  (** Copy an OCaml [bytes] object to a newly allocated buffer.

      In libnbd ≥ 1.20 you can write to the bigarray directly to avoid
      copying if you want. *)

  val of_string : string -> t
  (** Same as {!of_bytes} but takes a [string] instead. *)

  val size : t -> int
  (** Return the size of the buffer.

      In libnbd ≥ 1.20 this is an alias for {!Bigarray.Array1.dim}. *)

  val is_zero : ?sub:(int * int) -> t -> bool
  (** Return true if and only if the buffer contains only zero bytes.

      The optional [?sub = (offset, len)] can be used to check part
      of a buffer. *)

end
(** Persistent buffer used in AIO calls. *)

val errno_of_unix_error : Unix.error -> int
(** Return the raw C errno corresponding to a {!Unix.error}.  This
    can be used in callbacks to update the [int ref] parameter. *)

type t
(** The handle. *)

val create : unit -> t
(** Create a new handle. *)

val close : t -> unit
(** Close a handle.

    Handles can also be closed by the garbage collector when
    they become unreachable.  This call is used only if you want
    to force the handle to close now and reclaim resources
    immediately.
*)

val with_handle : (t -> 'a) -> 'a
(** Wrapper around {!create}.  It calls the function parameter with a
    newly created handle, and ensures that {!close} is always called
    even if the function throws an exception.

    Use this when it is essential that the handle is closed in order
    to free up external resources in a timely manner; for example if
    running the server as a subprocess and you want to ensure that the
    subprocess is always killed; or if you need to disconnect from the
    server before continuing with another operation. *)

val set_debug : t -> bool -> unit
(** [NBD.set_debug t debug]

    set or clear the debug flag

    Set or clear the debug flag. When debugging is enabled,
    debugging messages from the library are printed to
    stderr, unless a debugging callback has been defined too
    (see nbd_set_debug_callback(3)) in which case they are
    sent to that function. This flag defaults to false on
    newly created handles, except if "LIBNBD_DEBUG=1" is set
    in the environment in which case it defaults to true.
*)

val get_debug : t -> bool
(** [NBD.get_debug t]

    return the state of the debug flag

    Return the state of the debug flag on this handle.
*)

val set_debug_callback : t -> (string -> string -> int) -> unit
(** [NBD.set_debug_callback t debug]

    set the debug callback

    Set the debug callback. This function is called when the
    library emits debug messages, when debugging is enabled
    on a handle. The callback parameters are "user_data"
    passed to this function, the name of the libnbd function
    emitting the debug message ("context"), and the message
    itself ("msg"). If no debug callback is set on a handle
    then messages are printed on "stderr".

    The callback should not call "nbd_*" APIs on the same
    handle since it can be called while holding the handle
    lock and will cause a deadlock.
*)

val clear_debug_callback : t -> unit
(** [NBD.clear_debug_callback t]

    clear the debug callback

    Remove the debug callback if one was previously
    associated with the handle (with
    nbd_set_debug_callback(3)). If no callback was
    associated this does nothing.
*)

val stats_bytes_sent : t -> int64
(** [NBD.stats_bytes_sent t]

    statistics of bytes sent over connection so far

    Return the number of bytes that the client has sent to
    the server.

    This tracks the plaintext bytes utilized by the NBD
    protocol; it may differ from the number of bytes
    actually sent over the connection, particularly when TLS
    is in use.
*)

val stats_chunks_sent : t -> int64
(** [NBD.stats_chunks_sent t]

    statistics of chunks sent over connection so far

    Return the number of chunks that the client has sent to
    the server, where a chunk is a group of bytes delineated
    by a magic number that cannot be further subdivided
    without breaking the protocol.

    This number does not necessarily relate to the number of
    API calls made, nor to the number of TCP packets sent
    over the connection.
*)

val stats_bytes_received : t -> int64
(** [NBD.stats_bytes_received t]

    statistics of bytes received over connection so far

    Return the number of bytes that the client has received
    from the server.

    This tracks the plaintext bytes utilized by the NBD
    protocol; it may differ from the number of bytes
    actually received over the connection, particularly when
    TLS is in use.
*)

val stats_chunks_received : t -> int64
(** [NBD.stats_chunks_received t]

    statistics of chunks received over connection so far

    Return the number of chunks that the client has received
    from the server, where a chunk is a group of bytes
    delineated by a magic number that cannot be further
    subdivided without breaking the protocol.

    This number does not necessarily relate to the number of
    API calls made, nor to the number of TCP packets
    received over the connection.
*)

val set_handle_name : t -> string -> unit
(** [NBD.set_handle_name t handle_name]

    set the handle name

    Handles have a name which is unique within the current
    process. The handle name is used in debug output.

    Handle names are normally generated automatically and
    have the form "nbd1", "nbd2", etc., but you can
    optionally use this call to give the handles a name
    which is meaningful for your application to make
    debugging output easier to understand.
*)

val get_handle_name : t -> string
(** [NBD.get_handle_name t]

    get the handle name

    Get the name of the handle. If it was previously set by
    calling nbd_set_handle_name(3) then this returns the
    name that was set. Otherwise it will return a generic
    name like "nbd1", "nbd2", etc.
*)

val set_private_data : t -> int -> int
(** [NBD.set_private_data t private_data]

    set the per-handle private data

    Handles contain a private data field for applications to
    use for any purpose.

    When calling libnbd from C, the type of this field is
    "uintptr_t" so it can be used to store an unsigned
    integer or a pointer.

    In non-C bindings it can be used to store an unsigned
    integer.

    This function sets the value of this field and returns
    the old value (or 0 if it was not previously set).
*)

val get_private_data : t -> int
(** [NBD.get_private_data t]

    get the per-handle private data

    Return the value of the private data field set
    previously by a call to nbd_set_private_data(3) (or 0 if
    it was not previously set).
*)

val set_export_name : t -> string -> unit
(** [NBD.set_export_name t export_name]

    set the export name

    For servers which require an export name or can serve
    different content on different exports, set the
    "export_name" to connect to. The default is the empty
    string "".

    This is only relevant when connecting to servers using
    the newstyle protocol as the oldstyle protocol did not
    support export names. The NBD protocol limits export
    names to 4096 bytes, but servers may not support the
    full length. The encoding of export names is always
    UTF-8.

    When option mode is not in use, the export name must be
    set before beginning a connection. However, when
    nbd_set_opt_mode(3) has enabled option mode, it is
    possible to change the export name prior to
    nbd_opt_go(3). In particular, the use of nbd_opt_list(3)
    during negotiation can be used to determine a name the
    server is likely to accept, and nbd_opt_info(3) can be
    used to learn details about an export before connecting.

    This call may be skipped if using nbd_connect_uri(3) to
    connect to a URI that includes an export name.
*)

val get_export_name : t -> string
(** [NBD.get_export_name t]

    get the export name

    Get the export name associated with the handle. This is
    the name that libnbd requests; see
    nbd_get_canonical_export_name(3) for determining if the
    server has a different canonical name for the given
    export (most common when requesting the default export
    name of an empty string "")
*)

val set_request_block_size : t -> bool -> unit
(** [NBD.set_request_block_size t request]

    control whether NBD_OPT_GO requests block size

    By default, when connecting to an export, libnbd
    requests that the server report any block size
    restrictions. The NBD protocol states that a server may
    supply block sizes regardless of whether the client
    requests them, and libnbd will report those block sizes
    (see nbd_get_block_size(3)); conversely, if a client
    does not request block sizes, the server may reject the
    connection instead of dealing with a client sending
    unaligned requests. This function makes it possible to
    test server behavior by emulating older clients.

    Note that even when block size is requested, the server
    is not obligated to provide any. Furthermore, if block
    sizes are provided (whether or not the client requested
    them), libnbd enforces alignment to those sizes unless
    nbd_set_strict_mode(3) is used to bypass client-side
    safety checks.
*)

val get_request_block_size : t -> bool
(** [NBD.get_request_block_size t]

    see if NBD_OPT_GO requests block size

    Return the state of the block size request flag on this
    handle.
*)

val set_full_info : t -> bool -> unit
(** [NBD.set_full_info t request]

    control whether NBD_OPT_GO requests extra details

    By default, when connecting to an export, libnbd only
    requests the details it needs to service data
    operations. The NBD protocol says that a server can
    supply optional information, such as a canonical name of
    the export (see nbd_get_canonical_export_name(3)) or a
    description of the export (see
    nbd_get_export_description(3)), but that a hint from the
    client makes it more likely for this extra information
    to be provided. This function controls whether libnbd
    will provide that hint.

    Note that even when full info is requested, the server
    is not obligated to reply with all information that
    libnbd requested. Similarly, libnbd will ignore any
    optional server information that libnbd has not yet been
    taught to recognize. Furthermore, the hint to request
    block sizes is independently controlled via
    nbd_set_request_block_size(3).
*)

val get_full_info : t -> bool
(** [NBD.get_full_info t]

    see if NBD_OPT_GO requests extra details

    Return the state of the full info request flag on this
    handle.
*)

val get_canonical_export_name : t -> string
(** [NBD.get_canonical_export_name t]

    return the canonical export name, if the server has one

    The NBD protocol permits a server to report an optional
    canonical export name, which may differ from the
    client's request (as set by nbd_set_export_name(3) or
    nbd_connect_uri(3)). This function accesses any name
    returned by the server; it may be the same as the client
    request, but is more likely to differ when the client
    requested a connection to the default export name (an
    empty string "").

    Some servers are unlikely to report a canonical name
    unless the client specifically hinted about wanting it,
    via nbd_set_full_info(3).
*)

val get_export_description : t -> string
(** [NBD.get_export_description t]

    return the export description, if the server has one

    The NBD protocol permits a server to report an optional
    export description. This function reports any
    description returned by the server.

    Some servers are unlikely to report a description unless
    the client specifically hinted about wanting it, via
    nbd_set_full_info(3). For qemu-nbd(8), a description is
    set with *-D*.
*)

val set_tls : t -> TLS.t -> unit
(** [NBD.set_tls t tls]

    enable or require TLS (authentication and encryption)

    Enable or require TLS (authenticated and encrypted
    connections) to the NBD server. The possible settings
    are:

    "LIBNBD_TLS_DISABLE"
        Disable TLS. (The default setting, unless using
        nbd_connect_uri(3) with a URI that requires TLS).

        This setting is also necessary if you use
        nbd_set_opt_mode(3) and want to interact in
        plaintext with a server that implements the NBD
        protocol's "SELECTIVETLS" mode, prior to enabling
        TLS with nbd_opt_starttls(3). Most NBD servers with
        TLS support prefer the NBD protocol's "FORCEDTLS"
        mode, so this sort of manual interaction tends to be
        useful mainly during integration testing.

    "LIBNBD_TLS_ALLOW"
        Enable TLS if possible.

        This option is insecure (or best effort) in that in
        some cases it will fall back to an unencrypted
        and/or unauthenticated connection if TLS could not
        be established. Use "LIBNBD_TLS_REQUIRE" below if
        the connection must be encrypted.

        Some servers will drop the connection if TLS fails
        so fallback may not be possible.

    "LIBNBD_TLS_REQUIRE"
        Require an encrypted and authenticated TLS
        connection. Always fail to connect if the connection
        is not encrypted and authenticated.

    As well as calling this you may also need to supply the
    path to the certificates directory
    (nbd_set_tls_certificates(3)), the username
    (nbd_set_tls_username(3)) and/or the Pre-Shared Keys
    (PSK) file (nbd_set_tls_psk_file(3)). For now, when
    using nbd_connect_uri(3), any URI query parameters
    related to TLS are not handled automatically. Setting
    the level higher than zero will fail if libnbd was not
    compiled against gnutls; you can test whether this is
    the case with nbd_supports_tls(3).
*)

val get_tls : t -> TLS.t
(** [NBD.get_tls t]

    get the TLS request setting

    Get the TLS request setting.

    Note: If you want to find out if TLS was actually
    negotiated on a particular connection use
    nbd_get_tls_negotiated(3) instead.
*)

val get_tls_negotiated : t -> bool
(** [NBD.get_tls_negotiated t]

    find out if TLS was negotiated on a connection

    After connecting you may call this to find out if the
    connection is using TLS.

    This is normally useful only if you set the TLS request
    mode to "LIBNBD_TLS_ALLOW" (see nbd_set_tls(3)), because
    in this mode we try to use TLS but fall back to
    unencrypted if it was not available. This function will
    tell you if TLS was negotiated or not.

    In "LIBNBD_TLS_REQUIRE" mode (the most secure) the
    connection would have failed if TLS could not be
    negotiated. With "LIBNBD_TLS_DISABLE" mode, TLS is not
    tried automatically; but if the NBD server uses the
    less-common "SELECTIVETLS" mode, this function reports
    whether a manual nbd_opt_starttls(3) enabled TLS or if
    the connection is still plaintext.
*)

val set_tls_certificates : t -> string -> unit
(** [NBD.set_tls_certificates t dir]

    set the path to the TLS certificates directory

    Set the path to the TLS certificates directory. If not
    set and TLS is used then a compiled in default is used.
    For root this is "/etc/pki/libnbd/". For non-root this
    is "$HOME/.pki/libnbd" and "$HOME/.config/pki/libnbd".
    If none of these directories can be found then the
    system trusted CAs are used.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless nbd_set_tls(3)
    is also used to request or require TLS.
*)

val set_tls_verify_peer : t -> bool -> unit
(** [NBD.set_tls_verify_peer t verify]

    set whether we verify the identity of the server

    Set this flag to control whether libnbd will verify the
    identity of the server from the server's certificate and
    the certificate authority. This defaults to true when
    connecting to TCP servers using TLS certificate
    authentication, and false otherwise.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless nbd_set_tls(3)
    is also used to request or require TLS.
*)

val get_tls_verify_peer : t -> bool
(** [NBD.get_tls_verify_peer t]

    get whether we verify the identity of the server

    Get the verify peer flag.
*)

val set_tls_username : t -> string -> unit
(** [NBD.set_tls_username t username]

    set the TLS username

    Set the TLS client username. This is used if
    authenticating with PSK over TLS is enabled. If not set
    then the local username is used.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless nbd_set_tls(3)
    is also used to request or require TLS.
*)

val get_tls_username : t -> string
(** [NBD.get_tls_username t]

    get the current TLS username

    Get the current TLS username.
*)

val set_tls_hostname : t -> string -> unit
(** [NBD.set_tls_hostname t hostname]

    set the TLS hostname

    Set the TLS server hostname. This is used in preference
    to the hostname supplied when connecting (eg. through
    nbd_connect_tcp(3)), or when there is no explicit
    hostname at all (nbd_connect_unix(3)). It can be useful
    when you are connecting to a proxy which is forwarding
    the data to the final server, to specify the name of the
    final server so that the server's certificate can be
    checked.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless nbd_set_tls(3)
    is also used to request or require TLS.
*)

val get_tls_hostname : t -> string
(** [NBD.get_tls_hostname t]

    get the effective TLS hostname

    Get the TLS server hostname in effect. If not set, this
    returns the empty string (not an error).
*)

val set_tls_psk_file : t -> string -> unit
(** [NBD.set_tls_psk_file t filename]

    set the TLS Pre-Shared Keys (PSK) filename

    Set the TLS Pre-Shared Keys (PSK) filename. This is used
    if trying to authenticate to the server using with a
    pre-shared key. There is no default so if this is not
    set then PSK authentication cannot be used to connect to
    the server.

    This function may be called regardless of whether TLS is
    supported, but will have no effect unless nbd_set_tls(3)
    is also used to request or require TLS.
*)

val set_request_extended_headers : t -> bool -> unit
(** [NBD.set_request_extended_headers t request]

    control use of extended headers

    By default, libnbd tries to negotiate extended headers
    with the server, as this protocol extension permits the
    use of 64-bit zero, trim, and block status actions.
    However, for integration testing, it can be useful to
    clear this flag rather than find a way to alter the
    server to fail the negotiation request.

    For backwards compatibility, the setting of this knob is
    ignored if nbd_set_request_structured_replies(3) is also
    set to false, since the use of extended headers implies
    structured replies.
*)

val get_request_extended_headers : t -> bool
(** [NBD.get_request_extended_headers t]

    see if extended headers are attempted

    Return the state of the request extended headers flag on
    this handle.

    Note: If you want to find out if extended headers were
    actually negotiated on a particular connection use
    nbd_get_extended_headers_negotiated(3) instead.
*)

val get_extended_headers_negotiated : t -> bool
(** [NBD.get_extended_headers_negotiated t]

    see if extended headers are in use

    After connecting you may call this to find out if the
    connection is using extended headers. Note that this
    setting is sticky; this can return true even after a
    second nbd_opt_extended_headers(3) returns false because
    the server detected a duplicate request.

    When extended headers are not in use, commands are
    limited to a 32-bit length, even when the libnbd API
    uses a 64-bit parameter to express the length. But even
    when extended headers are supported, the server may
    enforce other limits, visible through
    nbd_get_block_size(3).

    Note that when extended headers are negotiated, you
    should prefer the use of nbd_block_status_64(3) instead
    of nbd_block_status(3) if any of the meta contexts you
    requested via nbd_add_meta_context(3) might return
    64-bit status values; however, all of the well-known
    meta contexts covered by current "LIBNBD_CONTEXT_*"
    constants only return 32-bit status.
*)

val set_request_structured_replies : t -> bool -> unit
(** [NBD.set_request_structured_replies t request]

    control use of structured replies

    By default, libnbd tries to negotiate structured replies
    with the server, as this protocol extension must be in
    use before nbd_can_meta_context(3) or nbd_can_df(3) can
    return true. However, for integration testing, it can be
    useful to clear this flag rather than find a way to
    alter the server to fail the negotiation request. It is
    also useful to set this to false prior to using
    nbd_set_opt_mode(3) if it is desired to control when to
    send nbd_opt_structured_reply(3) during negotiation.

    Note that setting this knob to false also disables any
    automatic request for extended headers.
*)

val get_request_structured_replies : t -> bool
(** [NBD.get_request_structured_replies t]

    see if structured replies are attempted

    Return the state of the request structured replies flag
    on this handle.

    Note: If you want to find out if structured replies were
    actually negotiated on a particular connection use
    nbd_get_structured_replies_negotiated(3) instead.
*)

val get_structured_replies_negotiated : t -> bool
(** [NBD.get_structured_replies_negotiated t]

    see if structured replies are in use

    After connecting you may call this to find out if the
    connection is using structured replies. Note that this
    setting is sticky; this can return true even after a
    second nbd_opt_structured_reply(3) returns false because
    the server detected a duplicate request.

    Note that if the connection negotiates extended headers,
    this function returns true (as extended headers imply
    structured replies) even if no explicit request for
    structured replies was attempted.
*)

val set_request_meta_context : t -> bool -> unit
(** [NBD.set_request_meta_context t request]

    control whether connect automatically requests meta contexts

    This function controls whether the act of connecting to
    an export (all "nbd_connect_*" calls when
    nbd_set_opt_mode(3) is false, or nbd_opt_go(3) and
    nbd_opt_info(3) when option mode is enabled) will also
    try to issue NBD_OPT_SET_META_CONTEXT when the server
    supports structured replies or extended headers and any
    contexts were registered by nbd_add_meta_context(3). The
    default setting is true; however the extra step of
    negotiating meta contexts is not always desirable:
    performing both info and go on the same export works
    without needing to re-negotiate contexts on the second
    call; integration testing of other servers may benefit
    from manual invocation of nbd_opt_set_meta_context(3) at
    other times in the negotiation sequence; and even when
    using just nbd_opt_info(3), it can be faster to collect
    the server's results by relying on the callback function
    passed to nbd_opt_list_meta_context(3) than a series of
    post-process calls to nbd_can_meta_context(3).

    Note that this control has no effect if the server does
    not negotiate structured replies or extended headers, or
    if the client did not request any contexts via
    nbd_add_meta_context(3). Setting this control to false
    may cause nbd_block_status(3) to fail.
*)

val get_request_meta_context : t -> bool
(** [NBD.get_request_meta_context t]

    see if connect automatically requests meta contexts

    Return the state of the automatic meta context request
    flag on this handle.
*)

val set_handshake_flags : t -> HANDSHAKE_FLAG.t list -> unit
(** [NBD.set_handshake_flags t flags]

    control use of handshake flags

    By default, libnbd tries to negotiate all possible
    handshake flags that are also supported by the server,
    since omitting a handshake flag can prevent the use of
    other functionality such as TLS encryption or structured
    replies. However, for integration testing, it can be
    useful to reduce the set of flags supported by the
    client to test that a particular server can handle
    various clients that were compliant to older versions of
    the NBD specification.

    The "flags" argument is a bitmask, including zero or
    more of the following handshake flags:

    "LIBNBD_HANDSHAKE_FLAG_FIXED_NEWSTYLE" = 1
        The server gracefully handles unknown option
        requests from the client, rather than disconnecting.
        Without this flag, a client cannot safely request to
        use extensions such as TLS encryption or structured
        replies, as the request may cause an older server to
        drop the connection.

    "LIBNBD_HANDSHAKE_FLAG_NO_ZEROES" = 2
        If the client is forced to use "NBD_OPT_EXPORT_NAME"
        instead of the preferred "NBD_OPT_GO", this flag
        allows the server to send fewer all-zero padding
        bytes over the connection.

    For convenience, the constant
    "LIBNBD_HANDSHAKE_FLAG_MASK" is available to describe
    all flags supported by this build of libnbd. Future NBD
    extensions may add further flags, which in turn may be
    enabled by default in newer libnbd. As such, when
    attempting to disable only one specific bit, it is wiser
    to first call nbd_get_handshake_flags(3) and modify that
    value, rather than blindly setting a constant value.
*)

val get_handshake_flags : t -> HANDSHAKE_FLAG.t list
(** [NBD.get_handshake_flags t]

    see which handshake flags are supported

    Return the state of the handshake flags on this handle.
    When the handle has not yet completed a connection (see
    nbd_aio_is_created(3)), this returns the flags that the
    client is willing to use, provided the server also
    advertises those flags. After the connection is ready
    (see nbd_aio_is_ready(3)), this returns the flags that
    were actually agreed on between the server and client.
    If the NBD protocol defines new handshake flags, then
    the return value from a newer library version may
    include bits that were undefined at the time of
    compilation.
*)

val set_pread_initialize : t -> bool -> unit
(** [NBD.set_pread_initialize t request]

    control whether libnbd pre-initializes read buffers

    By default, libnbd will pre-initialize the contents of a
    buffer passed to calls such as nbd_pread(3) to all
    zeroes prior to checking for any other errors, so that
    even if a client application passed in an uninitialized
    buffer but fails to check for errors, it will not result
    in a potential security risk caused by an accidental
    leak of prior heap contents (see CVE-2022-0485 in
    libnbd-security(3) for an example of a security hole in
    an application built against an earlier version of
    libnbd that lacked consistent pre-initialization).
    However, for a client application that has audited that
    an uninitialized buffer is never dereferenced, or which
    performs its own pre-initialization, libnbd's
    sanitization efforts merely pessimize performance
    (although the time spent in pre-initialization may pale
    in comparison to time spent waiting on network packets).

    Calling this function with "request" set to false tells
    libnbd to skip the buffer initialization step in read
    commands.
*)

val get_pread_initialize : t -> bool
(** [NBD.get_pread_initialize t]

    see whether libnbd pre-initializes read buffers

    Return whether libnbd performs a pre-initialization of a
    buffer passed to nbd_pread(3) and similar to all zeroes,
    as set by nbd_set_pread_initialize(3).
*)

val set_strict_mode : t -> STRICT.t list -> unit
(** [NBD.set_strict_mode t flags]

    control how strictly to follow NBD protocol

    By default, libnbd tries to detect requests that would
    trigger undefined behavior in the NBD protocol, and
    rejects them client side without causing any network
    traffic, rather than risking undefined server behavior.
    However, for integration testing, it can be handy to
    relax the strictness of libnbd, to coerce it into
    sending such requests over the network for testing the
    robustness of the server in dealing with such traffic.

    The "flags" argument is a bitmask, including zero or
    more of the following strictness flags:

    "LIBNBD_STRICT_COMMANDS" = 0x1
        If set, this flag rejects client requests that do
        not comply with the set of advertised server flags
        (for example, attempting a write on a read-only
        server, or attempting to use "LIBNBD_CMD_FLAG_FUA"
        when nbd_can_fua(3) returned false). If clear, this
        flag relies on the server to reject unexpected
        commands.

    "LIBNBD_STRICT_FLAGS" = 0x2
        If set, this flag rejects client requests that
        attempt to set a command flag not recognized by
        libnbd (those outside of "LIBNBD_CMD_FLAG_MASK"), or
        a flag not normally associated with a command (such
        as using "LIBNBD_CMD_FLAG_FUA" on a read command).
        If clear, all flags are sent on to the server, even
        if sending such a flag may cause the server to
        change its reply in a manner that confuses libnbd,
        perhaps causing deadlock or ending the connection.

        Flags that are known by libnbd as associated with a
        given command (such as "LIBNBD_CMD_FLAG_DF" for
        nbd_pread_structured(3) gated by nbd_can_df(3)) are
        controlled by "LIBNBD_STRICT_COMMANDS" instead; and
        "LIBNBD_CMD_FLAG_PAYLOAD_LEN" is managed
        automatically by libnbd unless
        "LIBNBD_STRICT_AUTO_FLAG" is disabled.

        Note that the NBD protocol only supports 16 bits of
        command flags, even though the libnbd API uses
        "uint32_t"; bits outside of the range permitted by
        the protocol are always a client-side error.

    "LIBNBD_STRICT_BOUNDS" = 0x4
        If set, this flag rejects client requests that would
        exceed the export bounds without sending any traffic
        to the server. If clear, this flag relies on the
        server to detect out-of-bounds requests.

    "LIBNBD_STRICT_ZERO_SIZE" = 0x8
        If set, this flag rejects client requests with
        length 0. If clear, this permits zero-length
        requests to the server, which may produce undefined
        results.

    "LIBNBD_STRICT_ALIGN" = 0x10
        If set, and the server provided minimum block sizes
        (see "LIBNBD_SIZE_MINIMUM" for
        nbd_get_block_size(3)), this flag rejects client
        requests that do not have length and offset aligned
        to the server's minimum requirements, except for an
        unaligned length that extends to the end of an image
        with an overall unaligned size. If clear, all
        unaligned requests are sent to the server, where it
        is up to the server whether to honor or reject the
        request.

    "LIBNBD_STRICT_PAYLOAD" = 0x20
        If set, the client refuses to send a command to the
        server with more than libnbd's outgoing payload
        maximum (see "LIBNBD_SIZE_PAYLOAD" for
        nbd_get_block_size(3)), whether or not the server
        advertised a block size maximum. If clear, oversize
        requests up to 64MiB may be attempted, although
        requests larger than 32MiB are liable to cause some
        servers to disconnect.

    "LIBNBD_STRICT_AUTO_FLAG" = 0x40
        If set, commands that accept the
        "LIBNBD_CMD_FLAG_PAYLOAD_LEN" flag (such as
        nbd_pwrite(3) and nbd_block_status_filter(3)) ignore
        the presence or absence of that flag from the
        caller, instead sending the value over the wire that
        matches the server's expectations based on whether
        extended headers were negotiated when the connection
        was made. If clear, the caller takes on the
        responsibility for whether the payload length flag
        is set or clear during the affected command, which
        can be useful during integration testing but is more
        likely to lead to undefined behavior.

    For convenience, the constant "LIBNBD_STRICT_MASK" is
    available to describe all strictness flags supported by
    this build of libnbd. Future versions of libnbd may add
    further flags, which are likely to be enabled by default
    for additional client-side filtering. As such, when
    attempting to relax only one specific bit while keeping
    remaining checks at the client side, it is wiser to
    first call nbd_get_strict_mode(3) and modify that value,
    rather than blindly setting a constant value.
*)

val get_strict_mode : t -> STRICT.t list
(** [NBD.get_strict_mode t]

    see which strictness flags are in effect

    Return flags indicating which protocol strictness items
    are being enforced locally by libnbd rather than the
    server. The return value from a newer library version
    may include bits that were undefined at the time of
    compilation.
*)

val set_opt_mode : t -> bool -> unit
(** [NBD.set_opt_mode t enable]

    control option mode, for pausing during option negotiation

    Set this flag to true in order to request that a
    connection command "nbd_connect_*" will pause for
    negotiation options rather than proceeding all the way
    to the ready state, when communicating with a newstyle
    server. This setting has no effect when connecting to an
    oldstyle server.

    Note that libnbd defaults to attempting
    "NBD_OPT_STARTTLS", "NBD_OPT_EXTENDED_HEADERS", and
    "NBD_OPT_STRUCTURED_REPLY" before letting you control
    remaining negotiation steps; if you need control over
    these steps as well, first set nbd_set_tls(3) to
    "LIBNBD_TLS_DISABLE", and
    nbd_set_request_extended_headers(3) or
    nbd_set_request_structured_replies(3) to false, before
    starting the connection attempt.

    When option mode is enabled, you have fine-grained
    control over which options are negotiated, compared to
    the default of the server negotiating everything on your
    behalf using settings made before starting the
    connection. To leave the mode and proceed on to the
    ready state, you must use nbd_opt_go(3) successfully; a
    failed nbd_opt_go(3) returns to the negotiating state to
    allow a change of export name before trying again. You
    may also use nbd_opt_abort(3) or nbd_shutdown(3) to end
    the connection without finishing negotiation.
*)

val get_opt_mode : t -> bool
(** [NBD.get_opt_mode t]

    return whether option mode was enabled

    Return true if option negotiation mode was enabled on
    this handle.
*)

val opt_go : t -> unit
(** [NBD.opt_go t]

    end negotiation and move on to using an export

    Request that the server finish negotiation and move on
    to serving the export previously specified by the most
    recent nbd_set_export_name(3) or nbd_connect_uri(3).
    This can only be used if nbd_set_opt_mode(3) enabled
    option mode.

    By default, libnbd will automatically request all meta
    contexts registered by nbd_add_meta_context(3) as part
    of this call; but this can be suppressed with
    nbd_set_request_meta_context(3), particularly if
    nbd_opt_set_meta_context(3) was used earlier in the
    negotiation sequence.

    If this fails, the server may still be in negotiation,
    where it is possible to attempt another option such as a
    different export name; although older servers will
    instead have killed the connection.
*)

val opt_abort : t -> unit
(** [NBD.opt_abort t]

    end negotiation and close the connection

    Request that the server finish negotiation, gracefully
    if possible, then close the connection. This can only be
    used if nbd_set_opt_mode(3) enabled option mode.
*)

val opt_starttls : t -> bool
(** [NBD.opt_starttls t]

    request the server to initiate TLS

    Request that the server initiate a secure TLS
    connection, by sending "NBD_OPT_STARTTLS". This can only
    be used if nbd_set_opt_mode(3) enabled option mode;
    furthermore, if you use nbd_set_tls(3) to request
    anything other than the default of "LIBNBD_TLS_DISABLE",
    then libnbd will have already attempted a TLS connection
    prior to allowing you control over option negotiation.
    This command is disabled if nbd_supports_tls(3) reports
    false.

    This function is mainly useful for integration testing
    of corner cases in server handling; in particular,
    misuse of this function when coupled with a server that
    is not careful about resetting stateful commands such as
    nbd_opt_structured_reply(3) could result in a security
    hole (see CVE-2021-3716 against nbdkit, for example).
    Thus, when security is a concern, you should instead
    prefer to use nbd_set_tls(3) with "LIBNBD_TLS_REQUIRE"
    and let libnbd negotiate TLS automatically.

    This function returns true if the server replies with
    success, false if the server replies with an error, and
    fails only if the server does not reply (such as for a
    loss of connection, which can include when the server
    rejects credentials supplied during the TLS handshake).
    Note that the NBD protocol documents that requesting TLS
    after it is already enabled is a client error; most
    servers will gracefully fail a second request, but that
    does not downgrade a TLS session that has already been
    established, as reported by nbd_get_tls_negotiated(3).
*)

val opt_extended_headers : t -> bool
(** [NBD.opt_extended_headers t]

    request the server to enable extended headers

    Request that the server use extended headers, by sending
    "NBD_OPT_EXTENDED_HEADERS". This can only be used if
    nbd_set_opt_mode(3) enabled option mode; furthermore,
    libnbd defaults to automatically requesting this unless
    you use nbd_set_request_extended_headers(3) or
    nbd_set_request_structured_replies(3) prior to
    connecting. This function is mainly useful for
    integration testing of corner cases in server handling.

    This function returns true if the server replies with
    success, false if the server replies with an error, and
    fails only if the server does not reply (such as for a
    loss of connection). Note that some servers fail a
    second request as redundant; libnbd assumes that once
    one request has succeeded, then extended headers are
    supported (as visible by
    nbd_get_extended_headers_negotiated(3)) regardless if
    later calls to this function return false. If this
    function returns true, the use of structured replies is
    implied.
*)

val opt_structured_reply : t -> bool
(** [NBD.opt_structured_reply t]

    request the server to enable structured replies

    Request that the server use structured replies, by
    sending "NBD_OPT_STRUCTURED_REPLY". This can only be
    used if nbd_set_opt_mode(3) enabled option mode;
    furthermore, libnbd defaults to automatically requesting
    this unless you use
    nbd_set_request_structured_replies(3) prior to
    connecting. This function is mainly useful for
    integration testing of corner cases in server handling.

    This function returns true if the server replies with
    success, false if the server replies with an error, and
    fails only if the server does not reply (such as for a
    loss of connection). Note that some servers fail a
    second request as redundant; libnbd assumes that once
    one request has succeeded, then structured replies are
    supported (as visible by
    nbd_get_structured_replies_negotiated(3)) regardless if
    later calls to this function return false. Similarly, a
    server may fail this request if extended headers are
    already negotiated, since extended headers take
    priority.
*)

val opt_list : t -> (string -> string -> int) -> int
(** [NBD.opt_list t list]

    request the server to list all exports during negotiation

    Request that the server list all exports that it
    supports. This can only be used if nbd_set_opt_mode(3)
    enabled option mode.

    The "list" function is called once per advertised
    export, with any "user_data" passed to this function,
    and with "name" and "description" supplied by the
    server. Many servers omit descriptions, in which case
    "description" will be an empty string. Remember that it
    is not safe to call nbd_set_export_name(3) from within
    the context of the callback function; rather, your code
    must copy any "name" needed for later use after this
    function completes. At present, the return value of the
    callback is ignored, although a return of -1 should be
    avoided.

    For convenience, when this function succeeds, it returns
    the number of exports that were advertised by the
    server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list to avoid being an information leak, may
    encounter a failure after delivering partial results, or
    may refuse to answer more than one query per connection
    in the interest of avoiding negotiation that does not
    resolve. Thus, this function may succeed even when no
    exports are reported, or may fail but have a non-empty
    list. Likewise, the NBD protocol does not specify an
    upper bound for the number of exports that might be
    advertised, so client code should be aware that a server
    may send a lengthy list.

    For nbd-server(1) you will need to allow clients to make
    list requests by adding "allowlist=true" to the
    "[generic]" section of /etc/nbd-server/config. For
    qemu-nbd(8), a description is set with *-D*.
*)

val opt_info : t -> unit
(** [NBD.opt_info t]

    request the server for information about an export

    Request that the server supply information about the
    export name previously specified by the most recent
    nbd_set_export_name(3) or nbd_connect_uri(3). This can
    only be used if nbd_set_opt_mode(3) enabled option mode.

    If successful, functions like nbd_is_read_only(3) and
    nbd_get_size(3) will report details about that export.
    If nbd_set_request_meta_context(3) is set (the default)
    and structured replies or extended headers were
    negotiated, it is also valid to use
    nbd_can_meta_context(3) after this call. However, it may
    be more efficient to clear that setting and manually
    utilize nbd_opt_list_meta_context(3) with its callback
    approach, for learning which contexts an export
    supports. In general, if nbd_opt_go(3) is called next,
    that call will likely succeed with the details remaining
    the same, although this is not guaranteed by all
    servers.

    Not all servers understand this request, and even when
    it is understood, the server might fail the request even
    when a corresponding nbd_opt_go(3) would succeed.
*)

val opt_list_meta_context : t -> (string -> int) -> int
(** [NBD.opt_list_meta_context t context]

    list available meta contexts, using implicit query list

    Request that the server list available meta contexts
    associated with the export previously specified by the
    most recent nbd_set_export_name(3) or
    nbd_connect_uri(3), and with a list of queries from
    prior calls to nbd_add_meta_context(3) (see
    nbd_opt_list_meta_context_queries(3) if you want to
    supply an explicit query list instead). This can only be
    used if nbd_set_opt_mode(3) enabled option mode.

    The NBD protocol allows a client to decide how many
    queries to ask the server. Rather than taking that list
    of queries as a parameter to this function, libnbd
    reuses the current list of requested meta contexts as
    set by nbd_add_meta_context(3); you can use
    nbd_clear_meta_contexts(3) to set up a different list of
    queries. When the list is empty, a server will typically
    reply with all contexts that it supports; when the list
    is non-empty, the server will reply only with supported
    contexts that match the client's request. Note that a
    reply by the server might be encoded to represent
    several feasible contexts within one string, rather than
    multiple strings per actual context name that would
    actually succeed during nbd_opt_go(3); so it is still
    necessary to use nbd_can_meta_context(3) after
    connecting to see which contexts are actually supported.

    The "context" function is called once per server reply,
    with any "user_data" passed to this function, and with
    "name" supplied by the server. Remember that it is not
    safe to call nbd_add_meta_context(3) from within the
    context of the callback function; rather, your code must
    copy any "name" needed for later use after this function
    completes. At present, the return value of the callback
    is ignored, although a return of -1 should be avoided.

    For convenience, when this function succeeds, it returns
    the number of replies returned by the server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list because it does not support the requested
    context, or may encounter a failure after delivering
    partial results. Thus, this function may succeed even
    when no contexts are reported, or may fail but have a
    non-empty list. Likewise, the NBD protocol does not
    specify an upper bound for the number of replies that
    might be advertised, so client code should be aware that
    a server may send a lengthy list.
*)

val opt_list_meta_context_queries : t -> string list -> (string -> int) -> int
(** [NBD.opt_list_meta_context_queries t queries context]

    list available meta contexts, using explicit query list

    Request that the server list available meta contexts
    associated with the export previously specified by the
    most recent nbd_set_export_name(3) or
    nbd_connect_uri(3), and with an explicit list of queries
    provided as a parameter (see
    nbd_opt_list_meta_context(3) if you want to reuse an
    implicit query list instead). This can only be used if
    nbd_set_opt_mode(3) enabled option mode.

    The NBD protocol allows a client to decide how many
    queries to ask the server. For this function, the list
    is explicit in the "queries" parameter. When the list is
    empty, a server will typically reply with all contexts
    that it supports; when the list is non-empty, the server
    will reply only with supported contexts that match the
    client's request. Note that a reply by the server might
    be encoded to represent several feasible contexts within
    one string, rather than multiple strings per actual
    context name that would actually succeed during
    nbd_opt_go(3); so it is still necessary to use
    nbd_can_meta_context(3) after connecting to see which
    contexts are actually supported.

    The "context" function is called once per server reply,
    with any "user_data" passed to this function, and with
    "name" supplied by the server. Remember that it is not
    safe to call nbd_add_meta_context(3) from within the
    context of the callback function; rather, your code must
    copy any "name" needed for later use after this function
    completes. At present, the return value of the callback
    is ignored, although a return of -1 should be avoided.

    For convenience, when this function succeeds, it returns
    the number of replies returned by the server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list because it does not support the requested
    context, or may encounter a failure after delivering
    partial results. Thus, this function may succeed even
    when no contexts are reported, or may fail but have a
    non-empty list. Likewise, the NBD protocol does not
    specify an upper bound for the number of replies that
    might be advertised, so client code should be aware that
    a server may send a lengthy list.
*)

val opt_set_meta_context : t -> (string -> int) -> int
(** [NBD.opt_set_meta_context t context]

    select specific meta contexts, using implicit query list

    Request that the server supply all recognized meta
    contexts registered through prior calls to
    nbd_add_meta_context(3), in conjunction with the export
    previously specified by the most recent
    nbd_set_export_name(3) or nbd_connect_uri(3). This can
    only be used if nbd_set_opt_mode(3) enabled option mode.
    Normally, this function is redundant, as nbd_opt_go(3)
    automatically does the same task if structured replies
    or extended headers have already been negotiated. But
    manual control over meta context requests can be useful
    for fine-grained testing of how a server handles unusual
    negotiation sequences. Often, use of this function is
    coupled with nbd_set_request_meta_context(3) to bypass
    the automatic context request normally performed by
    nbd_opt_go(3).

    The NBD protocol allows a client to decide how many
    queries to ask the server. Rather than taking that list
    of queries as a parameter to this function, libnbd
    reuses the current list of requested meta contexts as
    set by nbd_add_meta_context(3); you can use
    nbd_clear_meta_contexts(3) to set up a different list of
    queries (see nbd_opt_set_meta_context_queries(3) to pass
    an explicit list of contexts instead). Since this
    function is primarily designed for testing servers,
    libnbd does not prevent the use of this function on an
    empty list or when nbd_set_request_structured_replies(3)
    has disabled structured replies, in order to see how a
    server behaves.

    The "context" function is called once per server reply,
    with any "user_data" passed to this function, and with
    "name" supplied by the server. Additionally, each server
    name will remain visible through nbd_can_meta_context(3)
    until the next attempt at nbd_set_export_name(3) or
    nbd_opt_set_meta_context(3), as well as nbd_opt_go(3) or
    nbd_opt_info(3) that trigger an automatic meta context
    request. Remember that it is not safe to call any
    "nbd_*" APIs from within the context of the callback
    function. At present, the return value of the callback
    is ignored, although a return of -1 should be avoided.

    For convenience, when this function succeeds, it returns
    the number of replies returned by the server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list because it does not support the requested
    context, or may encounter a failure after delivering
    partial results. Thus, this function may succeed even
    when no contexts are reported, or may fail but have a
    non-empty list.
*)

val opt_set_meta_context_queries : t -> string list -> (string -> int) -> int
(** [NBD.opt_set_meta_context_queries t queries context]

    select specific meta contexts, using explicit query list

    Request that the server supply all recognized meta
    contexts passed in through "queries", in conjunction
    with the export previously specified by the most recent
    nbd_set_export_name(3) or nbd_connect_uri(3). This can
    only be used if nbd_set_opt_mode(3) enabled option mode.
    Normally, this function is redundant, as nbd_opt_go(3)
    automatically does the same task if structured replies
    or extended headers have already been negotiated. But
    manual control over meta context requests can be useful
    for fine-grained testing of how a server handles unusual
    negotiation sequences. Often, use of this function is
    coupled with nbd_set_request_meta_context(3) to bypass
    the automatic context request normally performed by
    nbd_opt_go(3).

    The NBD protocol allows a client to decide how many
    queries to ask the server. This function takes an
    explicit list of queries; to instead reuse an implicit
    list, see nbd_opt_set_meta_context(3). Since this
    function is primarily designed for testing servers,
    libnbd does not prevent the use of this function on an
    empty list or when nbd_set_request_structured_replies(3)
    has disabled structured replies, in order to see how a
    server behaves.

    The "context" function is called once per server reply,
    with any "user_data" passed to this function, and with
    "name" supplied by the server. Additionally, each server
    name will remain visible through nbd_can_meta_context(3)
    until the next attempt at nbd_set_export_name(3) or
    nbd_opt_set_meta_context(3), as well as nbd_opt_go(3) or
    nbd_opt_info(3) that trigger an automatic meta context
    request. Remember that it is not safe to call any
    "nbd_*" APIs from within the context of the callback
    function. At present, the return value of the callback
    is ignored, although a return of -1 should be avoided.

    For convenience, when this function succeeds, it returns
    the number of replies returned by the server.

    Not all servers understand this request, and even when
    it is understood, the server might intentionally send an
    empty list because it does not support the requested
    context, or may encounter a failure after delivering
    partial results. Thus, this function may succeed even
    when no contexts are reported, or may fail but have a
    non-empty list.
*)

val add_meta_context : t -> string -> unit
(** [NBD.add_meta_context t name]

    ask server to negotiate metadata context

    During connection libnbd can negotiate zero or more
    metadata contexts with the server. Metadata contexts are
    features (such as "base:allocation") which describe
    information returned by the nbd_block_status_64(3)
    command (for "base:allocation" this is whether blocks of
    data are allocated, zero or sparse).

    This call adds one metadata context to the list to be
    negotiated. You can call it as many times as needed. The
    list is initially empty when the handle is created; you
    can check the contents of the list with
    nbd_get_nr_meta_contexts(3) and nbd_get_meta_context(3),
    or clear it with nbd_clear_meta_contexts(3).

    The NBD protocol limits meta context names to 4096
    bytes, but servers may not support the full length. The
    encoding of meta context names is always UTF-8.

    Not all servers support all metadata contexts. To learn
    if a context was actually negotiated, call
    nbd_can_meta_context(3) after connecting.

    The single parameter is the name of the metadata
    context, for example "LIBNBD_CONTEXT_BASE_ALLOCATION".
    <libnbd.h> includes defined constants beginning with
    "LIBNBD_CONTEXT_" for some well-known contexts, but you
    are free to pass in other contexts.

    Other metadata contexts are server-specific, but include
    "qemu:dirty-bitmap:..." and "qemu:allocation-depth" for
    qemu-nbd (see qemu-nbd *-B* and *-A* options).
*)

val get_nr_meta_contexts : t -> int
(** [NBD.get_nr_meta_contexts t]

    return the current number of requested meta contexts

    During connection libnbd can negotiate zero or more
    metadata contexts with the server. Metadata contexts are
    features (such as "base:allocation") which describe
    information returned by the nbd_block_status_64(3)
    command (for "base:allocation" this is whether blocks of
    data are allocated, zero or sparse).

    This command returns how many meta contexts have been
    added to the list to request from the server via
    nbd_add_meta_context(3). The server is not obligated to
    honor all of the requests; to see what it actually
    supports, see nbd_can_meta_context(3).
*)

val get_meta_context : t -> int -> string
(** [NBD.get_meta_context t i]

    return the i'th meta context request

    During connection libnbd can negotiate zero or more
    metadata contexts with the server. Metadata contexts are
    features (such as "base:allocation") which describe
    information returned by the nbd_block_status_64(3)
    command (for "base:allocation" this is whether blocks of
    data are allocated, zero or sparse).

    This command returns the i'th meta context request, as
    added by nbd_add_meta_context(3), and bounded by
    nbd_get_nr_meta_contexts(3).
*)

val clear_meta_contexts : t -> unit
(** [NBD.clear_meta_contexts t]

    reset the list of requested meta contexts

    During connection libnbd can negotiate zero or more
    metadata contexts with the server. Metadata contexts are
    features (such as "base:allocation") which describe
    information returned by the nbd_block_status_64(3)
    command (for "base:allocation" this is whether blocks of
    data are allocated, zero or sparse).

    This command resets the list of meta contexts to request
    back to an empty list, for re-population by further use
    of nbd_add_meta_context(3). It is primarily useful when
    option negotiation mode is selected (see
    nbd_set_opt_mode(3)), for altering the list of attempted
    contexts between subsequent export queries.
*)

val set_uri_allow_transports : t -> ALLOW_TRANSPORT.t list -> unit
(** [NBD.set_uri_allow_transports t mask]

    set the allowed transports in NBD URIs

    Set which transports are allowed to appear in NBD URIs.
    The default is to allow any transport.

    The "mask" parameter may contain any of the following
    flags ORed together:

    "LIBNBD_ALLOW_TRANSPORT_TCP" = 0x1
    "LIBNBD_ALLOW_TRANSPORT_UNIX" = 0x2
    "LIBNBD_ALLOW_TRANSPORT_VSOCK" = 0x4
    "LIBNBD_ALLOW_TRANSPORT_SSH" = 0x8

    For convenience, the constant
    "LIBNBD_ALLOW_TRANSPORT_MASK" is available to describe
    all transports recognized by this build of libnbd. A
    future version of the library may add new flags.
*)

val set_uri_allow_tls : t -> TLS.t -> unit
(** [NBD.set_uri_allow_tls t tls]

    set the allowed TLS settings in NBD URIs

    Set which TLS settings are allowed to appear in NBD
    URIs. The default is to allow either non-TLS or TLS
    URIs.

    The "tls" parameter can be:

    "LIBNBD_TLS_DISABLE"
        TLS URIs are not permitted, ie. a URI such as
        "nbds://..." will be rejected.

    "LIBNBD_TLS_ALLOW"
        This is the default. TLS may be used or not,
        depending on whether the URI uses "nbds" or "nbd".

    "LIBNBD_TLS_REQUIRE"
        TLS URIs are required. All URIs must use "nbds".
*)

val set_uri_allow_local_file : t -> bool -> unit
(** [NBD.set_uri_allow_local_file t allow]

    set the allowed transports in NBD URIs

    Allow NBD URIs to reference local files. This is
    *disabled* by default.

    Currently this setting only controls whether the
    "tls-psk-file" parameter in NBD URIs is allowed.
*)

val connect_uri : t -> string -> unit
(** [NBD.connect_uri t uri]

    connect to NBD URI

    Connect (synchronously) to an NBD server and export by
    specifying the NBD URI. NBD URIs are a standard way to
    specify a network block device endpoint, using a syntax
    like "nbd://example.com" which is convenient, well
    defined and future proof.

    This call works by parsing the URI parameter and calling
    nbd_set_export_name(3) and nbd_set_tls(3) and other
    calls as needed, followed by nbd_connect_tcp(3),
    nbd_connect_unix(3) or nbd_connect_vsock(3).

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but nbd_set_opt_mode(3) can be used for manual
    control over option negotiation performed before
    transmission phase.

  Example URIs supported
    "nbd://example.com"
        Connect over TCP, unencrypted, to "example.com" port
        10809.

    "nbds://example.com"
        Connect over TCP with TLS, to "example.com" port
        10809. If the server does not support TLS then this
        will fail.

    "nbd+unix:///foo?socket=/tmp/nbd.sock"
        Connect over the Unix domain socket /tmp/nbd.sock to
        an NBD server running locally. The export name is
        set to "foo" (note without any leading "/"
        character).

    "nbds+unix://alice@/?socket=/tmp/nbd.sock&tls-certificat
    es=certs"
        Connect over a Unix domain socket, enabling TLS and
        setting the path to a directory containing
        certificates and keys.

    "nbd+vsock:///"
        In this scenario libnbd is running in a virtual
        machine. Connect over "AF_VSOCK" to an NBD server
        running on the hypervisor.

    "nbd+ssh://server/"
        Connect to remote "server" using Secure Shell, and
        tunnel NBD to an NBD server listening on port 10809.

  Supported URI formats
    The following schemes are supported in the current
    version of libnbd:

    "nbd:"
        Connect over TCP without using TLS.

    "nbds:"
        Connect over TCP. TLS is required and the connection
        will fail if the server does not support TLS.

    "nbd+unix:"
    "nbds+unix:"
        Connect over a Unix domain socket, without or with
        TLS respectively. The "socket" parameter is
        required.

    "nbd+vsock:"
    "nbds+vsock:"
        Connect over the "AF_VSOCK" transport, without or
        with TLS respectively. You can use
        nbd_supports_vsock(3) to see if this build of libnbd
        supports "AF_VSOCK".

    "nbd+ssh:"
    "nbds+ssh:"
        *Experimental*

        Tunnel NBD over a Secure Shell connection. This
        requires that ssh(1) is installed locally, and that
        nc(1) (from the nmap project) is installed on the
        remote server.

    The authority part of the URI
    ("[username@][servername][:port]") is parsed depending
    on the transport. For TCP it specifies the server to
    connect to and optional port number. For "+unix" it
    should not be present. For "+vsock" the server name is
    the numeric CID (eg. 2 to connect to the host), and the
    optional port number may be present. For "+ssh" the
    Secure Shell server and optional port. If the "username"
    is present it is used for TLS authentication.

    For all transports, an export name may be present,
    parsed in accordance with the NBD URI specification.

    Finally the query part of the URI can contain:

    socket=SOCKET
        Specifies the Unix domain socket to connect on. Must
        be present for the "+unix" transport, optional for
        "+ssh", and must not be present for the other
        transports.

    tls-certificates=DIR
        Set the certificates directory. See
        nbd_set_tls_certificates(3). Note this is not
        allowed by default - see next section.

    tls-psk-file=PSKFILE
        Set the PSK file. See nbd_set_tls_psk_file(3). Note
        this is not allowed by default - see next section.

    tls-hostname="SERVER"
        Set the TLS hostname. See nbd_set_tls_hostname(3).

    tls-verify-peer=false
        Do not verify the server certificate. See
        nbd_set_tls_verify_peer(3). The default is "true".

  Disable URI features
    For security reasons you might want to disable certain
    URI features. Pre-filtering URIs is error-prone and
    should not be attempted. Instead use the libnbd APIs
    below to control what can appear in URIs. Note you must
    call these functions on the same handle before calling
    nbd_connect_uri(3) or nbd_aio_connect_uri(3).

    TCP, Unix domain socket, "AF_VSOCK" or SSH transports
        Default: all allowed

        To select which transports are allowed call
        nbd_set_uri_allow_transports(3).

    TLS Default: both non-TLS and TLS connections allowed

        To force TLS off or on in URIs call
        nbd_set_uri_allow_tls(3).

    Connect to Unix domain socket in the local filesystem
        Default: allowed

        To prevent this you must disable the "+unix"
        transport using nbd_set_uri_allow_transports(3).

    Read from local files
        Default: denied

        To allow URIs to contain references to local files
        (eg. for parameters like "tls-psk-file") call
        nbd_set_uri_allow_local_file(3).

  Overriding the export name
    It is possible to override the export name portion of a
    URI by using nbd_set_opt_mode(3) to enable option mode,
    then using nbd_set_export_name(3) and nbd_opt_go(3) as
    part of subsequent negotiation.

  Optional features
    This call will fail if libnbd was not compiled with
    libxml2; you can test whether this is the case with
    nbd_supports_uri(3).

    Support for URIs that require TLS will fail if libnbd
    was not compiled with gnutls; you can test whether this
    is the case with nbd_supports_tls(3).

  Constructing a URI from an existing connection
    See nbd_get_uri(3).

  See if a string is an NBD URI
    See nbd_is_uri(3).

  Differences from qemu and glib parsing of NBD URIs
    qemu(1) also supports NBD URIs and has a separate URI
    parser. In qemu ≤ 9.0 this was done using their own
    parser. In qemu ≥ 9.1 this is done using glib "g_uri"
    functions. The current (glib-based) parser does not
    parse the export name part of the URI in exactly the
    same way as libnbd, which may cause URIs to work in
    libnbd but not in qemu or *vice versa*. Only URIs using
    exportnames should be affected. For details see
    <https://gitlab.com/qemu-project/qemu/-/issues/2584>.

  Limitations on vsock port numbers
    The vsock(7) protocol allows 32 bit unsigned ports,
    reserving ports 0, 1 and 2 for special purposes. In
    Linux, ports < 1024 are reserved for privileged
    processes.

    libxml2 (used to parse the URI) imposes additional
    restrictions. libxml2 < 2.9 limited port numbers to
    99,999,999. libxml2 ≥ 2.9 limits port numbers to ≤
    0x7fff_ffff (31 bits).
*)

val connect_unix : t -> string -> unit
(** [NBD.connect_unix t unixsocket]

    connect to NBD server over a Unix domain socket

    Connect (synchronously) over the named Unix domain
    socket ("unixsocket") to an NBD server running on the
    same machine.

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but nbd_set_opt_mode(3) can be used for manual
    control over option negotiation performed before
    transmission phase.
*)

val connect_vsock : t -> int64 (* uint32_t *) -> int64 (* uint32_t *) -> unit
(** [NBD.connect_vsock t cid port]

    connect to NBD server over AF_VSOCK protocol

    Connect (synchronously) over the "AF_VSOCK" protocol
    from a virtual machine to an NBD server, usually running
    on the host. The "cid" and "port" parameters specify the
    server address. Usually "cid" should be 2 (to connect to
    the host), and "port" might be 10809 or another port
    number assigned to you by the host administrator.

    Not all systems support "AF_VSOCK"; to determine if
    libnbd was built on a system with vsock support, see
    nbd_supports_vsock(3).

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but nbd_set_opt_mode(3) can be used for manual
    control over option negotiation performed before
    transmission phase.
*)

val connect_tcp : t -> string -> string -> unit
(** [NBD.connect_tcp t hostname port]

    connect to NBD server over a TCP port

    Connect (synchronously) to the NBD server listening on
    "hostname:port". The "port" may be a port name such as
    "nbd", or it may be a port number as a string such as
    "10809".

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but nbd_set_opt_mode(3) can be used for manual
    control over option negotiation performed before
    transmission phase.
*)

val connect_socket : t -> Unix.file_descr -> unit
(** [NBD.connect_socket t sock]

    connect directly to a connected socket

    Pass a connected socket "sock" through which libnbd will
    talk to the NBD server.

    The caller is responsible for creating and connecting
    this socket by some method, before passing it to libnbd.

    If this call returns without error then socket ownership
    is passed to libnbd. Libnbd will close the socket when
    the handle is closed. The caller must not use the socket
    in any way.

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but nbd_set_opt_mode(3) can be used for manual
    control over option negotiation performed before
    transmission phase.
*)

val connect_command : t -> string list -> unit
(** [NBD.connect_command t argv]

    connect to NBD server command

    Run the command as a subprocess and connect to it over
    stdin/stdout. This is for use with NBD servers which can
    behave like inetd clients, such as nbdkit(1) using the
    *-s*/*--single* flag, and nbd-server(1) with port number
    set to 0.

    To run qemu-nbd(1), use
    nbd_connect_systemd_socket_activation(3) instead.

  Subprocess
    Libnbd will fork the "argv" command and pass the NBD
    socket to it using file descriptors 0 and 1
    (stdin/stdout):

     ┌─────────┬─────────┐    ┌────────────────┐
     │ program │ libnbd  │    │   NBD server   │
     │         │         │    │       (argv)   │
     │         │ socket ╍╍╍╍╍╍╍╍▶ stdin/stdout │
     └─────────┴─────────┘    └────────────────┘

    When the NBD handle is closed the server subprocess is
    killed.

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but nbd_set_opt_mode(3) can be used for manual
    control over option negotiation performed before
    transmission phase.
*)

val connect_systemd_socket_activation : t -> string list -> unit
(** [NBD.connect_systemd_socket_activation t argv]

    connect using systemd socket activation

    Run the command as a subprocess and connect to it using
    systemd socket activation.

    This is especially useful for running qemu-nbd(1) as a
    subprocess of libnbd, for example to use it to open
    qcow2 files.

    To run nbdkit as a subprocess, this function can be
    used, or nbd_connect_command(3).

    To run nbd-server(1) as a subprocess, this function
    cannot be used, you must use nbd_connect_command(3).

  Socket activation
    Libnbd will fork the "argv" command and pass an NBD
    socket to it using special "LISTEN_*" environment
    variables (as defined by the systemd socket activation
    protocol).

     ┌─────────┬─────────┐    ┌───────────────┐
     │ program │ libnbd  │    │  qemu-nbd or  │
     │         │         │    │  other server │
     │         │ socket ╍╍╍╍╍╍╍╍▶             │
     └─────────┴─────────┘    └───────────────┘

    When the NBD handle is closed the server subprocess is
    killed.

   Socket name
    The socket activation protocol lets you optionally give
    the socket a name. If used, the name is passed to the
    NBD server using the "LISTEN_FDNAMES" environment
    variable. To provide a socket name, call
    nbd_set_socket_activation_name(3) before calling the
    connect function.

    This call returns when the connection has been made. By
    default, this proceeds all the way to transmission
    phase, but nbd_set_opt_mode(3) can be used for manual
    control over option negotiation performed before
    transmission phase.
*)

val set_socket_activation_name : t -> string -> unit
(** [NBD.set_socket_activation_name t socket_name]

    set the socket activation name

    When running an NBD server using
    nbd_connect_systemd_socket_activation(3) you can
    optionally name the socket. Call this function before
    connecting to the server.

    Some servers such as qemu-storage-daemon(1) can use this
    information to associate the socket with a name used on
    the command line, but most servers will ignore it. The
    name is passed through the "LISTEN_FDNAMES" environment
    variable.

    The parameter "socket_name" can be a short alphanumeric
    string. If it is set to the empty string (also the
    default when the handle is created) then the name
    "unknown" will be seen by the server.
*)

val get_socket_activation_name : t -> string
(** [NBD.get_socket_activation_name t]

    get the socket activation name

    Return the socket name used when you call
    nbd_connect_systemd_socket_activation(3) on the same
    handle. By default this will return the empty string
    meaning that the server will see the name "unknown".
*)

val is_read_only : t -> bool
(** [NBD.is_read_only t]

    is the NBD export read-only?

    Returns true if the NBD export is read-only; writes and
    write-like operations will fail.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_flush : t -> bool
(** [NBD.can_flush t]

    does the server support the flush command?

    Returns true if the server supports the flush command
    (see nbd_flush(3), nbd_aio_flush(3)). Returns false if
    the server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_fua : t -> bool
(** [NBD.can_fua t]

    does the server support the FUA flag?

    Returns true if the server supports the FUA flag on
    certain commands (see nbd_pwrite(3)).

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val is_rotational : t -> bool
(** [NBD.is_rotational t]

    is the NBD disk rotational (like a disk)?

    Returns true if the disk exposed over NBD is rotational
    (like a traditional floppy or hard disk). Returns false
    if the disk has no penalty for random access (like an
    SSD or RAM disk).

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_trim : t -> bool
(** [NBD.can_trim t]

    does the server support the trim command?

    Returns true if the server supports the trim command
    (see nbd_trim(3), nbd_aio_trim(3)). Returns false if the
    server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_zero : t -> bool
(** [NBD.can_zero t]

    does the server support the zero command?

    Returns true if the server supports the zero command
    (see nbd_zero(3), nbd_aio_zero(3)). Returns false if the
    server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_fast_zero : t -> bool
(** [NBD.can_fast_zero t]

    does the server support the fast zero flag?

    Returns true if the server supports the use of the
    "LIBNBD_CMD_FLAG_FAST_ZERO" flag to the zero command
    (see nbd_zero(3), nbd_aio_zero(3)). Returns false if the
    server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_block_status_payload : t -> bool
(** [NBD.can_block_status_payload t]

    does the server support the block status payload flag?

    Returns true if the server supports the use of the
    "LIBNBD_CMD_FLAG_PAYLOAD_LEN" flag to allow filtering of
    the block status command (see
    nbd_block_status_filter(3)). Returns false if the server
    does not. Note that this will never return true if
    nbd_get_extended_headers_negotiated(3) is false.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_df : t -> bool
(** [NBD.can_df t]

    does the server support the don't fragment flag to pread?

    Returns true if the server supports structured reads
    with an ability to request a non-fragmented read (see
    nbd_pread_structured(3), nbd_aio_pread_structured(3)).
    Returns false if the server either lacks structured
    reads or if it does not support a non-fragmented read
    request.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_multi_conn : t -> bool
(** [NBD.can_multi_conn t]

    does the server support multi-conn?

    Returns true if the server supports multi-conn. Returns
    false if the server does not.

    It is not safe to open multiple handles connecting to
    the same server if you will write to the server and the
    server does not advertise multi-conn support. The safe
    way to check for this is to open one connection, check
    this flag is true, then open further connections as
    required.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_cache : t -> bool
(** [NBD.can_cache t]

    does the server support the cache command?

    Returns true if the server supports the cache command
    (see nbd_cache(3), nbd_aio_cache(3)). Returns false if
    the server does not.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val can_meta_context : t -> string -> bool
(** [NBD.can_meta_context t metacontext]

    does the server support a specific meta context?

    Returns true if the server supports the given meta
    context (see nbd_add_meta_context(3)). Returns false if
    the server does not. It is possible for this command to
    fail if meta contexts were requested but there is a
    missing or failed attempt at NBD_OPT_SET_META_CONTEXT
    during option negotiation.

    If the server supports block status filtering (see
    nbd_can_block_status_payload(3), this function must
    return true for any filter name passed to
    nbd_block_status_filter(3).

    The single parameter is the name of the metadata
    context, for example "LIBNBD_CONTEXT_BASE_ALLOCATION".
    <libnbd.h> includes defined constants for well-known
    namespace contexts beginning with "LIBNBD_CONTEXT_", but
    you are free to pass in other contexts.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val get_protocol : t -> string
(** [NBD.get_protocol t]

    return the NBD protocol variant

    Return the NBD protocol variant in use on the
    connection. At the moment this returns one of the
    strings "oldstyle", "newstyle" or "newstyle-fixed".
    Other strings might be returned in the future. Most
    modern NBD servers use "newstyle-fixed".

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val get_size : t -> int64
(** [NBD.get_size t]

    return the export size

    Returns the size in bytes of the NBD export.

    Note that this call fails with "EOVERFLOW" for an
    unlikely server that advertises a size which cannot fit
    in a 64-bit signed integer.

    nbdinfo(1) *--size* option is a way to access this API
    from shell scripts.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val get_block_size : t -> SIZE.t -> int64
(** [NBD.get_block_size t size_type]

    return a specific server block size constraint

    Returns a specific block size constraint advertised by
    the server. If zero is returned it means the server did
    not advertise a constraint.

    Constraints are hints. Servers differ in their behaviour
    as to whether they enforce constraints or not.

    The "size_type" parameter selects which constraint to
    read. It can be one of:

    "LIBNBD_SIZE_MINIMUM" = 0
        If non-zero, this will be a power of 2 between 1 and
        64k; any client request that is not aligned in
        length or offset to this size is likely to fail with
        "EINVAL". The image size will generally also be a
        multiple of this value (if not, the final few bytes
        are inaccessible while obeying alignment
        constraints).

        If zero (meaning no information was returned by the
        server), it is safest to assume a minimum block size
        of 512, although many servers support a minimum
        block size of 1.

        If the server provides a constraint, then libnbd
        defaults to honoring that constraint client-side
        unless "LIBNBD_STRICT_ALIGN" is cleared in
        nbd_set_strict_mode(3).

    "LIBNBD_SIZE_PREFERRED" = 1
        If non-zero, this is a power of 2 representing the
        preferred size for efficient I/O. Smaller requests
        may incur overhead such as read-modify-write cycles
        that will not be present when using I/O that is a
        multiple of this value. This value may be larger
        than the size of the export.

        If zero (meaning no information was returned by the
        server), using 4k as a preferred block size tends to
        give decent performance.

    "LIBNBD_SIZE_MAXIMUM" = 2
        If non-zero, this represents the maximum length that
        the server is willing to handle during nbd_pread(3)
        or nbd_pwrite(3). Other functions like nbd_zero(3)
        may still be able to use larger sizes. Note that
        this function returns what the server advertised,
        but libnbd itself imposes a maximum of 64M.

        If zero (meaning no information was returned by the
        server), some NBD servers will abruptly disconnect
        if a transaction sends or receives more than 32M of
        data.

    "LIBNBD_SIZE_PAYLOAD" = 3
        This value is not advertised by the server, but
        rather represents the maximum outgoing payload size
        for a given connection that libnbd will enforce
        unless "LIBNBD_STRICT_PAYLOAD" is cleared in
        nbd_set_strict_mode(3). It is always non-zero: never
        smaller than 1M, never larger than 64M, and matches
        "LIBNBD_SIZE_MAXIMUM" when possible.

    Future NBD extensions may result in additional
    "size_type" values. Note that by default, libnbd
    requests all available block sizes, but that a server
    may differ in what sizes it chooses to report if
    nbd_set_request_block_size(3) alters whether the client
    requests sizes.

    This call does not block, because it returns data that
    is saved in the handle from the NBD protocol handshake.
*)

val pread : ?flags:CMD_FLAG.t list -> t -> bytes -> int64 -> unit
(** [NBD.pread t ?flags buf offset]

    read from the NBD server

    Issue a read command to the NBD server for the range
    starting at "offset" and ending at "offset" + "count" -
    1. NBD can only read all or nothing using this call. The
    call returns when the data has been read fully into
    "buf" or there is an error. See also
    nbd_pread_structured(3), if finer visibility is required
    into the server's replies, or if you want to use
    "LIBNBD_CMD_FLAG_DF".

    Note that libnbd currently enforces a maximum read
    buffer of 64MiB, even if the server would permit a
    larger buffer in a single transaction; attempts to
    exceed this will result in an "ERANGE" error. The server
    may enforce a smaller limit, which can be learned with
    nbd_get_block_size(3).

    The "flags" parameter must be 0 for now (it exists for
    future NBD protocol extensions).

    Note that if this command fails, and
    nbd_get_pread_initialize(3) returns true, then libnbd
    sanitized "buf", but it is unspecified whether the
    contents of "buf" will read as zero or as partial
    results from the server. If nbd_get_pread_initialize(3)
    returns false, then libnbd did not sanitize "buf", and
    the contents are undefined on failure.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val pread_structured : ?flags:CMD_FLAG.t list -> t -> bytes -> int64 -> (bytes -> int64 -> int -> int ref -> int) -> unit
(** [NBD.pread_structured t ?flags buf offset chunk]

    read from the NBD server

    Issue a read command to the NBD server for the range
    starting at "offset" and ending at "offset" + "count" -
    1. The server's response may be subdivided into chunks
    which may arrive out of order before reassembly into the
    original buffer; the "chunk" callback is used for
    notification after each chunk arrives, and may perform
    additional sanity checking on the server's reply. The
    callback cannot call "nbd_*" APIs on the same handle
    since it holds the handle lock and will cause a
    deadlock. If the callback returns -1, and no earlier
    error has been detected, then the overall read command
    will fail with any non-zero value stored into the
    callback's "error" parameter (with a default of
    "EPROTO"); but any further chunks will still invoke the
    callback.

    The "chunk" function is called once per chunk of data
    received, with the "user_data" passed to this function.
    The "subbuf" and "count" parameters represent the subset
    of the original buffer which has just been populated by
    results from the server (in C, "subbuf" always points
    within the original "buf"; but this guarantee may not
    extend to other language bindings). The "offset"
    parameter represents the absolute offset at which
    "subbuf" begins within the image (note that this is not
    the relative offset of "subbuf" within the original
    buffer "buf"). Changes to "error" on output are ignored
    unless the callback fails. The input meaning of the
    "error" parameter is controlled by the "status"
    parameter, which is one of

    "LIBNBD_READ_DATA" = 1
        "subbuf" was populated with "count" bytes of data.
        On input, "error" contains the errno value of any
        earlier detected error, or zero.

    "LIBNBD_READ_HOLE" = 2
        "subbuf" represents a hole, and contains "count" NUL
        bytes. On input, "error" contains the errno value of
        any earlier detected error, or zero.

    "LIBNBD_READ_ERROR" = 3
        "count" is 0, so "subbuf" is unusable. On input,
        "error" contains the errno value reported by the
        server as occurring while reading that "offset",
        regardless if any earlier error has been detected.

    Future NBD extensions may permit other values for
    "status", but those will not be returned to a client
    that has not opted in to requesting such extensions. If
    the server is non-compliant, it is possible for the
    "chunk" function to be called more times than you expect
    or with "count" 0 for "LIBNBD_READ_DATA" or
    "LIBNBD_READ_HOLE". It is also possible that the "chunk"
    function is not called at all (in particular,
    "LIBNBD_READ_ERROR" is used only when an error is
    associated with a particular offset, and not when the
    server reports a generic error), but you are guaranteed
    that the callback was called at least once if the
    overall read succeeds. Libnbd does not validate that the
    server obeyed the requirement that a read call must not
    have overlapping chunks and must not succeed without
    enough chunks to cover the entire request.

    Note that libnbd currently enforces a maximum read
    buffer of 64MiB, even if the server would permit a
    larger buffer in a single transaction; attempts to
    exceed this will result in an "ERANGE" error. The server
    may enforce a smaller limit, which can be learned with
    nbd_get_block_size(3).

    The "flags" parameter may be 0 for no flags, or may
    contain "LIBNBD_CMD_FLAG_DF" meaning that the server
    should not reply with more than one fragment (if that is
    supported - some servers cannot do this, see
    nbd_can_df(3)). Libnbd does not validate that the server
    actually obeys the flag.

    Note that if this command fails, and
    nbd_get_pread_initialize(3) returns true, then libnbd
    sanitized "buf", but it is unspecified whether the
    contents of "buf" will read as zero or as partial
    results from the server. If nbd_get_pread_initialize(3)
    returns false, then libnbd did not sanitize "buf", and
    the contents are undefined on failure.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val pwrite : ?flags:CMD_FLAG.t list -> t -> bytes -> int64 -> unit
(** [NBD.pwrite t ?flags buf offset]

    write to the NBD server

    Issue a write command to the NBD server, writing the
    data in "buf" to the range starting at "offset" and
    ending at "offset" + "count" - 1. NBD can only write all
    or nothing using this call. The call returns when the
    command has been acknowledged by the server, or there is
    an error. Note this will generally return an error if
    nbd_is_read_only(3) is true.

    Note that libnbd defaults to enforcing a maximum write
    buffer of the lesser of 64MiB or any maximum payload
    size advertised by the server; attempts to exceed this
    will generally result in a client-side "ERANGE" error,
    rather than a server-side disconnection. The actual
    limit can be learned with nbd_get_block_size(3).

    The "flags" parameter may be 0 for no flags, or may
    contain "LIBNBD_CMD_FLAG_FUA" meaning that the server
    should not return until the data has been committed to
    permanent storage (if that is supported - some servers
    cannot do this, see nbd_can_fua(3)). For convenience,
    unless nbd_set_strict_flags(3) was used to disable
    "LIBNBD_STRICT_AUTO_FLAG", libnbd ignores the presence
    or absence of the flag "LIBNBD_CMD_FLAG_PAYLOAD_LEN" in
    "flags", while correctly using the flag over the wire
    according to whether extended headers were negotiated.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val shutdown : ?flags:SHUTDOWN.t list -> t -> unit
(** [NBD.shutdown t ?flags]

    disconnect from the NBD server

    Issue the disconnect command to the NBD server. This is
    a nice way to tell the server we are going away, but
    from the client's point of view has no advantage over
    abruptly closing the connection (see nbd_close(3)).

    This function works whether or not the handle is ready
    for transmission of commands. If more fine-grained
    control is needed, see nbd_aio_opt_abort(3) and
    nbd_aio_disconnect(3).

    The "flags" argument is a bitmask, including zero or
    more of the following shutdown flags:

    "LIBNBD_SHUTDOWN_ABANDON_PENDING" = 0x10000
        If there are any pending requests which have not yet
        been sent to the server (see nbd_aio_in_flight(3)),
        abandon them without sending them to the server,
        rather than the usual practice of issuing those
        commands before informing the server of the intent
        to disconnect.

    For convenience, the constant "LIBNBD_SHUTDOWN_MASK" is
    available to describe all shutdown flags recognized by
    this build of libnbd. A future version of the library
    may add new flags.
*)

val flush : ?flags:CMD_FLAG.t list -> t -> unit
(** [NBD.flush t ?flags]

    send flush command to the NBD server

    Issue the flush command to the NBD server. The function
    should return when all write commands which have
    completed have been committed to permanent storage on
    the server. Note this will generally return an error if
    nbd_can_flush(3) is false.

    The "flags" parameter must be 0 for now (it exists for
    future NBD protocol extensions).

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val trim : ?flags:CMD_FLAG.t list -> t -> int64 -> int64 -> unit
(** [NBD.trim t ?flags count offset]

    send trim command to the NBD server

    Issue a trim command to the NBD server, which if
    supported by the server causes a hole to be punched in
    the backing store starting at "offset" and ending at
    "offset" + "count" - 1. The call returns when the
    command has been acknowledged by the server, or there is
    an error. Note this will generally return an error if
    nbd_can_trim(3) is false or nbd_is_read_only(3) is true.

    Note that not all servers can support a "count" of 4GiB
    or larger; nbd_get_extended_headers_negotiated(3)
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum trim size, although a future extension
    may add a constraint visible in nbd_get_block_size(3).

    The "flags" parameter may be 0 for no flags, or may
    contain "LIBNBD_CMD_FLAG_FUA" meaning that the server
    should not return until the data has been committed to
    permanent storage (if that is supported - some servers
    cannot do this, see nbd_can_fua(3)).

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val cache : ?flags:CMD_FLAG.t list -> t -> int64 -> int64 -> unit
(** [NBD.cache t ?flags count offset]

    send cache (prefetch) command to the NBD server

    Issue the cache (prefetch) command to the NBD server,
    which if supported by the server causes data to be
    prefetched into faster storage by the server, speeding
    up a subsequent nbd_pread(3) call. The server can also
    silently ignore this command. Note this will generally
    return an error if nbd_can_cache(3) is false.

    Note that not all servers can support a "count" of 4GiB
    or larger; nbd_get_extended_headers_negotiated(3)
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum cache size, although a future extension
    may add a constraint visible in nbd_get_block_size(3).

    The "flags" parameter must be 0 for now (it exists for
    future NBD protocol extensions).

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val zero : ?flags:CMD_FLAG.t list -> t -> int64 -> int64 -> unit
(** [NBD.zero t ?flags count offset]

    send write zeroes command to the NBD server

    Issue a write zeroes command to the NBD server, which if
    supported by the server causes a zeroes to be written
    efficiently starting at "offset" and ending at "offset"
    + "count" - 1. The call returns when the command has
    been acknowledged by the server, or there is an error.
    Note this will generally return an error if
    nbd_can_zero(3) is false or nbd_is_read_only(3) is true.

    Note that not all servers can support a "count" of 4GiB
    or larger; nbd_get_extended_headers_negotiated(3)
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum zero size, although a future extension
    may add a constraint visible in nbd_get_block_size(3).
    Also, some servers may permit a larger zero request only
    when the "LIBNBD_CMD_FLAG_FAST_ZERO" is in use.

    The "flags" parameter may be 0 for no flags, or may
    contain "LIBNBD_CMD_FLAG_FUA" meaning that the server
    should not return until the data has been committed to
    permanent storage (if that is supported - some servers
    cannot do this, see nbd_can_fua(3)),
    "LIBNBD_CMD_FLAG_NO_HOLE" meaning that the server should
    favor writing actual allocated zeroes over punching a
    hole, and/or "LIBNBD_CMD_FLAG_FAST_ZERO" meaning that
    the server must fail quickly if writing zeroes is no
    faster than a normal write (if that is supported - some
    servers cannot do this, see nbd_can_fast_zero(3)).

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val block_status : ?flags:CMD_FLAG.t list -> t -> int64 -> int64 -> (string -> int64 -> int64 (* uint32_t *) array -> int ref -> int) -> unit
(** [NBD.block_status t ?flags count offset extent]

    send block status command, with 32-bit callback

    Issue the block status command to the NBD server. If
    supported by the server, this causes metadata context
    information about blocks beginning from the specified
    offset to be returned. The "count" parameter is a hint:
    the server may choose to return less status, or the
    final block may extend beyond the requested range. If
    multiple contexts are supported, the number of blocks
    and cumulative length of those blocks need not be
    identical between contexts.

    Note that not all servers can support a "count" of 4GiB
    or larger; nbd_get_extended_headers_negotiated(3)
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum block status size, although a future
    extension may add a constraint visible in
    nbd_get_block_size(3). Furthermore, this function is
    inherently limited to 32-bit values. If the server
    replies with a larger extent, the length of that extent
    will be truncated to just below 32 bits and any further
    extents from the server will be ignored. If the server
    replies with a status value larger than 32 bits (only
    possible when extended headers are in use), the callback
    function will be passed an "EOVERFLOW" error. To get the
    full extent information from a server that supports
    64-bit extents, you must use nbd_block_status_64(3).

    Depending on which metadata contexts were enabled before
    connecting (see nbd_add_meta_context(3)) and which are
    supported by the server (see nbd_can_meta_context(3))
    this call returns information about extents by calling
    back to the "extent" function. The callback cannot call
    "nbd_*" APIs on the same handle since it holds the
    handle lock and will cause a deadlock. If the callback
    returns -1, and no earlier error has been detected, then
    the overall block status command will fail with any
    non-zero value stored into the callback's "error"
    parameter (with a default of "EPROTO"); but any further
    contexts will still invoke the callback.

    The "extent" function is called once per type of
    metadata available, with the "user_data" passed to this
    function. The "metacontext" parameter is a string such
    as "base:allocation". The "entries" array is an array of
    pairs of integers with the first entry in each pair
    being the length (in bytes) of the block and the second
    entry being a status/flags field which is specific to
    the metadata context. The number of pairs passed to the
    function is "nr_entries/2". The NBD protocol document in
    the section about "NBD_REPLY_TYPE_BLOCK_STATUS"
    describes the meaning of this array; for contexts known
    to libnbd, <libnbd.h> contains constants beginning with
    "LIBNBD_STATE_" that may help decipher the values. On
    entry to the callback, the "error" parameter contains
    the errno value of any previously detected error, but
    even if an earlier error was detected, the current
    "metacontext" and "entries" are valid.

    It is possible for the extent function to be called more
    times than you expect (if the server is buggy), so
    always check the "metacontext" field to ensure you are
    receiving the data you expect. It is also possible that
    the extent function is not called at all, even for
    metadata contexts that you requested. This indicates
    either that the server doesn't support the context or
    for some other reason cannot return the data.

    The "flags" parameter may be 0 for no flags, or may
    contain "LIBNBD_CMD_FLAG_REQ_ONE" meaning that the
    server should return only one extent per metadata
    context where that extent does not exceed "count" bytes;
    however, libnbd does not validate that the server obeyed
    the flag.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val block_status_64 : ?flags:CMD_FLAG.t list -> t -> int64 -> int64 -> (string -> int64 -> extent array -> int ref -> int) -> unit
(** [NBD.block_status_64 t ?flags count offset extent64]

    send block status command, with 64-bit callback

    Issue the block status command to the NBD server. If
    supported by the server, this causes metadata context
    information about blocks beginning from the specified
    offset to be returned. The "count" parameter is a hint:
    the server may choose to return less status, or the
    final block may extend beyond the requested range. When
    multiple contexts are supported, the number of blocks
    and cumulative length of those blocks need not be
    identical between contexts; this command generally
    returns the status of all negotiated contexts, while
    some servers also support a filtered request (see
    nbd_can_block_status_payload(3),
    nbd_block_status_filter(3)).

    Note that not all servers can support a "count" of 4GiB
    or larger; nbd_get_extended_headers_negotiated(3)
    indicates which servers will parse a request larger than
    32 bits. The NBD protocol does not yet have a way for a
    client to learn if the server will enforce an even
    smaller maximum block status size, although a future
    extension may add a constraint visible in
    nbd_get_block_size(3).

    Depending on which metadata contexts were enabled before
    connecting (see nbd_add_meta_context(3)) and which are
    supported by the server (see nbd_can_meta_context(3))
    this call returns information about extents by calling
    back to the "extent64" function. The callback cannot
    call "nbd_*" APIs on the same handle since it holds the
    handle lock and will cause a deadlock. If the callback
    returns -1, and no earlier error has been detected, then
    the overall block status command will fail with any
    non-zero value stored into the callback's "error"
    parameter (with a default of "EPROTO"); but any further
    contexts will still invoke the callback.

    The "extent64" function is called once per type of
    metadata available, with the "user_data" passed to this
    function. The "metacontext" parameter is a string such
    as "base:allocation". The "entries" array is an array of
    nbd_extent structs, containing length (in bytes) of the
    block and a status/flags field which is specific to the
    metadata context. The number of array entries passed to
    the function is "nr_entries". The NBD protocol document
    in the section about "NBD_REPLY_TYPE_BLOCK_STATUS"
    describes the meaning of this array; for contexts known
    to libnbd, <libnbd.h> contains constants beginning with
    "LIBNBD_STATE_" that may help decipher the values. On
    entry to the callback, the "error" parameter contains
    the errno value of any previously detected error.

    It is possible for the extent function to be called more
    times than you expect (if the server is buggy), so
    always check the "metacontext" field to ensure you are
    receiving the data you expect. It is also possible that
    the extent function is not called at all, even for
    metadata contexts that you requested. This indicates
    either that the server doesn't support the context or
    for some other reason cannot return the data.

    The "flags" parameter may be 0 for no flags, or may
    contain "LIBNBD_CMD_FLAG_REQ_ONE" meaning that the
    server should return only one extent per metadata
    context where that extent does not exceed "count" bytes;
    however, libnbd does not validate that the server obeyed
    the flag.

    By default, libnbd will reject attempts to use this
    function with parameters that are likely to result in
    server failure, such as requesting an unknown command
    flag. The nbd_set_strict_mode(3) function can be used to
    alter which scenarios should await a server reply rather
    than failing fast.
*)

val block_status_filter : ?flags:CMD_FLAG.t list -> t -> int64 