Squashed 'third_party/allwpilib/' changes from e4b91005cf..83f1860047

83f1860047 [wpilib] Add/update documentation to PneumaticBase and subclasses (NFC) (#4881)
9872e676d8 [commands] Make Subsystem destructor virtual (#4892)
25db20e49d [hal] Fix segfault in various HAL functions (#4891)
b0c6724eed [glass] Add hamburger menu icon to titlebars (#4874)
f0fa8205ac Add missing compiler flags and fix warnings (#4889)
42fc4cb6bc [wpiutil] SafeThread: Provide start/stop hooks (#4880)
cc166c98d2 [templates] Add Command-based skeleton template (#4861)
3f51f10ad3 [build] Update to 2023v3 image (#4886)
1562eae74a [ntcore] Refactor meta-topic decoding from glass (#4809)
b632b288a3 Fix usages of std::min and std::max to be windows safe (#4887)
c11bd2720f [wpilibc] Add internal function to reset Shuffleboard instance (#4884)
f1151d375f [ntcore] Add method to get server time offset (#4847)
fe1b62647f [hal,wpilib] Update documentation for getComments (NFC) (#4879)
c49a45abbd [build] Fix examples linking in incorrect jni library (#4873)
bc3d01a721 [build] Add platform check to doxygen plugin (#4862)
bc473240ae Add Jetbrains Fleet folder to .gitignore (#4872)
2121bd5fb8 [wpimath] Remove RKF45 (#4870)
835f8470d6 [build] Fix roborio cross-compiler on arm hosts (#4864)
6cfe5de00d [ntcore] Don't deadlock server on early destroy (#4863)
2ac41f3edc [hal, wpilib] Add RobotController.getComments()  (#4463)
26bdbf3d41 Java optimization and formatting fixes (#4857)
92149efa11 Spelling and grammar cleanups (#4849)
176fddeb4c [commands] Add functions to HID classes to allow use of axes as BooleanEvents/Triggers (#4762)
87a34af367 [templates] Add bindings to command-based template (#4838)
4534e75787 [examples] Remove redundant MotorControl example (#4837)
1cbebaa2f7 [commands] Remove final semicolon from test macro definition (#4859)
6efb9ee405 [commands] Add constructor for SwerveControllerCommand that takes a HolonomicDriveController (#4785)
1e7fcd5637 [cscore] Change run loop functions to not be mac specific (#4854)
1f940e2b60 [apriltag] Add C++ wrappers, rewrite Java/JNI to match (#4842)
a6d127aedf [build] Add missing task dependency in wpilibjExamples (#4852)
b893b3d6d3 [cscore] Add support for USB cameras on macOS (#4846)
1696a490fa [glass] Add support for alternate NT ports (#4848)
40a22d69bc [glass] Add support for alternate NT ports (#4848)
e84dbfede0 [wpilib] GenericHID: Add rumble both option (#4843)
8aa9dbfa90 [examples] Link apriltag package in examples build.gradle (#4845)
eda2fa8a17 [build] Update Spotless (#4840)
d20594db0d Fix typos (#4839)
dd8ecfdd54 [commands] Fix typo in waitUntil docs (NFC) (#4841)
17ceebfff4 [apriltag] Clean up apriltag JNI (#4823)
8b74ab389d [examples] RapidReactCommandBot: Fix array indices (#4833)
1aad3489c2 [sim] Implement PD total current and power (#4830)
2744991771 [wpimath] Fix docs in SwerveModulePosition (#4825)
ffbf6a1fa2 [commands] Disable regularly failing unit test (#4824)
fbabd0ef15 [commands] Enhance Command Sendable implementations (#4822)
7713f68772 [hal] Use atomic rather then mutex for DS Data updates (#4787)
701995d6cc [examples] Update Command-based starter project (#4778)
bf7068ac27 [wpilibc] Add missing PPS implementation for C++ (#4821)
aae0f52ca6 [ntcore] NetworkTable: fix visibility of get/set value (#4820)
ee02fb7ba7 [hal] Add support for Pulse-Per-Second signal (#4819)
518916ba02 [wpilib] Fix DS mode thread event being manual reset accidentally (#4818)
3997c6635b [hal] Update to new image, use new TCP notify callback and new duty cycle API (#4774)
cc8675a4e5 [examples] Add comment on how to view elevator sim (NFC) (#4482)
fb2c170b6e [ntcore] Simplify local startup (#4803)
7ba8a9ee1f [wpimath] ProfiledPIDController: Add to SendableRegistry (#4656)
c569d8e523 [wpilib] Joystick.getMagnitude(): use hypot() function (#4816)
2a5e89fa97 [apriltag] Improve description of pose coordinates (NFC) (#4810)
cc003c6c38 [apriltag] Fix AprilTagFieldLayout JSON name (#4814)
5522916123 [commands] CommandXBoxController bumper documentation fix (NFC) (#4815)
967b30de3a [glass] Fix NT view UpdateClients() bug (#4808)
3270d4fc86 [wpimath] Rewrite pose estimator docs (#4807)
be39678447 [apriltag] Add test to ensure apriltagjni loads (#4805)
61c75deb2a [commands] Test no-op behavior of scheduling a scheduled command (#4806)
a865f48e96 [ntcore] Pass pub/sub options as a unified PubSubOptions struct (#4794)
f66a667321 [commands] Fix incorrect Trigger docs (NFC) (#4792)
f8d4e9866e [ntcore] Clean up ntcore_test.h (#4804)
7e84ea891f [wpimath] Fix ComputerVisionUtil transform example in parameter docs (NFC) (#4800)
da3ec1be10 [wpimath] Change terminology for ArmFeedforward gravity gain (NFC) (#4791)
944dd7265d [wpilibc] Add C++ Notifier error handling, update java notifier error message (#4795)
6948cea67a [wpiutil] Fix MemoryBuffer initialization (#4797)
a31459bce6 [wpiutil] Fix UnescapeCString overflow when inputSize < 2 (#4796)
4a0ad6b48c [wpimath] Rotation2d: Add reference to angleModulus in docs (NFC) (#4786)
e6552d272e [ntcore] Remove table multi-subscriber (#4789)
bde383f763 [hal] Replace const char* with std::string_view in Driver Station sim functions (#4532)
5a52b51443 [hal] Add RobotController.getSerialNumber() (#4783)
69a66ec5ec [wpilib] Fix multiple motor safety issues (#4784)
989c9fb29a [wpimath] Revert Rotation2D change that limits angles (#4781)
0f5b08ec69 [wpigui] Update imgui to 1.89.1+ (#4780)
fba191099c [examples] AddressableLED: Add unit test (#4779)
b390cad095 [wpilibj] Consistently use ErrorMessages.requireNonNullParam (#4776)
b9772214d9 [wpilib] Sendable: Don't call setter for getter changes
342c375a71 [ntcore] Add subscriber option to exclude single publisher
b0e4053087 [ntcore] Use int for options instead of double
f3e666b7bb [cscore] Convert YUYV and UYVY directly to grayscale (#4777)
b300518bd1 [hal] Add CAN Stream API to Java through JNI bindings (#4193)
be27171236 [wpilibj] Shuffleboard: Check for null sendable (#4772)
4bbdbdfb48 [commands] Move GroupedCommands to CommandScheduler (#4728)
f18fd41ac3 [wpimath] Remove broken and obsoleted ComputerVisionUtil functions (#4775)
2d0faecf4f [glass] DataSource: Add spinlock to protect value (#4771)
348bd107fc [hal] Add CANManufacturer for The Thrifty Bot (#4773)
3149dc64b8 [examples] HatchbotInlined: Use Subsystem factories (#4765)
8618dd4160 [glass, wpilib] Replace remaining references to Speed Controller with Motor Controller (#4769)
72e21a1ed1 [apriltag] Use wpilibsuite fork of apriltag (#4764)
eab0d929e6 [commands] CommandGenericHID POV methods: Fix docs (NFC) (#4760)
6789869663 [wpilib] Call set(0) rather than disable for stopMotor (#4763)
c9dea2968d [cscore] Emit warning that USB Camera isn't supported on OSX (#4766)
8f402645f5 [commands] Fix PIDSubsystem setSetpoint behavior (#4759)
f24ad1d715 [build] Upgrade to googletest 1.12.1 (#4752)
ff88756864 [wpimath] Add new DCMotor functions for alternative calculations and reduction calculation (#4749)
f58873db8e [wpimath] Remove extra terms in matrix for pose estimator docs (#4756)
37e969b41a [wpimath] Add constructors to pose estimators with default standard deviations (#4754)
13cdc29382 [ci] Rename comment command from "/wpiformat" to "/format" (#4755)
6e23985ae6 [examples] Add main include directory to test builds (#4751)
66bb0ffb2c [examples] Add unit testing infrastructure (#4646)
74cc86c4c5 [wpimath] Make transform tests use pose/transform equality operators (#4675)
e22d8cc343 [wpimath] Use Odometry for internal state in Pose Estimation (#4668)
68dba92630 [ci] Update mac and windows builds to Java 17 (#4750)
23bfc2d9ab [sim] Remove unmaintained Gazebo support (#4736)
1f1461e254 [wpilib] Add method to enable/disable LiveWindow in test mode (#4678)
eae68fc165 [wpimath] Add tolerance for Rotation3d rotation matrix special orthogonality (#4744)
4c4545fb4b [apriltag] Suppress warning (#4743)
16ffaa754d [docs] Generate docs for apriltag subproject (#4745)
5e74ff26d8 [apriltag, build] Update native utils, add apriltag impl and JNI (#4733)
53875419a1 [hal] Allow overriding stderr printing by HAL_SendError (#4742)
aa6499e920 [ntcore] Fix special topic multi-subscriber handling (#4740)
df70351107 [build] Fix cmake install of thirdparty includes (#4741)
e9bd50ff9b [glass] NT view: clear meta-topic info on disconnect (#4732)
9b319fd56b [ntcore] Add sub option for local vs remote changes (#4731)
18d28ec5e3 [ntcore] Remove duplicate value checking from ClientImpl
bdfb625211 [ntcore] Send duplicate values to network if necessary
21003e34eb [commands] Update Subsystem factories and example to return CommandBase (#4729)
70080457d5 [commands] Refactor ProxyScheduleCommand, SelectCommand into ProxyCommand (#4534)
e82cd5147b [wpilib] Tweak Color HSV formula and use in AddressableLED (#4724)
ec124bb662 [commands] Allow unsetting a subsystem's default command (#4621)
2b2aa8eef7 [examples] Update all examples to use NWU coordinate conventions (#4725)
cb38bacfe8 [commands] Revert to original Trigger implementation (#4673)
15561338d5 [commands] Remove one more default command isFinished check (#4727)
ca35a2e097 Add simgui files to .gitignore (#4726)
20dbae0cee [examples] Renovate command-based examples (#4409)
1a59737f40 [commands] Add convenience factories (#4460)
42b6d4e3f7 Use defaulted comparison operators in C++ (#4723)
135c13958f [wpigui] Add FontAwesome (#4713)
ffbfc61532 [ntcore] Add NetworkTable table-specific listeners (#4640)
8958b2a4da [commands] Add property tests for command compositions (#4715)
e4ac09077c [wpilib] Add link to MotorSafety article (#4720)
f40de0c120 [commands] Add C++ factory templates (#4686)
51fa3e851f [build] cmake: Use FetchContent instead of ExternalProject (#4714)
1da84b2255 [wpigui] Reload fonts to scale rather than preloading (#4712)
e43e2fbc84 [wpiutil] StringExtras: Add UnescapeCString (#4707)
5804d8fa84 [ntcore] Server: Properly handle multiple subscribers (#4717)
169ef5fabf [glass] Update NT view for topicsOnly and sendAll changes (#4718)
148759ef54 [examples] CANPDP: Expand properties shown (#4687)
58ed112b51 [commands] RepeatCommand: restart on following iteration (#4706)
dd1da77d20 [readme] Fix broken CI badge (#4710)
7cda85df20 [build] Check Gradle plugin repo last to fix CI (#4711)
7ed9b13277 [build] Bump version plugin to fix null tag (#4705)
6b4f26225d [apriltag] Fix pluralization of apriltag artifacts (#4671)
b2d2924b72 [cscore] Add Y16 image support (#4702)
34ec89c041 [wpilibc] Shuffleboard SimpleWidget: Return pointer instead of reference (#4703)
e15200068d [ci] Disable HW testbench runs (#4704)
d5200db6cd [wpimath] Rename HolonomicDriveController.calculate params (#4683)
2ee3d86de4 [wpimath] Clarify Rotation3d roll-pitch-yaw direction (#4699)
9f0a8b930f [cscore] Use MFVideoFormat_L8 for Gray on Windows (#4701)
2bca43779e [cscore] Add UYVY image support (#4700)
4307d0ee8b [glass] Plot: allow for more than 11 plots (#4685)
3fe8d355a1 [examples] StateSpaceDifferentialDriveSimulation: Use encoder reversed constants (#4682)
b44034dadc [ntcore] Allow duplicate client IDs on server (#4676)
52d2c53888 [commands] Rename Java factory wait() to waitSeconds() (#4684)
76e918f71e [build] Fix JNI artifacts linking to incorrect libraries (#4680)
0bee875aff [commands] Change C++ CommandPtr to use CommandBase (#4677)
98e922313b [glass] Don't check IsConnected for NT widgets (#4674)
9a36373b8f [apriltag] Switch 2022 apriltag layout length and width values (#4670)
cf8faa9e67 [wpilib] Update values on controllable sendables (#4667)
5ec067c1f8 [ntcore] Implement keep duplicates pub/sub flag (#4666)
e962fd2916 [ntcore] Allow numeric-compatible value sets (#4620)
88bd67e7de [ci] Update clang repositories to jammy (#4665)
902e8686d3 [wpimath] Rework odometry APIs to improve feature parity (#4645)
e2d49181da Update to native utils 2023.8.0 (#4664)
149bac55b1 [cscore] Add Arducam OV9281 exposure quirk (#4663)
88f7a3ccb9 [wpimath] Fix Pose relativeTo documentation (#4661)
8acce443f0 [examples] Fix swerve examples to use getDistance for turning encoder (#4652)
295a1f8f3b [ntcore] Fix WaitForListenerQueue (#4662)
388e7a4265 [ntcore] Provide mechanism to reset internals of NT instance (#4653)
13aceea8dc [apriltag] Fix FieldDimensions argument order (#4659)
c203f3f0a9 [apriltag] Fix documentation for AprilTagFieldLayout (#4657)
f54d495c90 Fix non initialized hal functionality during motor safety init (#4658)
e6392a1570 [cmd] Change factories return type to CommandBase (#4655)
53904e7cf4 [apriltag] Split AprilTag functionality to a separate library (#4578)
2e88a496c2 [wpimath] Add support for swerve joystick normalization (#4516)
ce4c45df13 [wpimath] Rework function signatures for Pose Estimation / Odometry (#4642)
0401597d3b [readme] Add wpinet to MavenArtifacts.md (#4651)
2e5f9e45bb [wpimath] Remove encoder reset comments on Swerve, Mecanum Odometry and Pose Estimation (#4643)
e4b5795fc7 [docs] Disable Doxygen for memory to fix search (#4636)
03d0ea188c [build] cmake: Add missing wpinet to installed config file (#4637)
3082bd236b [build] Move version file to its own source set (#4638)
b7ca860417 [build] Use build cache for sign step (#4635)
64838e6367 [commands] Remove unsafe default command isFinished check (#4411)
1269d2b901 [myRobot] Disable spotbugs (#4565)
14d8506b72 [wpimath] Fix units docs for LinearSystemId::IdentifyDrivetrainSystem() (#4600)
d1d458db2b [wpimath] Constrain Rotation2d range to -pi to pi (#4611)
f656e99245 [readme] Add links to development build documentation (#4481)
6dd937cef7 [commands] Fix Trigger API docs (NFC) (#4599)
49047c85b9 [commands] Report error on C++ CommandPtr use-after-move (#4575)
d07267fed1 [ci] Upgrade containers to Ubuntu 22.04 and remove libclang installation (#4633)
b53ce1d3f0 [build, wpiutil] Switch macos to universal binaries (#4628)
5a320c326b [upstream_util, wpiutil] Refactor python scripts (#4614)
c4e526d315 [glass] Fix NT Mechanism2D (#4626)
d122e4254f [ci] Run spotlessApply after wpiformat in comment command (#4623)
5a1e7ea036 [wpilibj] FieldObject2d: Add null check to close() (#4619)
179f569113 [ntcore] Notify locally on SetDefault (#4617)
b0f6dc199d [wpilibc] ShuffleboardComponent.WithProperties: Update type (#4615)
7836f661cd [wpimath] Add missing open curly brace to units/base.h (#4613)
dbcc1de37f [wpimath] Add DifferentialDriveFeedforward classes which wrap LinearPlantInversionFeedforward (#4598)
93890c528b [wpimath] Add additional angular acceleration units (#4610)
3d8d5936f9 [wpimath] Add macro for disabling units fmt support (#4609)
2b04159dec [wpimath] Update units/base.h license header (#4608)
2764004fad [wpinet] Fix incorrect jni definitions (#4605)
85f1bb8f2b [wpiutil] Reenable jni check task (#4606)
231ae2c353 [glass] Plot: Fix Y-axis not being saved (#4594)
e92b6dd5f9 [wpilib] Fix AprilTagFieldLayout JSON property name typos (#4597)
2a8e0e1cc8 Update all dependencies that use grgit (#4596)
7d06e517e9 [commands] Move SelectCommand factory impl to header (#4581)
323524fed6 [wpimath] Remove deprecated units/units.h header (#4572)
d426873ed1 [commands] Add missing PS4 triangle methods (#4576)
5be5869b2f [apriltags] Use map as internal data model (#4577)
b1b4c1e9e7 [wpimath] Fix Pose3d transformBy rotation type (#4545)
a4054d702f [commands] Allow composing two triggers directly (#4580)
0190301e09 [wpilibc] Explicitly mark EventLoop as non-copyable/non-movable (#4579)
9d1ce6a6d9 [ntcore] Catch file open error when saving preferences (#4571)
5005e2ca04 [ntcore] Change Java event mask to EnumSet (#4564)
fa44a07938 [upstream-utils][mpack] Add upstream util for mpack (#4500)
4ba16db645 [ntcore] Various fixes and cleanups (#4544)
837415abfd [hal] Fix joysticks either crashing or returning 0 (#4570)
2c20fd0d09 [wpilib] SingleJointedArmSim: Check angle equals limit on wouldHit (#4567)
64a7136e08 [wpimath] SwerveDrivePoseEstimator: Restore comment about encoder reset (#4569)
b2b473b24a [wpilib] Add AprilTag and AprilTagFieldLayout (#4421)
7aab8fa93a [build] Update to Native Utils 2023.6.0 (#4563)
12c2851856 [commands] WrapperCommand: inherit from CommandBase (#4561)
0da169dd84 [wpimath] Remove template argument from ElevatorFeedforward (#4554)
2416827c25 [wpimath] Fix docs for pose estimator local measurement models (#4558)
1177a3522e [wpilib] Fix Xbox/PS4 POV sim for port number constructors (#4548)
102344e27a [commands] HID classes: Add missing methods, tweak return types (#4557)
1831ef3e19 [wpilib] Fix Shuffleboard SuppliedValueWidget (#4559)
a9606ce870 [wpilib] Fix Xbox/PS4 POV sim (#4546)
6c80d5eab3 [wpimath] Remove unused SymbolExports.h include from units/base.h (#4541)
b114006543 [ntcore] Unify listeners (#4536)
32fbfb7da6 [build] cmake: Install ntcore generated include files (#4540)
02465920fb [build] Update native utils to 2023.4.0 (#4539)
3a5a376465 [wpimath] Increase constexpr support in geometry data types (#4231)
1c3c86e9f1 [ntcore] Cache GetEntry(name) values (#4531)
dcda09f90a [command] Rename trigger methods (#4210)
66157397c1 [wpilib] Make drive classes follow NWU axes convention (#4079)
9e22ffbebf [ntcore] Fix null deref in NT3 client (#4530)
648ab6115c [wpigui,dlt,glass,ov] Support arm in GUI tools (#4527)
8bc3b04f5b [wpimath] Make ComputerVisionUtil use 3D geometry classes (#4528)
cfb84a6083 [wpilibc] Don't hang waiting for NT server to start (#4524)
02c47726e1 [wpimath] Remove unused odometry instance from DifferentialDrivePoseEstimator test (#4522)
b2a0093294 [ci] Revert upgrade of github-pages-deploy-action (#4521)
2a98d6b5d7 [wpimath] PIDController: Add getters for position & velocity tolerances (#4458)
9f36301dc8 [ci] Write wpiformat patch to job summary (#4519)
901fc555f4 [wpimath] Position Delta Odometry for Mecanum (#4514)
4170ec6107 [wpimath] Position Delta Odometry for Swerve (#4493)
fe400f68c5 [docs] Add wpinet to docs build (#4517)
794669b346 [ntcore] Revamp listeners (#4511)
dcfa85a5d5 [ci] Build sanitizers with clang-14 (#4518)
15ad855f1d [ntcore] Add UnitTopic<T> (C++ only) (#4497)
11244a49d9 [wpilib] Add IsConnected function to all gyros (#4465)
1d2e8eb153 [build] Update myRobot deployment (#4515)
ad53fb19b4 [hal] Use new HMB api for addressable LED (#4479)
ba850bac3b [hal] Add more shutdown checks and motor safety shutdown (#4510)
023a5989f8 [ntcore] Fix typo in NetworkServer client connect message (#4512)
c970011ccc [docs] Add Doxygen aliases used by Foonathan memory (#4509)
07a43c3d9a [readme] Document clang-format version and /wpiformat (#4503)
a05b212b04 [ci] Revert changes to wpiformat task from #4501 (#4508)
09faf31b67 [commands] Replace Command HID inheritance with delegation (#4470)
9e1f9c1133 [commands] Add command factories (#4476)
f19d2b9b84 [ci] Add NUMBER environment variable to comment command commit script (#4507)
a28f93863c [ci] Push comment command commit directly to PR (#4506)
c9f61669b8 [ci] Fix comment command commit push (#4505)
dcce5ad3b3 [ci] Update github-script API usage (#4504)
6836e5923d [wpilibc] Restore get duty cycle scale factor (#4502)
335188c652 [dlt] Add deselect/select all buttons to download view (#4499)
60a29dcb99 [glass] Field2D: Add "hidden" option for objects (#4498)
b55d5b3034 [ci] Update deprecated github actions (#4501)
10ed4b3969 [ntcore] Various NT4 fixes (#4474)
4a401b89d7 [hal, wpilib] New DS thread model and implementation (#3787)
c195b4fc46 [wpimath] Clean up PoseEstimator nominal dt docs (#4496)
8f2e34c6a3 [build] Remove wpilib prefix from CMake flat install (#4492)
150d692df7 [wpimath] Remove unused private PoseEstimator function (#4495)
3e5bfff1b5 [wpimath] FromFieldRelativeSpeeds: Add ChassisSpeeds overload (#4494)
9c7e66a27d [commands] C++: Add CommandPtr overload for SetDefaultCommand (#4488)
0ca274866b [build] Fix CMake system library opt-ins (#4487)
dc037f8d41 [commands] Remove EndlessCommand (#4483)
16cdc741cf [wpimath] Add Pose3d(Pose2d) constructor (#4485)
9d5055176d [build] cmake: Allow disabling ntcore build (#4486)
d1e66e1296 [build] Compile all java code with inline string concatenation (#4490)
1fc098e696 Enable log macros to work with no args (#4475)
878cc8defb [wpilib] LiveWindow: Add enableAllTelemetry() (#4480)
8153911160 [build] Fix MSVC runtime archiver to grab default runtime (#4478)
fbdc810887 Upgrade to C++20 (#4239)
396143004c [ntcore] Add ntcoreffi binary (#4471)
1f45732700 [build] Update to 2023.2.4 native-utils and new dependencies (#4473)
574cb41c18 [ntcore] Various fixes (#4469)
d9d6c425e7 [build] Force Java 11 source compatibility (#4472)
58b6484dbe Switch away from NI interrupt manager to custom implementation (#3705)
ca43fe2798 [wpimath] Use Units conversions in ComputerVisionUtil docs (NFC) (#4464)
87a64ccedc [hal] Convert DutyCycle Raw output to be a high time measurement (#4466)
89a3d00297 [commands] Add FinallyDo and HandleInterrupt decorators (#4412)
1497665f96 [commands] Add C++ versions of Java-only decorators (#4457)
27b173374e [wpimath] Add minLinearAccel parameter to DifferentialDriveAccelerationLimiter (#4422)
2a13dba8ac [wpilib] TrajectoryUtil: Fix ambiguous documentation (NFC) (#4461)
77301b126c [ntcore] NetworkTables 4 (#3217)
90cfa00115 [build] cmake: Fix libssh include directory order (#4459)
5cf961edb9 [commands] Refactor lambda-based commands to inherit FunctionalCommand (#4451)
b2276e47de [wpimath] Enable continuous angle input for HolonomicDriveController (#4453)
893b46139a [fieldImages] Add utilities to simplify loading of fields (#4456)
60e29627c0 [commands] C++ unique_ptr migration (#4319)
3b81cf6c35 [wpilib] Improve Color.toString (#4450)
5c067d30a0 [wpinet] WebSocket: Add SendFrames() (#4445)
ceaf493811 [wpiutil] MakeJByteArray: Use span<uint8> instead of string_view (#4446)
10e04e2b13 [examples] FrisbeeBot: Fix reference capture (#4449)
726f67c64b [build] Add exeSplitSetup (#4444)
c7b7624c1c [wpiutil] Add MessagePack utility functions (#4448)
d600529ec0 [wpinet] uv::Async: Add UnsafeSend() (#4447)
b53b3526a2 [wpimath] Add CoordinateSystem conversion for Transform3d (#4443)
38bb23eb18 [wpimath] Add scalar multiply and divide operators to all geometry classes (#4438)
3937ff8221 [wpilib] Remove deprecated Controller class (#4440)
abbfe244b5 [wpilib] Improve Color FromHSV (#4439)
4ddb8aa0dd [sim] Provide function that resets all simulation data (#4016)
a791470de7 Clean up Java warning suppressions (#4433)
17f504f548 [hal,wpilib] Fix SPI Mode Setting (#4434)
773198537c [wpiutil] Add wpi::scope_exit (#4432)
5ac658c8f0 [wpiutil] Logger: Conditionalize around WPI_LOG (#4431)
8767e4a941 [wpiutil] DataLog: Fix SetMetadata output (#4430)
8c4af073f4 [wpiutil] Synchronization: shutdown race protection (#4429)
c79f38584a [build] Fix Java integration tests (#4428)
36c08dd97c [build] Fix cmake install of fmtlib (#4426)
69b7b3dd7d [ci] Remove the Windows cmake job (#4425)
738c75fed8 [readme] Fix formatting/linting link (#4423)
4eb1d03fb3 [wpimath] Document C++ LinearFilter exception (#4417)
ba4ec6c967 [build] Fix clang-tidy false positive on Linux (#4406)
97836f0e55 [commands] Fix ProfiledPIDSubsystem setGoal behavior (#4414)
fdfb85f695 [wpimath] Remove Java LQR constructor that takes a controller gain matrix (#4419)
ab1baf4832 [wpimath] Add rotation matrix constructor to Rotation3d (#4413)
9730032866 [wpimath] Document LQR and KalmanFilter exceptions (#4418)
5b656eecf6 [wpimath] Fix HTML5 entity (#4420)
9ae38eaa7c [commands] Add owning overload to ProxyScheduleCommand (#4405)
cb33bd71df [commands] deprecate withInterrupt decorator (#4407)
d9b4e7b8bf [commands] Revert "Change grouping decorator impl to flatten nested group structures (#3335)" (#4402)
0389bf5214 [hal] REVPH: Improve handling of disconnected CAN Bus (#4169)
4267fa08d1 [wpilibc] ADIS IMUs: Fix memory leak (#4170)
65c8fbd452 [wpilib] MotorControllerGroup: Override setVoltage (#4403)
f36162fddc [wpimath] Improve Discretization internal docs (#4400)
5149f7d894 [wpimath] Add two-vector Rotation3d constructor (#4398)
20b5bed1cb [wpimath] Clean up Java Quaternion class (#4399)
f18dd1905d [build] Include all thirdparty sources in distribution (#4397)
aa9d7f1cdc [wpiutil] Import foonathan memory (#4306)
2742662254 [ci] Remove a couple of obsolete clang-tidy checks (#4396)
a5df391166 [hal, wpilib] Fix up DIO pulse API (#4387)
59e6706b75 [glass] Turn on docking by default
8461bb1e03 [glass] Add support for saving docking info
b873e208b4 [wpigui] Add support for imgui config flags
873e72df8c [build] Update imgui to 1.88 docking branch
c8bd6fc5b4 [ci] Fix comment-command (take 2) (#4395)
fed68b83b4 [ci] Fix comment-command action not running runners (#4393)
0ef8a4e1df [wpimath] Support formatting more Eigen types (#4391)
c393b3b367 [build] Update to native utils 2023.1.0 and Gradle 7.5.1 (#4392)
b5a17f762c [wpimath] Add direction to slew rate limiter (#4377)
fafc81ed1a [wpiutil] Upgrade to fmt 9.1.0 (#4389)
cc56bdc787 [wpiutil] SafeThread: Add Synchronization object variant (#4382)
4254438d8d [commands] Mark command group lifecycle methods as final (#4385)
97c15af238 [wpimath] LinearSystemId: Fix docs, move C++ impls out of header (#4388)
d22ff8a158 [wpiutil] Add JNI access to C++ stderr (#4381)
fdb5a2791f [wpiutil] jni_util: Add Mac-friendly MakeJLongArray/JArrayRef (#4383)
c3a93fb995 [commands] Revamp Interruptible (#4192)
f2a8d38d2a [commands] Rename Command.repeat to repeatedly (#4379)
9e24c6eac0 [wpiutil] Logger: paren-protect instance usage in macro (#4384)
fe4d12ce22 [wpimath] Add LTV controller derivations and make enums private (#4380)
eb08486039 [build] Fix MacOS binary rpath generation (#4376)
ccf83c634a [build] Use native-utils platform names instead of raw strings (#4375)
3fd69749e7 [docs] Upgrade to doxygen 1.9.4 (#4370)
594df5fc08 [wpinet] uv/util.h: Pull in ws2_32.lib on Windows for ntohs (#4371)
539070820d [ci] Enable asan for wpinet and wpiutil (#4369)
564a56d99b [wpinet] Fix memory leak in WorkerThreadTest (#4368)
5adf50d93c [upstream_utils] Refactor upstream_utils scripts (#4367)
d80e8039d7 [wpiutil] Suppress fmtlib clang-tidy warning in C++20 consteval contexts (#4364)
0e6d67b23b [upstream_utils] Remove yapf format disable comment (#4366)
be5270697a [build] Suppress enum-enum deprecation warning in OpenCV (#4365)
8d28851263 Add Rosetta install command to build requirements (#4363)
3d2115c93e [wpinet] include-what-you-use in MulticastTest (#4360)
91002ae3cc [wpimath] Upgrade to Drake 1.6.0 (#4361)
148c18e658 [wpinet] Upgrade to libuv 1.44.2 (#4362)
a2a5c926b6 Fix clang-tidy warnings (#4359)
ea6b1d8449 [wpiutil] Remove unused ManagedStatic class (#4358)
ac9be78e27 Use stricter C++ type conversions (#4357)
151dabb2af [wpiutil] Upgrade to fmt 9.0.0 (#4337)
340465c929 [ci] Upgrade to clang-format and clang-tidy 14 (NFC) (#4347)
d45bcddd15 [examples] Add comments to StateSpaceDifferentialDrive (#4341)
0e0786331a Update LLVM libraries to 14.0.6 (#4350)
c5db23f296 [wpimath] Add Eigen sparse matrix and iterative solver support (#4349)
44abc8dfa6 [upstream_utils] Remove git version from upstream patches (#4351)
3fdb2f767d [wpimath] Add comments with Ramsete equations (#4348)
0485f05da9 [wpilibjExamples] Upgrade jacoco to match allwpilib (#4346)
0a5eb65231 [wpinet] Handle empty txt block for mdns announcer (#4072)
19ffebaf3e [wpilib] Add reference to I2C Lockup to API Docs (NFC) (#4340)
ce1a90d639 [hal] Replace SerialHelper "goto done" with continue (#4342)
d25af48797 [ci] Make upstream_utils CI fail on untracked files (#4339)
ebb836dacb [examples] Fix negations in event loop examples (#4334)
d83e202f00 [upstream_utils] Update paths in update_fmt.py (#4338)
3ccf806064 [wpimath] Remove redundant LinearFilter.finiteDifference() argument (#4335)
6f1e01f8bd [wpimath] Document example of online filtering for LinearFilter.finiteDifference() (#4336)
1023c34b1c [readme] Update location of ni-libraries (#4333)
faa29d596c [wpilib] Improve Notifier docs (NFC) (#4326)
add00a96ed [wpimath] Improve DifferentialDriveAccelerationLimiter docs (NFC) (#4323)
82fac41244 [wpimath] Better document trackwidth parameters (NFC) (#4324)
5eb44e22a9 Format Python scripts with black (NFC) (#4325)
2e09fa7325 [build] Fix mpack cmake (#4322)
fe3c24b1ee [command] Add ignoringDisable decorator (#4305)
aa221597bc [build] Add M1 builds, change arm name, update to 2023 deps (#4315)
579a8ee229 [ci] Use one worker for Windows release Gradle build (#4318)
5105c5eab6 [wpilibj] Change "final" to "exit" in the IterativeRobotBase JavaDoc (NFC) (#4317)
787fe6e7a5 [wpiutil] Separate third party libraries (#4190)
6671f8d099 [wpigui] Update portable file dialogs (#4316)
9ac9b69aa2 [command] Reorder Scheduler operations (#4261)
e61028cb18 [build] halsim_gui: Add wpinet dependency (#4313)
661d23eaf5 [glass] Add precision setting for NetworkTable view (#4311)
666040e3e5 [hal] Throw exceptions for invalid sizes in I2C and SPI JNI (#4312)
aebc272449 [build] Upgrade to spotbugs Gradle plugin 5.0.8 (#4310)
fd884581e4 [wpilib] Add BooleanEvent/Trigger factories on HID classes (#4247)
9b1bf5c7f1 [wpimath] Move Drake and Eigen to thirdparty folders (#4307)
c9e620a920 [wpilibc] Change EventLoop data structure to vector (#4304)
41d40dd62f [wpinet] Fix libuv unused variable warning on Mac (#4299)
30f5b68264 [wpinet] Fix JNI loading error (#4295)
f7b3f4b90e [examples] Getting Started: Change Joystick to XboxController (#4194)
a99c11c14c [wpimath] Replace UKF implementation with square root form (#4168)
45b7fc445b [wpilib] Add EventLoop (#4104)
16a4888c52 [wpilib] Default off LiveWindow telemetry (#4301)
17752f1337 [ci] Split debug and release Windows builds (#4277)
abb45a68db [commands] Remove custom test wrappers (#4296)
1280a54ef3 [upstream_utils]: Make work with Python 3.8 (#4298)
f2d243fa68 [build] Change defaults for Java lints (#4300)
a4787130f4 Update using development build to work with 2023 gradlerio (#4294)
af7985e46c [wpiutil] Use invoke_result_t instead of result_of in future.h (#4293)
e9d1b5c2d0 [hal] Remove deprecated SimDevice functions (#4209)
45b598d236 [wpilibj] Add toString() methods to Color and Color8Bit (#4286)
fc37265da5 [wpimath] Add angle measurement convention to ArmFeedforward docs (NFC) (#4285)
a4ec13eb0e [wpilibjexamples] Remove unnecessary voltage desaturation
2fa52007af [wpilibc] Use GetBatteryVoltage() in MotorController::SetVoltage
d9f9cd1140 [wpimath] Reset prev_time on pose estimator reset (#4283)
8b6df88783 [wpilibj] Tachometer.getFrequency(): Fix bug (#4281)
345cff08c0 [wpiutil] Make wpi::array constexpr (#4278)
57428112ac [wpimath] Upgrade to Drake v1.3.0 (#4279)
a18d4ff154 [build] Fix tools not being copied when built with -Ponly* (#4276)
d1cd07b9f3 [wpigui] Add OpenURL (#4273)
e67f8e917a [glass] Use glfwSetKeyCallback for Enter key remap (#4275)
be2fedfe50 [wpimath] Add stdexcept include for std::invalid_argument (IWYU) (#4274)
7ad2be172e [build] Update native-utils to 2023.0.1 (#4272)
abc605c9c9 [ci] Update workflows to 20.04 base image (#4271)
3e94805220 [wpiutil] Reduce llvm collections patches (#4268)
db2e1d170e [upstream_utils] Document how to update thirdparty libraries (#4253)
96ebdcaf16 [wpimath] Remove unused Eigen AutoDiff module (#4267)
553b2a3b12 [upstream_utils] Fix stackwalker (#4265)
3e13ef42eb [wpilibc] Add missing std::array #include (include-what-you-use) (#4266)
d651a1fcec Fix internal deprecation warnings (#4257)
b193b318c1 [commands] Add unless() decorator (#4244)
ef3714223b [commands] Remove docs reference to obsolete interrupted() method (NFC) (#4262)
3d8dbbbac3 [readme] Add quickstart (#4225)
013efdde25 [wpinet] Wrap a number of newer libuv features (#4260)
816aa4e465 [wpilib] Add Pneumatics sim classes (#4033)
046c2c8972 [wpilibc] Rename SpeedControllerGroupTest.cpp (#4258)
d80e9cdf64 [upstream_utils] Use shallow clones for thirdparty repos (#4255)
7576136b4a [upstream_utils] Make update_llvm.py executable (#4254)
c3b223ce60 [wpiutil] Vendor llvm and update to 13.0.0 (#4224)
5aa67f56e6 [wpimath] Clean up math comments (#4252)
fff4d1f44e [wpimath] Extend Eigen warning suppression to GCC 12 (#4251)
0d9956273c [wpimath] Add CoordinateSystem.convert() translation and rotation overloads (#4227)
3fada4e0b4 [wpinet] Update to libuv 1.44.1 (#4232)
65b23ac45e [wpilibc] Fix return value of DriverStation::GetJoystickAxisType() (#4230)
4ac34c0141 [upstream_utils] Cleanup update_libuv.py (#4249)
8bd614bb1e [upstream_utils] Use "git am" instead of "git apply" for patches (#4248)
4253d6d5f0 [upstream_utils] Apply "git am" patches individually (#4250)
6a4752dcdc Fix GCC 12.1 warning false positives (#4246)
5876b40f08 [wpimath] Memoize CoordinateSystem and CoordinateAxis statics (#4241)
5983434a70 [cameraserver] Replace IterativeRobot in comment sample code with TimedRobot (#4238)
a3d44a1e69 [wpimath] Add Translation2d.getAngle() (#4217)
d364bbd5a7 [upstream_utils] Give vendor update scripts execute permissions (#4226)
f341e1b2be [wpimath] Document standard coordinate systems better (NFC) (#4228)
9af389b200 [wpinet] AddrToName: Initialize name (#4229)
2ae4adf2d7 [ci] Add wpiformat command to PRs (#4223)
178b2a1e88 Contributing.md: Correct version of clang-format used (#4222)
18db343cdc [wpiutil, wpinet] Vendor libuv, stack walker (#4219)
f0c821282a [build] Use artifactory mirror (#4220)
d673ead481 [wpinet] Move network portions of wpiutil into new wpinet library (#4077)
b33715db15 [wpimath] Add CoordinateSystem class (#4214)
99424ad562 [sim] Allow creating a PWMSim object from a PWMMotorController (#4039)
dc6f641fd2 [wpimath] PIDController: Reset position and velocity error when reset() is called. (#4064)
f20a20f3f1 [wpimath] Add 3D geometry classes (#4175)
708a4bc3bc [wpimath] Conserve previously calculated swerve module angles when updating states for stationary ChassisSpeeds (#4208)
ef7ed21a9d [wpimath] Improve accuracy of ComputerVisionUtil.calculateDistanceToTarget() (#4215)
b1abf455c1 [wpimath] LTVUnicycleController: Use LUT, provide default hyperparameters (#4213)
d5456cf278 [wpimath] LTVDifferentialDriveController: Remove unused variable (#4212)
99343d40ba [command] Remove old command-based framework (#4211)
ee03a7ad3b Remove most 2022 deprecations (#4205)
ce1a7d698a [wpimath] Refactor WheelVoltages inner class to a separate file (#4203)
87bf70fa8e [wpimath] Add LTV controllers (#4094)
ebd2a303bf [wpimath] Remove deprecated MakeMatrix() function (#4202)
e28776d361 [wpimath] LinearSystemLoop: Add extern templates for common cases
dac1429aa9 [wpimath] LQR: Use extern template instead of Impl class
e767605e94 [wpimath] Add typedefs for common types
97c493241f [wpimath] UnscentedKalmanFilter: Move implementation out-of-line
8ea90d8bc9 [wpimath] ExtendedKalmanFilter: Move implementation out-of-line
ae7b1851ec [wpimath] KalmanFilter: Use extern template instead of Impl class
e3d62c22d3 [wpimath] Add extern templates for common cases
7200c4951d [wpiutil] SymbolExports: Add WPILIB_IMPORTS for dllimport
84056c9347 [wpiutil] SymbolExports: Add EXPORT_TEMPLATE_DECLARE/DEFINE
09cf6eeecb [wpimath] ApplyDeadband: add a scale param (#3865)
03230fc842 [build,ci] Enable artifactory build cache (#4200)
63cf3aaa3f [examples] Don't square ArcadeDrive inputs in auto (#4201)
18ff694f02 [wpimath] Add Rotation2d.fromRadians factory (#4178)
4f79ceedd9 [wpilibc] Add missing #include (#4198)
f7ca72fb41 [command] Rename PerpetualCommand to EndlessCommand (#4177)
a06b3f0307 [hal] Correct documentation on updateNotifierAlarm (#4156)
d926dd1610 [wpimath] Fix pose estimator performance (#4111)
51bc893bc5 [wpiutil] CircularBuffer: Change Java package-private methods to public (#4181)
fbe761f7f6 [build] Increase Gradle JVM heap size (#4172)
5ebe911933 [wpimath] Add DifferentialDriveAccelerationLimiter (#4091)
3919250da2 [wpilibj] Remove finalizers (#4158)
b3aee28388 [commands] Allow BooleanSupplier for Trigger operations (#4103)
9d20ab3024 [wpilib] Allow disabling ElevatorSim gravity (#4145)
aaa69f6717 [ci] Remove 32-bit Windows builds (#4078)
355a11a414 Update Java linters and fix new PMD errors (#4157)
ffc69d406c [examples] Reduce suggested acceleration in Ramsete example (#4171)
922d50079a [wpimath] Units: fix comment in degreesToRotations (NFC) (#4159)
dd163b62ae [wpimath] Rotation2d: Add factory method that uses rotations (#4166)
bd80e220b9 [ci] Upgrade CMake actions (#4161)
aef4b16d4c [wpimath] Remove unnecessary NOLINT in LinearPlantInversionFeedforward (NFC) (#4155)
975171609e [wpilib] Compressor: Rename enabled to isEnabled (#4147)
5bf46a9093 [wpimath] Add ComputerVisionUtil (#4124)
f27a1f9bfb [commands] Fix JoystickButton.getAsBoolean (#4131)
1b26e2d5da [commands] Add RepeatCommand (#4009)
88222daa3d [hal] Fix misspelling in AnalogInput/Output docs (NFC) (#4153)
81c5b41ce1 [wpilibj] Document MechanismLigament2d angle unit (NFC) (#4142)
9650e6733e [wpiutil] DataLog: Document finish and thread safety (NFC) (#4140)
c8905ec29a [wpimath] Remove ImplicitModelFollower dt argument (#4119)
b4620f01f9 [wpimath] Fix Rotation2d interpolation in Java (#4125)
2e462a19d3 [wpimath] Constexprify units unary operators (#4138)
069f932e59 [build] Fix gl3w cmake build (#4139)
126e3de91a [wpilibc] Remove unused SetPriority() call from Ultrasonic (#4123)
ba0dccaae4 [wpimath] Fix reference to Rotation2d.fromRadians() (#4118)
e1b6e5f212 [wpilib] Improve MotorSafety documentation (NFC) (#4120)
8d79dc8738 [wpimath] Add ImplicitModelFollower (#4056)
78108c2aba [wpimath] Fix PIDController having incorrect error after calling SetSetpoint() (#4070)
cdafc723fb [examples] Remove unused LinearPlantInversionFeedforward includes (#4069)
0d70884dce [wpimath] Add InterpolatedTreeMap (#4073)
765efa325e [wpimath] Remove redundant column index from vectors (#4116)
89ffcbbe41 [wpimath] Update TrapezoidProfile class name in comment (NFC) (#4107)
95ae23b0e7 [wpimath] Improve EKF numerical stability (#4093)
d5cb6fed67 [wpimath] Support zero cost entries in MakeCostMatrix() (#4100)
d0fef18378 [wpimath] Remove redundant `this.` from ExtendedKalmanFilter.java (#4115)
d640c0f41f [wpimath] Fix pose estimator local measurement standard deviation docs (NFC) (#4113)
a2fa5e3ff7 [wpilibc] BatterySim: Provide non-initializer list versions of Calculate (#4076)
a3eea9958e [hal] Add link to FRC CAN Spec (NFC) (#4086)
db27331d7b [wpilib] Update DifferentialDrive docs (NFC) (#4085)
fdfb31f164 [dlt] Export boolean[] values (#4082)
f93c3331b3 [wpigui] disable changing directory when initializing on MacOS (#4092)
ab7ac4fbb9 [build] Fix various warnings in cmake builds (#4081)
bc39a1a293 [wpilibc] Fix moved pneumatics objects not destructing properly (#4068)
2668130e70 [wpimath] Remove SwerveDrivePoseEstimator encoder reset warning (#4066)
d27ed3722b [ci] Set actions workflow concurrency (#4060)
dae18308c9 [wpimath] Minor fixes to Rotation2d docs (NFC) (#4055)
d66555e42f [datalogtool] Add datalogtool
9f52d8a3b1 [wpilib] DriverStation: Add DataLog support for modes and joystick data
757ea91932 [wpilib] Add DataLogManager
02a804f1c5 [ntcore] Add DataLog support
9b500df0d9 [wpiutil] Add high speed data logging
5a89575b3a [wpiutil] Import customized LLVM MemoryBuffer
b8c4d7527b [wpiutil] Add MappedFileRegion
ac5d46cfa7 [wpilibc] Fix ProfiledPID SetTolerance default velocity value (#4054)
bc9e96e86f [wpilib] Absolute Encoder API and behavior fixes (#4052)
f88c435dd0 [hal] Add mechanism to cancel all periodic callbacks (#4049)

Change-Id: I49aa5b08abbefc7a045e99e19d48ce2cd8fc4d1b
git-subtree-dir: third_party/allwpilib
git-subtree-split: 83f1860047c86aa3330fcb41caf3b2047e074804
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/wpiutil/src/main/native/cpp/Base64.cpp b/wpiutil/src/main/native/cpp/Base64.cpp
index 8f1f810..bc1d3ba 100644
--- a/wpiutil/src/main/native/cpp/Base64.cpp
+++ b/wpiutil/src/main/native/cpp/Base64.cpp
@@ -138,8 +138,8 @@
   return Base64Decode(os, encoded);
 }
 
-span<uint8_t> Base64Decode(std::string_view encoded, size_t* num_read,
-                           SmallVectorImpl<uint8_t>& buf) {
+std::span<uint8_t> Base64Decode(std::string_view encoded, size_t* num_read,
+                                SmallVectorImpl<uint8_t>& buf) {
   buf.clear();
   raw_usvector_ostream os(buf);
   *num_read = Base64Decode(os, encoded);
@@ -193,19 +193,19 @@
   return os.str();
 }
 
-void Base64Encode(raw_ostream& os, span<const uint8_t> plain) {
+void Base64Encode(raw_ostream& os, std::span<const uint8_t> plain) {
   Base64Encode(os, std::string_view{reinterpret_cast<const char*>(plain.data()),
                                     plain.size()});
 }
 
-void Base64Encode(span<const uint8_t> plain, std::string* encoded) {
+void Base64Encode(std::span<const uint8_t> plain, std::string* encoded) {
   encoded->resize(0);
   raw_string_ostream os(*encoded);
   Base64Encode(os, plain);
   os.flush();
 }
 
-std::string_view Base64Encode(span<const uint8_t> plain,
+std::string_view Base64Encode(std::span<const uint8_t> plain,
                               SmallVectorImpl<char>& buf) {
   buf.clear();
   raw_svector_ostream os(buf);
diff --git a/wpiutil/src/main/native/cpp/DataLog.cpp b/wpiutil/src/main/native/cpp/DataLog.cpp
new file mode 100644
index 0000000..7009628
--- /dev/null
+++ b/wpiutil/src/main/native/cpp/DataLog.cpp
@@ -0,0 +1,821 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "wpi/DataLog.h"
+
+#include "wpi/Synchronization.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>  // NOLINT(build/include_order)
+
+#endif
+
+#include <atomic>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <random>
+#include <vector>
+
+#include "fmt/format.h"
+#include "wpi/Endian.h"
+#include "wpi/Logger.h"
+#include "wpi/MathExtras.h"
+#include "wpi/fs.h"
+#include "wpi/timestamp.h"
+
+using namespace wpi::log;
+
+static constexpr size_t kBlockSize = 16 * 1024;
+static constexpr size_t kRecordMaxHeaderSize = 17;
+
+template <typename T>
+static unsigned int WriteVarInt(uint8_t* buf, T val) {
+  unsigned int len = 0;
+  do {
+    *buf++ = static_cast<unsigned int>(val) & 0xff;
+    ++len;
+    val >>= 8;
+  } while (val != 0);
+  return len;
+}
+
+// min size: 4, max size: 17
+static unsigned int WriteRecordHeader(uint8_t* buf, uint32_t entry,
+                                      uint64_t timestamp,
+                                      uint32_t payloadSize) {
+  uint8_t* origbuf = buf++;
+
+  unsigned int entryLen = WriteVarInt(buf, entry);
+  buf += entryLen;
+  unsigned int payloadLen = WriteVarInt(buf, payloadSize);
+  buf += payloadLen;
+  unsigned int timestampLen =
+      WriteVarInt(buf, timestamp == 0 ? wpi::Now() : timestamp);
+  buf += timestampLen;
+  *origbuf =
+      ((timestampLen - 1) << 4) | ((payloadLen - 1) << 2) | (entryLen - 1);
+  return buf - origbuf;
+}
+
+class DataLog::Buffer {
+ public:
+  explicit Buffer(size_t alloc = kBlockSize)
+      : m_buf{new uint8_t[alloc]}, m_maxLen{alloc} {}
+  ~Buffer() { delete[] m_buf; }
+
+  Buffer(const Buffer&) = delete;
+  Buffer& operator=(const Buffer&) = delete;
+
+  Buffer(Buffer&& oth)
+      : m_buf{oth.m_buf}, m_len{oth.m_len}, m_maxLen{oth.m_maxLen} {
+    oth.m_buf = nullptr;
+    oth.m_len = 0;
+    oth.m_maxLen = 0;
+  }
+
+  Buffer& operator=(Buffer&& oth) {
+    if (m_buf) {
+      delete[] m_buf;
+    }
+    m_buf = oth.m_buf;
+    m_len = oth.m_len;
+    m_maxLen = oth.m_maxLen;
+    oth.m_buf = nullptr;
+    oth.m_len = 0;
+    oth.m_maxLen = 0;
+    return *this;
+  }
+
+  uint8_t* Reserve(size_t size) {
+    assert(size <= GetRemaining());
+    uint8_t* rv = m_buf + m_len;
+    m_len += size;
+    return rv;
+  }
+
+  void Unreserve(size_t size) { m_len -= size; }
+
+  void Clear() { m_len = 0; }
+
+  size_t GetRemaining() const { return m_maxLen - m_len; }
+
+  std::span<uint8_t> GetData() { return {m_buf, m_len}; }
+  std::span<const uint8_t> GetData() const { return {m_buf, m_len}; }
+
+ private:
+  uint8_t* m_buf;
+  size_t m_len = 0;
+  size_t m_maxLen;
+};
+
+static void DefaultLog(unsigned int level, const char* file, unsigned int line,
+                       const char* msg) {
+  if (level > wpi::WPI_LOG_INFO) {
+    fmt::print(stderr, "DataLog: {}\n", msg);
+  } else if (level == wpi::WPI_LOG_INFO) {
+    fmt::print("DataLog: {}\n", msg);
+  }
+}
+
+static wpi::Logger defaultMessageLog{DefaultLog};
+
+DataLog::DataLog(std::string_view dir, std::string_view filename, double period,
+                 std::string_view extraHeader)
+    : DataLog{defaultMessageLog, dir, filename, period, extraHeader} {}
+
+DataLog::DataLog(wpi::Logger& msglog, std::string_view dir,
+                 std::string_view filename, double period,
+                 std::string_view extraHeader)
+    : m_msglog{msglog},
+      m_period{period},
+      m_extraHeader{extraHeader},
+      m_newFilename{filename},
+      m_thread{[this, dir = std::string{dir}] { WriterThreadMain(dir); }} {}
+
+DataLog::DataLog(std::function<void(std::span<const uint8_t> data)> write,
+                 double period, std::string_view extraHeader)
+    : DataLog{defaultMessageLog, std::move(write), period, extraHeader} {}
+
+DataLog::DataLog(wpi::Logger& msglog,
+                 std::function<void(std::span<const uint8_t> data)> write,
+                 double period, std::string_view extraHeader)
+    : m_msglog{msglog},
+      m_period{period},
+      m_extraHeader{extraHeader},
+      m_thread{[this, write = std::move(write)] {
+        WriterThreadMain(std::move(write));
+      }} {}
+
+DataLog::~DataLog() {
+  {
+    std::scoped_lock lock{m_mutex};
+    m_active = false;
+    m_doFlush = true;
+  }
+  m_cond.notify_all();
+  m_thread.join();
+}
+
+void DataLog::SetFilename(std::string_view filename) {
+  {
+    std::scoped_lock lock{m_mutex};
+    m_newFilename = filename;
+  }
+  m_cond.notify_all();
+}
+
+void DataLog::Flush() {
+  {
+    std::scoped_lock lock{m_mutex};
+    m_doFlush = true;
+  }
+  m_cond.notify_all();
+}
+
+void DataLog::Pause() {
+  std::scoped_lock lock{m_mutex};
+  m_paused = true;
+}
+
+void DataLog::Resume() {
+  std::scoped_lock lock{m_mutex};
+  m_paused = false;
+}
+
+static void WriteToFile(fs::file_t f, std::span<const uint8_t> data,
+                        std::string_view filename, wpi::Logger& msglog) {
+  do {
+#ifdef _WIN32
+    DWORD ret;
+    if (!WriteFile(f, data.data(), data.size(), &ret, nullptr)) {
+      WPI_ERROR(msglog, "Error writing to log file '{}': {}", filename,
+                GetLastError());
+      break;
+    }
+#else
+    ssize_t ret = ::write(f, data.data(), data.size());
+    if (ret < 0) {
+      // If it's a recoverable error, swallow it and retry the write
+      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+        continue;
+      }
+
+      // Otherwise it's a non-recoverable error; quit trying
+      WPI_ERROR(msglog, "Error writing to log file '{}': {}", filename,
+                std::strerror(errno));
+      break;
+    }
+#endif
+
+    // The write may have written some or all of the data
+    data = data.subspan(ret);
+  } while (data.size() > 0);
+}
+
+static std::string MakeRandomFilename() {
+  // build random filename
+  static std::random_device dev;
+  static std::mt19937 rng(dev());
+  std::uniform_int_distribution<int> dist(0, 15);
+  const char* v = "0123456789abcdef";
+  std::string filename = "wpilog_";
+  for (int i = 0; i < 16; i++) {
+    filename += v[dist(rng)];
+  }
+  filename += ".wpilog";
+  return filename;
+}
+
+void DataLog::WriterThreadMain(std::string_view dir) {
+  std::chrono::duration<double> periodTime{m_period};
+
+  std::error_code ec;
+  fs::path dirPath{dir};
+  std::string filename;
+
+  {
+    std::scoped_lock lock{m_mutex};
+    filename = std::move(m_newFilename);
+    m_newFilename.clear();
+  }
+
+  if (filename.empty()) {
+    filename = MakeRandomFilename();
+  }
+
+  // try preferred filename, or randomize it a few times, before giving up
+  fs::file_t f;
+  for (int i = 0; i < 5; ++i) {
+    // open file for append
+#ifdef _WIN32
+    // WIN32 doesn't allow combination of CreateNew and Append
+    f = fs::OpenFileForWrite(dirPath / filename, ec, fs::CD_CreateNew,
+                             fs::OF_None);
+#else
+    f = fs::OpenFileForWrite(dirPath / filename, ec, fs::CD_CreateNew,
+                             fs::OF_Append);
+#endif
+    if (ec) {
+      WPI_ERROR(m_msglog, "Could not open log file '{}': {}",
+                (dirPath / filename).string(), ec.message());
+      // try again with random filename
+      filename = MakeRandomFilename();
+    } else {
+      break;
+    }
+  }
+
+  if (f == fs::kInvalidFile) {
+    WPI_ERROR(m_msglog, "Could not open log file, no log being saved");
+  } else {
+    WPI_INFO(m_msglog, "Logging to '{}'", (dirPath / filename).string());
+  }
+
+  // write header (version 1.0)
+  if (f != fs::kInvalidFile) {
+    const uint8_t header[] = {'W', 'P', 'I', 'L', 'O', 'G', 0, 1};
+    WriteToFile(f, header, filename, m_msglog);
+    uint8_t extraLen[4];
+    support::endian::write32le(extraLen, m_extraHeader.size());
+    WriteToFile(f, extraLen, filename, m_msglog);
+    if (m_extraHeader.size() > 0) {
+      WriteToFile(f,
+                  {reinterpret_cast<const uint8_t*>(m_extraHeader.data()),
+                   m_extraHeader.size()},
+                  filename, m_msglog);
+    }
+  }
+
+  std::vector<Buffer> toWrite;
+
+  std::unique_lock lock{m_mutex};
+  while (m_active) {
+    bool doFlush = false;
+    auto timeoutTime = std::chrono::steady_clock::now() + periodTime;
+    if (m_cond.wait_until(lock, timeoutTime) == std::cv_status::timeout) {
+      doFlush = true;
+    }
+
+    if (!m_newFilename.empty()) {
+      auto newFilename = std::move(m_newFilename);
+      m_newFilename.clear();
+      lock.unlock();
+      // rename
+      if (filename != newFilename) {
+        fs::rename(dirPath / filename, dirPath / newFilename, ec);
+      }
+      if (ec) {
+        WPI_ERROR(m_msglog, "Could not rename log file from '{}' to '{}': {}",
+                  filename, newFilename, ec.message());
+      } else {
+        WPI_INFO(m_msglog, "Renamed log file from '{}' to '{}'", filename,
+                 newFilename);
+      }
+      filename = std::move(newFilename);
+      lock.lock();
+    }
+
+    if (doFlush || m_doFlush) {
+      // flush to file
+      m_doFlush = false;
+      if (m_outgoing.empty()) {
+        continue;
+      }
+      // swap outgoing with empty vector
+      toWrite.swap(m_outgoing);
+
+      if (f != fs::kInvalidFile) {
+        lock.unlock();
+        // write buffers to file
+        for (auto&& buf : toWrite) {
+          WriteToFile(f, buf.GetData(), filename, m_msglog);
+        }
+
+        // sync to storage
+#if defined(__linux__)
+        ::fdatasync(f);
+#elif defined(__APPLE__)
+        ::fsync(f);
+#endif
+        lock.lock();
+      }
+
+      // release buffers back to free list
+      for (auto&& buf : toWrite) {
+        buf.Clear();
+        m_free.emplace_back(std::move(buf));
+      }
+      toWrite.resize(0);
+    }
+  }
+
+  if (f != fs::kInvalidFile) {
+    fs::CloseFile(f);
+  }
+}
+
+void DataLog::WriterThreadMain(
+    std::function<void(std::span<const uint8_t> data)> write) {
+  std::chrono::duration<double> periodTime{m_period};
+
+  // write header (version 1.0)
+  {
+    const uint8_t header[] = {'W', 'P', 'I', 'L', 'O', 'G', 0, 1};
+    write(header);
+    uint8_t extraLen[4];
+    support::endian::write32le(extraLen, m_extraHeader.size());
+    write(extraLen);
+    if (m_extraHeader.size() > 0) {
+      write({reinterpret_cast<const uint8_t*>(m_extraHeader.data()),
+             m_extraHeader.size()});
+    }
+  }
+
+  std::vector<Buffer> toWrite;
+
+  std::unique_lock lock{m_mutex};
+  while (m_active) {
+    bool doFlush = false;
+    auto timeoutTime = std::chrono::steady_clock::now() + periodTime;
+    if (m_cond.wait_until(lock, timeoutTime) == std::cv_status::timeout) {
+      doFlush = true;
+    }
+
+    if (doFlush || m_doFlush) {
+      // flush to file
+      m_doFlush = false;
+      if (m_outgoing.empty()) {
+        continue;
+      }
+      // swap outgoing with empty vector
+      toWrite.swap(m_outgoing);
+
+      lock.unlock();
+      // write buffers
+      for (auto&& buf : toWrite) {
+        if (!buf.GetData().empty()) {
+          write(buf.GetData());
+        }
+      }
+      lock.lock();
+
+      // release buffers back to free list
+      for (auto&& buf : toWrite) {
+        buf.Clear();
+        m_free.emplace_back(std::move(buf));
+      }
+      toWrite.resize(0);
+    }
+  }
+
+  write({});  // indicate EOF
+}
+
+// Control records use the following format:
+// 1-byte type
+// 4-byte entry
+// rest of data (depending on type)
+
+int DataLog::Start(std::string_view name, std::string_view type,
+                   std::string_view metadata, int64_t timestamp) {
+  std::scoped_lock lock{m_mutex};
+  auto& entryInfo = m_entries[name];
+  if (entryInfo.id == 0) {
+    entryInfo.id = ++m_lastId;
+  }
+  auto& savedCount = m_entryCounts[entryInfo.id];
+  ++savedCount;
+  if (savedCount > 1) {
+    if (entryInfo.type != type) {
+      WPI_ERROR(m_msglog,
+                "type mismatch for '{}': was '{}', requested '{}'; ignoring",
+                name, entryInfo.type, type);
+      return 0;
+    }
+    return entryInfo.id;
+  }
+  entryInfo.type = type;
+  size_t strsize = name.size() + type.size() + metadata.size();
+  uint8_t* buf = StartRecord(0, timestamp, 5 + 12 + strsize, 5);
+  *buf++ = impl::kControlStart;
+  wpi::support::endian::write32le(buf, entryInfo.id);
+  AppendStringImpl(name);
+  AppendStringImpl(type);
+  AppendStringImpl(metadata);
+
+  return entryInfo.id;
+}
+
+void DataLog::Finish(int entry, int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  auto& savedCount = m_entryCounts[entry];
+  if (savedCount == 0) {
+    return;
+  }
+  --savedCount;
+  if (savedCount != 0) {
+    return;
+  }
+  m_entryCounts.erase(entry);
+  uint8_t* buf = StartRecord(0, timestamp, 5, 5);
+  *buf++ = impl::kControlFinish;
+  wpi::support::endian::write32le(buf, entry);
+}
+
+void DataLog::SetMetadata(int entry, std::string_view metadata,
+                          int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  uint8_t* buf = StartRecord(0, timestamp, 5 + 4 + metadata.size(), 5);
+  *buf++ = impl::kControlSetMetadata;
+  wpi::support::endian::write32le(buf, entry);
+  AppendStringImpl(metadata);
+}
+
+uint8_t* DataLog::Reserve(size_t size) {
+  assert(size <= kBlockSize);
+  if (m_outgoing.empty() || size > m_outgoing.back().GetRemaining()) {
+    if (m_free.empty()) {
+      m_outgoing.emplace_back();
+    } else {
+      m_outgoing.emplace_back(std::move(m_free.back()));
+      m_free.pop_back();
+    }
+  }
+  return m_outgoing.back().Reserve(size);
+}
+
+uint8_t* DataLog::StartRecord(uint32_t entry, uint64_t timestamp,
+                              uint32_t payloadSize, size_t reserveSize) {
+  uint8_t* buf = Reserve(kRecordMaxHeaderSize + reserveSize);
+  auto headerLen = WriteRecordHeader(buf, entry, timestamp, payloadSize);
+  m_outgoing.back().Unreserve(kRecordMaxHeaderSize - headerLen);
+  buf += headerLen;
+  return buf;
+}
+
+void DataLog::AppendImpl(std::span<const uint8_t> data) {
+  while (data.size() > kBlockSize) {
+    uint8_t* buf = Reserve(kBlockSize);
+    std::memcpy(buf, data.data(), kBlockSize);
+    data = data.subspan(kBlockSize);
+  }
+  uint8_t* buf = Reserve(data.size());
+  std::memcpy(buf, data.data(), data.size());
+}
+
+void DataLog::AppendStringImpl(std::string_view str) {
+  uint8_t* buf = Reserve(4);
+  wpi::support::endian::write32le(buf, str.size());
+  AppendImpl({reinterpret_cast<const uint8_t*>(str.data()), str.size()});
+}
+
+void DataLog::AppendRaw(int entry, std::span<const uint8_t> data,
+                        int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  StartRecord(entry, timestamp, data.size(), 0);
+  AppendImpl(data);
+}
+
+void DataLog::AppendRaw2(int entry,
+                         std::span<const std::span<const uint8_t>> data,
+                         int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  size_t size = 0;
+  for (auto&& chunk : data) {
+    size += chunk.size();
+  }
+  StartRecord(entry, timestamp, size, 0);
+  for (auto chunk : data) {
+    AppendImpl(chunk);
+  }
+}
+
+void DataLog::AppendBoolean(int entry, bool value, int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  uint8_t* buf = StartRecord(entry, timestamp, 1, 1);
+  buf[0] = value ? 1 : 0;
+}
+
+void DataLog::AppendInteger(int entry, int64_t value, int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  uint8_t* buf = StartRecord(entry, timestamp, 8, 8);
+  wpi::support::endian::write64le(buf, value);
+}
+
+void DataLog::AppendFloat(int entry, float value, int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  uint8_t* buf = StartRecord(entry, timestamp, 4, 4);
+  if constexpr (wpi::support::endian::system_endianness() ==
+                wpi::support::little) {
+    std::memcpy(buf, &value, 4);
+  } else {
+    wpi::support::endian::write32le(buf, wpi::FloatToBits(value));
+  }
+}
+
+void DataLog::AppendDouble(int entry, double value, int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  uint8_t* buf = StartRecord(entry, timestamp, 8, 8);
+  if constexpr (wpi::support::endian::system_endianness() ==
+                wpi::support::little) {
+    std::memcpy(buf, &value, 8);
+  } else {
+    wpi::support::endian::write64le(buf, wpi::DoubleToBits(value));
+  }
+}
+
+void DataLog::AppendString(int entry, std::string_view value,
+                           int64_t timestamp) {
+  AppendRaw(entry,
+            {reinterpret_cast<const uint8_t*>(value.data()), value.size()},
+            timestamp);
+}
+
+void DataLog::AppendBooleanArray(int entry, std::span<const bool> arr,
+                                 int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  StartRecord(entry, timestamp, arr.size(), 0);
+  uint8_t* buf;
+  while (arr.size() > kBlockSize) {
+    buf = Reserve(kBlockSize);
+    for (auto val : arr.subspan(0, kBlockSize)) {
+      *buf++ = val ? 1 : 0;
+    }
+    arr = arr.subspan(kBlockSize);
+  }
+  buf = Reserve(arr.size());
+  for (auto val : arr) {
+    *buf++ = val ? 1 : 0;
+  }
+}
+
+void DataLog::AppendBooleanArray(int entry, std::span<const int> arr,
+                                 int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  StartRecord(entry, timestamp, arr.size(), 0);
+  uint8_t* buf;
+  while (arr.size() > kBlockSize) {
+    buf = Reserve(kBlockSize);
+    for (auto val : arr.subspan(0, kBlockSize)) {
+      *buf++ = val & 1;
+    }
+    arr = arr.subspan(kBlockSize);
+  }
+  buf = Reserve(arr.size());
+  for (auto val : arr) {
+    *buf++ = val & 1;
+  }
+}
+
+void DataLog::AppendBooleanArray(int entry, std::span<const uint8_t> arr,
+                                 int64_t timestamp) {
+  AppendRaw(entry, arr, timestamp);
+}
+
+void DataLog::AppendIntegerArray(int entry, std::span<const int64_t> arr,
+                                 int64_t timestamp) {
+  if constexpr (wpi::support::endian::system_endianness() ==
+                wpi::support::little) {
+    AppendRaw(entry,
+              {reinterpret_cast<const uint8_t*>(arr.data()), arr.size() * 8},
+              timestamp);
+  } else {
+    if (entry <= 0) {
+      return;
+    }
+    std::scoped_lock lock{m_mutex};
+    if (m_paused) {
+      return;
+    }
+    StartRecord(entry, timestamp, arr.size() * 8, 0);
+    uint8_t* buf;
+    while ((arr.size() * 8) > kBlockSize) {
+      buf = Reserve(kBlockSize);
+      for (auto val : arr.subspan(0, kBlockSize / 8)) {
+        wpi::support::endian::write64le(buf, val);
+        buf += 8;
+      }
+      arr = arr.subspan(kBlockSize / 8);
+    }
+    buf = Reserve(arr.size() * 8);
+    for (auto val : arr) {
+      wpi::support::endian::write64le(buf, val);
+      buf += 8;
+    }
+  }
+}
+
+void DataLog::AppendFloatArray(int entry, std::span<const float> arr,
+                               int64_t timestamp) {
+  if constexpr (wpi::support::endian::system_endianness() ==
+                wpi::support::little) {
+    AppendRaw(entry,
+              {reinterpret_cast<const uint8_t*>(arr.data()), arr.size() * 4},
+              timestamp);
+  } else {
+    if (entry <= 0) {
+      return;
+    }
+    std::scoped_lock lock{m_mutex};
+    if (m_paused) {
+      return;
+    }
+    StartRecord(entry, timestamp, arr.size() * 4, 0);
+    uint8_t* buf;
+    while ((arr.size() * 4) > kBlockSize) {
+      buf = Reserve(kBlockSize);
+      for (auto val : arr.subspan(0, kBlockSize / 4)) {
+        wpi::support::endian::write32le(buf, wpi::FloatToBits(val));
+        buf += 4;
+      }
+      arr = arr.subspan(kBlockSize / 4);
+    }
+    buf = Reserve(arr.size() * 4);
+    for (auto val : arr) {
+      wpi::support::endian::write32le(buf, wpi::FloatToBits(val));
+      buf += 4;
+    }
+  }
+}
+
+void DataLog::AppendDoubleArray(int entry, std::span<const double> arr,
+                                int64_t timestamp) {
+  if constexpr (wpi::support::endian::system_endianness() ==
+                wpi::support::little) {
+    AppendRaw(entry,
+              {reinterpret_cast<const uint8_t*>(arr.data()), arr.size() * 8},
+              timestamp);
+  } else {
+    if (entry <= 0) {
+      return;
+    }
+    std::scoped_lock lock{m_mutex};
+    if (m_paused) {
+      return;
+    }
+    StartRecord(entry, timestamp, arr.size() * 8, 0);
+    uint8_t* buf;
+    while ((arr.size() * 8) > kBlockSize) {
+      buf = Reserve(kBlockSize);
+      for (auto val : arr.subspan(0, kBlockSize / 8)) {
+        wpi::support::endian::write64le(buf, wpi::DoubleToBits(val));
+        buf += 8;
+      }
+      arr = arr.subspan(kBlockSize / 8);
+    }
+    buf = Reserve(arr.size() * 8);
+    for (auto val : arr) {
+      wpi::support::endian::write64le(buf, wpi::DoubleToBits(val));
+      buf += 8;
+    }
+  }
+}
+
+void DataLog::AppendStringArray(int entry, std::span<const std::string> arr,
+                                int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  // storage: 4-byte array length, each string prefixed by 4-byte length
+  // calculate total size
+  size_t size = 4;
+  for (auto&& str : arr) {
+    size += 4 + str.size();
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  uint8_t* buf = StartRecord(entry, timestamp, size, 4);
+  wpi::support::endian::write32le(buf, arr.size());
+  for (auto&& str : arr) {
+    AppendStringImpl(str);
+  }
+}
+
+void DataLog::AppendStringArray(int entry,
+                                std::span<const std::string_view> arr,
+                                int64_t timestamp) {
+  if (entry <= 0) {
+    return;
+  }
+  // storage: 4-byte array length, each string prefixed by 4-byte length
+  // calculate total size
+  size_t size = 4;
+  for (auto&& str : arr) {
+    size += 4 + str.size();
+  }
+  std::scoped_lock lock{m_mutex};
+  if (m_paused) {
+    return;
+  }
+  uint8_t* buf = StartRecord(entry, timestamp, size, 4);
+  wpi::support::endian::write32le(buf, arr.size());
+  for (auto sv : arr) {
+    AppendStringImpl(sv);
+  }
+}
diff --git a/wpiutil/src/main/native/cpp/DataLogReader.cpp b/wpiutil/src/main/native/cpp/DataLogReader.cpp
new file mode 100644
index 0000000..96f6689
--- /dev/null
+++ b/wpiutil/src/main/native/cpp/DataLogReader.cpp
@@ -0,0 +1,307 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "wpi/DataLogReader.h"
+
+#include "wpi/DataLog.h"
+#include "wpi/Endian.h"
+#include "wpi/MathExtras.h"
+
+using namespace wpi::log;
+
+static bool ReadString(std::span<const uint8_t>* buf, std::string_view* str) {
+  if (buf->size() < 4) {
+    *str = {};
+    return false;
+  }
+  uint32_t len = wpi::support::endian::read32le(buf->data());
+  if (len > (buf->size() - 4)) {
+    *str = {};
+    return false;
+  }
+  *str = {reinterpret_cast<const char*>(buf->data() + 4), len};
+  *buf = buf->subspan(len + 4);
+  return true;
+}
+
+bool DataLogRecord::IsStart() const {
+  return m_entry == 0 && m_data.size() >= 17 &&
+         m_data[0] == impl::kControlStart;
+}
+
+bool DataLogRecord::IsFinish() const {
+  return m_entry == 0 && m_data.size() == 5 &&
+         m_data[0] == impl::kControlFinish;
+}
+
+bool DataLogRecord::IsSetMetadata() const {
+  return m_entry == 0 && m_data.size() >= 9 &&
+         m_data[0] == impl::kControlSetMetadata;
+}
+
+bool DataLogRecord::GetStartData(StartRecordData* out) const {
+  if (!IsStart()) {
+    return false;
+  }
+  out->entry = wpi::support::endian::read32le(&m_data[1]);
+  auto buf = m_data.subspan(5);
+  if (!ReadString(&buf, &out->name)) {
+    return false;
+  }
+  if (!ReadString(&buf, &out->type)) {
+    return false;
+  }
+  if (!ReadString(&buf, &out->metadata)) {
+    return false;
+  }
+  return true;
+}
+
+bool DataLogRecord::GetFinishEntry(int* out) const {
+  if (!IsFinish()) {
+    return false;
+  }
+  *out = wpi::support::endian::read32le(&m_data[1]);
+  return true;
+}
+
+bool DataLogRecord::GetSetMetadataData(MetadataRecordData* out) const {
+  if (!IsSetMetadata()) {
+    return false;
+  }
+  out->entry = wpi::support::endian::read32le(&m_data[1]);
+  auto buf = m_data.subspan(5);
+  return ReadString(&buf, &out->metadata);
+}
+
+bool DataLogRecord::GetBoolean(bool* value) const {
+  if (m_data.size() != 1) {
+    return false;
+  }
+  *value = m_data[0] != 0;
+  return true;
+}
+
+bool DataLogRecord::GetInteger(int64_t* value) const {
+  if (m_data.size() != 8) {
+    return false;
+  }
+  *value = wpi::support::endian::read64le(m_data.data());
+  return true;
+}
+
+bool DataLogRecord::GetFloat(float* value) const {
+  if (m_data.size() != 4) {
+    return false;
+  }
+  *value = wpi::BitsToFloat(wpi::support::endian::read32le(m_data.data()));
+  return true;
+}
+
+bool DataLogRecord::GetDouble(double* value) const {
+  if (m_data.size() != 8) {
+    return false;
+  }
+  *value = wpi::BitsToDouble(wpi::support::endian::read64le(m_data.data()));
+  return true;
+}
+
+bool DataLogRecord::GetString(std::string_view* value) const {
+  *value = {reinterpret_cast<const char*>(m_data.data()), m_data.size()};
+  return true;
+}
+
+bool DataLogRecord::GetBooleanArray(std::vector<int>* arr) const {
+  arr->clear();
+  arr->reserve(m_data.size());
+  for (auto v : m_data) {
+    arr->push_back(v);
+  }
+  return true;
+}
+
+bool DataLogRecord::GetIntegerArray(std::vector<int64_t>* arr) const {
+  arr->clear();
+  if ((m_data.size() % 8) != 0) {
+    return false;
+  }
+  arr->reserve(m_data.size() / 8);
+  for (size_t pos = 0; pos < m_data.size(); pos += 8) {
+    arr->push_back(wpi::support::endian::read64le(&m_data[pos]));
+  }
+  return true;
+}
+
+bool DataLogRecord::GetFloatArray(std::vector<float>* arr) const {
+  arr->clear();
+  if ((m_data.size() % 4) != 0) {
+    return false;
+  }
+  arr->reserve(m_data.size() / 4);
+  for (size_t pos = 0; pos < m_data.size(); pos += 4) {
+    arr->push_back(
+        wpi::BitsToFloat(wpi::support::endian::read32le(&m_data[pos])));
+  }
+  return true;
+}
+
+bool DataLogRecord::GetDoubleArray(std::vector<double>* arr) const {
+  arr->clear();
+  if ((m_data.size() % 8) != 0) {
+    return false;
+  }
+  arr->reserve(m_data.size() / 8);
+  for (size_t pos = 0; pos < m_data.size(); pos += 8) {
+    arr->push_back(
+        wpi::BitsToDouble(wpi::support::endian::read64le(&m_data[pos])));
+  }
+  return true;
+}
+
+bool DataLogRecord::GetStringArray(std::vector<std::string_view>* arr) const {
+  arr->clear();
+  if (m_data.size() < 4) {
+    return false;
+  }
+  uint32_t size = wpi::support::endian::read32le(m_data.data());
+  // sanity check size
+  if (size > ((m_data.size() - 4) / 4)) {
+    return false;
+  }
+  auto buf = m_data.subspan(4);
+  arr->reserve(size);
+  for (uint32_t i = 0; i < size; ++i) {
+    std::string_view str;
+    if (!ReadString(&buf, &str)) {
+      arr->clear();
+      return false;
+    }
+    arr->push_back(str);
+  }
+  // any left over?  treat as corrupt
+  if (!buf.empty()) {
+    arr->clear();
+    return false;
+  }
+  return true;
+}
+
+DataLogReader::DataLogReader(std::unique_ptr<MemoryBuffer> buffer)
+    : m_buf{std::move(buffer)} {}
+
+bool DataLogReader::IsValid() const {
+  if (!m_buf) {
+    return false;
+  }
+  auto buf = m_buf->GetBuffer();
+  return buf.size() >= 12 &&
+         std::string_view{reinterpret_cast<const char*>(buf.data()), 6} ==
+             "WPILOG" &&
+         wpi::support::endian::read16le(&buf[6]) >= 0x0100;
+}
+
+uint16_t DataLogReader::GetVersion() const {
+  if (!m_buf) {
+    return 0;
+  }
+  auto buf = m_buf->GetBuffer();
+  if (buf.size() < 12) {
+    return 0;
+  }
+  return wpi::support::endian::read16le(&buf[6]);
+}
+
+std::string_view DataLogReader::GetExtraHeader() const {
+  if (!m_buf) {
+    return {};
+  }
+  auto buf = m_buf->GetBuffer();
+  if (buf.size() < 8) {
+    return {};
+  }
+  std::string_view rv;
+  buf = buf.subspan(8);
+  ReadString(&buf, &rv);
+  return rv;
+}
+
+DataLogReader::iterator DataLogReader::begin() const {
+  if (!m_buf) {
+    return end();
+  }
+  auto buf = m_buf->GetBuffer();
+  if (buf.size() < 12) {
+    return end();
+  }
+  uint32_t size = wpi::support::endian::read32le(&buf[8]);
+  if (buf.size() < (12 + size)) {
+    return end();
+  }
+  return DataLogIterator{this, 12 + size};
+}
+
+static uint64_t ReadVarInt(std::span<const uint8_t> buf) {
+  uint64_t val = 0;
+  int shift = 0;
+  for (auto v : buf) {
+    val |= static_cast<uint64_t>(v) << shift;
+    shift += 8;
+  }
+  return val;
+}
+
+bool DataLogReader::GetRecord(size_t* pos, DataLogRecord* out) const {
+  if (!m_buf) {
+    return false;
+  }
+  auto buf = m_buf->GetBuffer();
+  if (*pos >= buf.size()) {
+    return false;
+  }
+  buf = buf.subspan(*pos);
+  if (buf.size() < 4) {  // minimum header length
+    return false;
+  }
+  unsigned int entryLen = (buf[0] & 0x3) + 1;
+  unsigned int sizeLen = ((buf[0] >> 2) & 0x3) + 1;
+  unsigned int timestampLen = ((buf[0] >> 4) & 0x7) + 1;
+  unsigned int headerLen = 1 + entryLen + sizeLen + timestampLen;
+  if (buf.size() < headerLen) {
+    return false;
+  }
+  int entry = ReadVarInt(buf.subspan(1, entryLen));
+  uint32_t size = ReadVarInt(buf.subspan(1 + entryLen, sizeLen));
+  if (size > (buf.size() - headerLen)) {
+    return false;
+  }
+  int64_t timestamp =
+      ReadVarInt(buf.subspan(1 + entryLen + sizeLen, timestampLen));
+  *out = DataLogRecord{entry, timestamp, buf.subspan(headerLen, size)};
+  *pos += headerLen + size;
+  return true;
+}
+
+bool DataLogReader::GetNextRecord(size_t* pos) const {
+  if (!m_buf) {
+    return false;
+  }
+  auto buf = m_buf->GetBuffer();
+  if (buf.size() < (*pos + 4)) {  // minimum header length
+    return false;
+  }
+  unsigned int entryLen = (buf[*pos] & 0x3) + 1;
+  unsigned int sizeLen = ((buf[*pos] >> 2) & 0x3) + 1;
+  unsigned int timestampLen = ((buf[*pos] >> 4) & 0x7) + 1;
+  unsigned int headerLen = 1 + entryLen + sizeLen + timestampLen;
+  if (buf.size() < (*pos + headerLen)) {
+    return false;
+  }
+  uint32_t size = ReadVarInt(buf.subspan(*pos + 1 + entryLen, sizeLen));
+  // check this way to avoid overflow
+  if (size >= (buf.size() - *pos - headerLen)) {
+    return false;
+  }
+  *pos += headerLen + size;
+  return true;
+}
diff --git a/wpiutil/src/main/native/cpp/DsClient.cpp b/wpiutil/src/main/native/cpp/DsClient.cpp
deleted file mode 100644
index 455f10c..0000000
--- a/wpiutil/src/main/native/cpp/DsClient.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/DsClient.h"
-
-#include <fmt/format.h>
-#include <wpi/StringExtras.h>
-#include <wpi/json.h>
-#include <wpi/uv/Tcp.h>
-#include <wpi/uv/Timer.h>
-
-#include "wpi/Logger.h"
-
-using namespace wpi;
-
-static constexpr uv::Timer::Time kReconnectTime{500};
-
-DsClient::DsClient(wpi::uv::Loop& loop, wpi::Logger& logger,
-                   const private_init&)
-    : m_logger{logger},
-      m_tcp{uv::Tcp::Create(loop)},
-      m_timer{uv::Timer::Create(loop)} {
-  m_tcp->end.connect([this] {
-    WPI_DEBUG4(m_logger, "{}", "DS connection closed");
-    clearIp();
-    // try to connect again
-    m_tcp->Reuse([this] { m_timer->Start(kReconnectTime); });
-  });
-  m_tcp->data.connect([this](wpi::uv::Buffer buf, size_t len) {
-    HandleIncoming({buf.base, len});
-  });
-  m_timer->timeout.connect([this] { Connect(); });
-  Connect();
-}
-
-DsClient::~DsClient() = default;
-
-void DsClient::Close() {
-  m_tcp->Close();
-  m_timer->Close();
-  clearIp();
-}
-
-void DsClient::Connect() {
-  auto connreq = std::make_shared<uv::TcpConnectReq>();
-  connreq->connected.connect([this] {
-    m_json.clear();
-    m_tcp->StopRead();
-    m_tcp->StartRead();
-  });
-
-  connreq->error = [this](uv::Error err) {
-    WPI_DEBUG4(m_logger, "DS connect failure: {}", err.str());
-    // try to connect again
-    m_tcp->Reuse([this] { m_timer->Start(kReconnectTime); });
-  };
-
-  WPI_DEBUG4(m_logger, "{}", "Starting DS connection attempt");
-  m_tcp->Connect("127.0.0.1", 1742, connreq);
-}
-
-void DsClient::HandleIncoming(std::string_view in) {
-  // this is very bare-bones, as there are never nested {} in these messages
-  while (!in.empty()) {
-    // if json is empty, look for the first { (and discard)
-    if (m_json.empty()) {
-      auto start = in.find('{');
-      in = wpi::slice(in, start, std::string_view::npos);
-    }
-
-    // look for the terminating } (and save)
-    auto end = in.find('}');
-    if (end == std::string_view::npos) {
-      m_json.append(in);
-      return;  // nothing left to read
-    }
-
-    // have complete json message
-    ++end;
-    m_json.append(wpi::slice(in, 0, end));
-    in = wpi::slice(in, end, std::string_view::npos);
-    ParseJson();
-    m_json.clear();
-  }
-}
-
-void DsClient::ParseJson() {
-  WPI_DEBUG4(m_logger, "DsClient JSON: {}", m_json);
-  unsigned int ip = 0;
-  try {
-    ip = wpi::json::parse(m_json).at("robotIP").get<unsigned int>();
-  } catch (wpi::json::exception& e) {
-    WPI_INFO(m_logger, "DsClient JSON error: {}", e.what());
-    return;
-  }
-
-  if (ip == 0) {
-    clearIp();
-  } else {
-    // Convert number into dotted quad
-    auto newip = fmt::format("{}.{}.{}.{}", (ip >> 24) & 0xff,
-                             (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
-    WPI_INFO(m_logger, "DS received server IP: {}", newip);
-    setIp(newip);
-  }
-}
diff --git a/wpiutil/src/main/native/cpp/EventLoopRunner.cpp b/wpiutil/src/main/native/cpp/EventLoopRunner.cpp
deleted file mode 100644
index c86176e..0000000
--- a/wpiutil/src/main/native/cpp/EventLoopRunner.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/EventLoopRunner.h"
-
-#include "wpi/SmallVector.h"
-#include "wpi/condition_variable.h"
-#include "wpi/mutex.h"
-#include "wpi/uv/AsyncFunction.h"
-#include "wpi/uv/Loop.h"
-
-using namespace wpi;
-
-class EventLoopRunner::Thread : public SafeThread {
- public:
-  using UvExecFunc = uv::AsyncFunction<void(LoopFunc)>;
-
-  Thread() : m_loop(uv::Loop::Create()) {
-    // set up async handles
-    if (!m_loop) {
-      return;
-    }
-
-    // run function
-    m_doExec = UvExecFunc::Create(
-        m_loop, [loop = m_loop.get()](auto out, LoopFunc func) {
-          func(*loop);
-          out.set_value();
-        });
-  }
-
-  void Main() override {
-    if (m_loop) {
-      m_loop->Run();
-    }
-  }
-
-  // the loop
-  std::shared_ptr<uv::Loop> m_loop;
-
-  // run function
-  std::weak_ptr<UvExecFunc> m_doExec;
-};
-
-EventLoopRunner::EventLoopRunner() {
-  m_owner.Start();
-}
-
-EventLoopRunner::~EventLoopRunner() {
-  Stop();
-}
-
-void EventLoopRunner::Stop() {
-  ExecAsync([](uv::Loop& loop) {
-    // close all handles; this will (eventually) stop the loop
-    loop.Walk([](uv::Handle& h) {
-      h.SetLoopClosing(true);
-      h.Close();
-    });
-  });
-  m_owner.Join();
-}
-
-void EventLoopRunner::ExecAsync(LoopFunc func) {
-  if (auto thr = m_owner.GetThread()) {
-    if (auto doExec = thr->m_doExec.lock()) {
-      doExec->Call(std::move(func));
-    }
-  }
-}
-
-void EventLoopRunner::ExecSync(LoopFunc func) {
-  wpi::future<void> f;
-  if (auto thr = m_owner.GetThread()) {
-    if (auto doExec = thr->m_doExec.lock()) {
-      f = doExec->Call(std::move(func));
-    }
-  }
-  if (f.valid()) {
-    f.wait();
-  }
-}
-
-std::shared_ptr<uv::Loop> EventLoopRunner::GetLoop() {
-  if (auto thr = m_owner.GetThread()) {
-    return thr->m_loop;
-  }
-  return nullptr;
-}
diff --git a/wpiutil/src/main/native/cpp/HttpParser.cpp b/wpiutil/src/main/native/cpp/HttpParser.cpp
deleted file mode 100644
index 3c18e0f..0000000
--- a/wpiutil/src/main/native/cpp/HttpParser.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/HttpParser.h"
-
-using namespace wpi;
-
-uint32_t HttpParser::GetParserVersion() {
-  return static_cast<uint32_t>(http_parser_version());
-}
-
-HttpParser::HttpParser(Type type) {
-  http_parser_init(&m_parser,
-                   static_cast<http_parser_type>(static_cast<int>(type)));
-  m_parser.data = this;
-
-  http_parser_settings_init(&m_settings);
-
-  // Unlike the underlying http_parser library, we don't perform callbacks
-  // (other than body) with partial data; instead we buffer and call the user
-  // callback only when the data is complete.
-
-  // on_message_begin: initialize our state, call user callback
-  m_settings.on_message_begin = [](http_parser* p) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-    self.m_urlBuf.clear();
-    self.m_state = kStart;
-    self.messageBegin();
-    return self.m_aborted;
-  };
-
-  // on_url: collect into buffer
-  m_settings.on_url = [](http_parser* p, const char* at, size_t length) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-    // append to buffer
-    if ((self.m_urlBuf.size() + length) > self.m_maxLength) {
-      return 1;
-    }
-    self.m_urlBuf += std::string_view{at, length};
-    self.m_state = kUrl;
-    return 0;
-  };
-
-  // on_status: collect into buffer, call user URL callback
-  m_settings.on_status = [](http_parser* p, const char* at,
-                            size_t length) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-    // use valueBuf for the status
-    if ((self.m_valueBuf.size() + length) > self.m_maxLength) {
-      return 1;
-    }
-    self.m_valueBuf += std::string_view{at, length};
-    self.m_state = kStatus;
-    return 0;
-  };
-
-  // on_header_field: collect into buffer, call user header/status callback
-  m_settings.on_header_field = [](http_parser* p, const char* at,
-                                  size_t length) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-
-    // once we're in header, we know the URL is complete
-    if (self.m_state == kUrl) {
-      self.url(self.m_urlBuf);
-      if (self.m_aborted) {
-        return 1;
-      }
-    }
-
-    // once we're in header, we know the status is complete
-    if (self.m_state == kStatus) {
-      self.status(self.m_valueBuf);
-      if (self.m_aborted) {
-        return 1;
-      }
-    }
-
-    // if we previously were in value state, that means we finished a header
-    if (self.m_state == kValue) {
-      self.header(self.m_fieldBuf, self.m_valueBuf);
-      if (self.m_aborted) {
-        return 1;
-      }
-    }
-
-    // clear field and value when we enter this state
-    if (self.m_state != kField) {
-      self.m_state = kField;
-      self.m_fieldBuf.clear();
-      self.m_valueBuf.clear();
-    }
-
-    // append data to field buffer
-    if ((self.m_fieldBuf.size() + length) > self.m_maxLength) {
-      return 1;
-    }
-    self.m_fieldBuf += std::string_view{at, length};
-    return 0;
-  };
-
-  // on_header_field: collect into buffer
-  m_settings.on_header_value = [](http_parser* p, const char* at,
-                                  size_t length) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-
-    // if we weren't previously in value state, clear the buffer
-    if (self.m_state != kValue) {
-      self.m_state = kValue;
-      self.m_valueBuf.clear();
-    }
-
-    // append data to value buffer
-    if ((self.m_valueBuf.size() + length) > self.m_maxLength) {
-      return 1;
-    }
-    self.m_valueBuf += std::string_view{at, length};
-    return 0;
-  };
-
-  // on_headers_complete: call user status/header/complete callback
-  m_settings.on_headers_complete = [](http_parser* p) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-
-    // if we previously were in url state, that means we finished the url
-    if (self.m_state == kUrl) {
-      self.url(self.m_urlBuf);
-      if (self.m_aborted) {
-        return 1;
-      }
-    }
-
-    // if we previously were in status state, that means we finished the status
-    if (self.m_state == kStatus) {
-      self.status(self.m_valueBuf);
-      if (self.m_aborted) {
-        return 1;
-      }
-    }
-
-    // if we previously were in value state, that means we finished a header
-    if (self.m_state == kValue) {
-      self.header(self.m_fieldBuf, self.m_valueBuf);
-      if (self.m_aborted) {
-        return 1;
-      }
-    }
-
-    self.headersComplete(self.ShouldKeepAlive());
-    return self.m_aborted;
-  };
-
-  // on_body: call user callback
-  m_settings.on_body = [](http_parser* p, const char* at,
-                          size_t length) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-    self.body(std::string_view{at, length}, self.IsBodyFinal());
-    return self.m_aborted;
-  };
-
-  // on_message_complete: call user callback
-  m_settings.on_message_complete = [](http_parser* p) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-    self.messageComplete(self.ShouldKeepAlive());
-    return self.m_aborted;
-  };
-
-  // on_chunk_header: call user callback
-  m_settings.on_chunk_header = [](http_parser* p) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-    self.chunkHeader(p->content_length);
-    return self.m_aborted;
-  };
-
-  // on_chunk_complete: call user callback
-  m_settings.on_chunk_complete = [](http_parser* p) -> int {
-    auto& self = *static_cast<HttpParser*>(p->data);
-    self.chunkComplete();
-    return self.m_aborted;
-  };
-}
-
-void HttpParser::Reset(Type type) {
-  http_parser_init(&m_parser,
-                   static_cast<http_parser_type>(static_cast<int>(type)));
-  m_parser.data = this;
-  m_maxLength = 1024;
-  m_state = kStart;
-  m_urlBuf.clear();
-  m_fieldBuf.clear();
-  m_valueBuf.clear();
-  m_aborted = false;
-}
diff --git a/wpiutil/src/main/native/cpp/HttpServerConnection.cpp b/wpiutil/src/main/native/cpp/HttpServerConnection.cpp
deleted file mode 100644
index 716d2af..0000000
--- a/wpiutil/src/main/native/cpp/HttpServerConnection.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/HttpServerConnection.h"
-
-#include "fmt/format.h"
-#include "wpi/SmallString.h"
-#include "wpi/SmallVector.h"
-#include "wpi/SpanExtras.h"
-#include "wpi/StringExtras.h"
-#include "wpi/fmt/raw_ostream.h"
-#include "wpi/raw_uv_ostream.h"
-
-using namespace wpi;
-
-HttpServerConnection::HttpServerConnection(std::shared_ptr<uv::Stream> stream)
-    : m_stream(*stream) {
-  // process HTTP messages
-  m_messageCompleteConn =
-      m_request.messageComplete.connect_connection([this](bool keepAlive) {
-        m_keepAlive = keepAlive;
-        ProcessRequest();
-      });
-
-  // look for Accept-Encoding headers to determine if gzip is acceptable
-  m_request.messageBegin.connect([this] { m_acceptGzip = false; });
-  m_request.header.connect(
-      [this](std::string_view name, std::string_view value) {
-        if (wpi::equals_lower(name, "accept-encoding") &&
-            wpi::contains(value, "gzip")) {
-          m_acceptGzip = true;
-        }
-      });
-
-  // pass incoming data to HTTP parser
-  m_dataConn =
-      stream->data.connect_connection([this](uv::Buffer& buf, size_t size) {
-        m_request.Execute({buf.base, size});
-        if (m_request.HasError()) {
-          // could not parse; just close the connection
-          m_stream.Close();
-        }
-      });
-
-  // close when remote side closes
-  m_endConn =
-      stream->end.connect_connection([h = stream.get()] { h->Close(); });
-
-  // start reading
-  stream->StartRead();
-}
-
-void HttpServerConnection::BuildCommonHeaders(raw_ostream& os) {
-  os << "Server: WebServer/1.0\r\n"
-        "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, "
-        "post-check=0, max-age=0\r\n"
-        "Pragma: no-cache\r\n"
-        "Expires: Mon, 3 Jan 2000 12:34:56 GMT\r\n";
-}
-
-void HttpServerConnection::BuildHeader(raw_ostream& os, int code,
-                                       std::string_view codeText,
-                                       std::string_view contentType,
-                                       uint64_t contentLength,
-                                       std::string_view extra) {
-  fmt::print(os, "HTTP/{}.{} {} {}\r\n", m_request.GetMajor(),
-             m_request.GetMinor(), code, codeText);
-  if (contentLength == 0) {
-    m_keepAlive = false;
-  }
-  if (!m_keepAlive) {
-    os << "Connection: close\r\n";
-  }
-  BuildCommonHeaders(os);
-  os << "Content-Type: " << contentType << "\r\n";
-  if (contentLength != 0) {
-    fmt::print(os, "Content-Length: {}\r\n", contentLength);
-  }
-  os << "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: *\r\n";
-  if (!extra.empty()) {
-    os << extra;
-  }
-  os << "\r\n";  // header ends with a blank line
-}
-
-void HttpServerConnection::SendData(span<const uv::Buffer> bufs,
-                                    bool closeAfter) {
-  m_stream.Write(bufs, [closeAfter, stream = &m_stream](auto bufs, uv::Error) {
-    for (auto&& buf : bufs) {
-      buf.Deallocate();
-    }
-    if (closeAfter) {
-      stream->Close();
-    }
-  });
-}
-
-void HttpServerConnection::SendResponse(int code, std::string_view codeText,
-                                        std::string_view contentType,
-                                        std::string_view content,
-                                        std::string_view extraHeader) {
-  SmallVector<uv::Buffer, 4> toSend;
-  raw_uv_ostream os{toSend, 4096};
-  BuildHeader(os, code, codeText, contentType, content.size(), extraHeader);
-  os << content;
-  // close after write completes if we aren't keeping alive
-  SendData(os.bufs(), !m_keepAlive);
-}
-
-void HttpServerConnection::SendStaticResponse(
-    int code, std::string_view codeText, std::string_view contentType,
-    std::string_view content, bool gzipped, std::string_view extraHeader) {
-  // TODO: handle remote side not accepting gzip (very rare)
-
-  std::string_view contentEncodingHeader;
-  if (gzipped /* && m_acceptGzip*/) {
-    contentEncodingHeader = "Content-Encoding: gzip\r\n";
-  }
-
-  SmallVector<uv::Buffer, 4> bufs;
-  raw_uv_ostream os{bufs, 4096};
-  BuildHeader(os, code, codeText, contentType, content.size(),
-              fmt::format("{}{}", extraHeader, contentEncodingHeader));
-  // can send content without copying
-  bufs.emplace_back(content);
-
-  m_stream.Write(bufs, [closeAfter = !m_keepAlive, stream = &m_stream](
-                           auto bufs, uv::Error) {
-    // don't deallocate the static content
-    for (auto&& buf : wpi::drop_back(bufs)) {
-      buf.Deallocate();
-    }
-    if (closeAfter) {
-      stream->Close();
-    }
-  });
-}
-
-void HttpServerConnection::SendError(int code, std::string_view message) {
-  std::string_view codeText, extra, baseMessage;
-  switch (code) {
-    case 401:
-      codeText = "Unauthorized";
-      extra = "WWW-Authenticate: Basic realm=\"CameraServer\"";
-      baseMessage = "401: Not Authenticated!";
-      break;
-    case 404:
-      codeText = "Not Found";
-      baseMessage = "404: Not Found!";
-      break;
-    case 500:
-      codeText = "Internal Server Error";
-      baseMessage = "500: Internal Server Error!";
-      break;
-    case 400:
-      codeText = "Bad Request";
-      baseMessage = "400: Not Found!";
-      break;
-    case 403:
-      codeText = "Forbidden";
-      baseMessage = "403: Forbidden!";
-      break;
-    case 503:
-      codeText = "Service Unavailable";
-      baseMessage = "503: Service Unavailable";
-      break;
-    default:
-      code = 501;
-      codeText = "Not Implemented";
-      baseMessage = "501: Not Implemented!";
-      break;
-  }
-  SmallString<256> content{baseMessage};
-  content += "\r\n";
-  content += message;
-  SendResponse(code, codeText, "text/plain", content.str(), extra);
-}
diff --git a/wpiutil/src/main/native/cpp/HttpUtil.cpp b/wpiutil/src/main/native/cpp/HttpUtil.cpp
deleted file mode 100644
index b8b7cc8..0000000
--- a/wpiutil/src/main/native/cpp/HttpUtil.cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/HttpUtil.h"
-
-#include <cctype>
-
-#include "fmt/format.h"
-#include "wpi/Base64.h"
-#include "wpi/StringExtras.h"
-#include "wpi/TCPConnector.h"
-#include "wpi/raw_ostream.h"
-
-namespace wpi {
-
-std::string_view UnescapeURI(std::string_view str, SmallVectorImpl<char>& buf,
-                             bool* error) {
-  buf.clear();
-  for (auto i = str.begin(), end = str.end(); i != end; ++i) {
-    // pass non-escaped characters to output
-    if (*i != '%') {
-      // decode + to space
-      if (*i == '+') {
-        buf.push_back(' ');
-      } else {
-        buf.push_back(*i);
-      }
-      continue;
-    }
-
-    // are there enough characters left?
-    if (i + 2 >= end) {
-      *error = true;
-      return {};
-    }
-
-    // replace %xx with the corresponding character
-    unsigned val1 = hexDigitValue(*++i);
-    if (val1 == -1U) {
-      *error = true;
-      return {};
-    }
-    unsigned val2 = hexDigitValue(*++i);
-    if (val2 == -1U) {
-      *error = true;
-      return {};
-    }
-    buf.push_back((val1 << 4) | val2);
-  }
-
-  *error = false;
-  return {buf.data(), buf.size()};
-}
-
-std::string_view EscapeURI(std::string_view str, SmallVectorImpl<char>& buf,
-                           bool spacePlus) {
-  static const char* const hexLut = "0123456789ABCDEF";
-
-  buf.clear();
-  for (auto i = str.begin(), end = str.end(); i != end; ++i) {
-    // pass unreserved characters to output
-    if (std::isalnum(*i) || *i == '-' || *i == '_' || *i == '.' || *i == '~') {
-      buf.push_back(*i);
-      continue;
-    }
-
-    // encode space to +
-    if (spacePlus && *i == ' ') {
-      buf.push_back('+');
-      continue;
-    }
-
-    // convert others to %xx
-    buf.push_back('%');
-    buf.push_back(hexLut[((*i) >> 4) & 0x0f]);
-    buf.push_back(hexLut[(*i) & 0x0f]);
-  }
-
-  return {buf.data(), buf.size()};
-}
-
-HttpQueryMap::HttpQueryMap(std::string_view query) {
-  SmallVector<std::string_view, 16> queryElems;
-  split(query, queryElems, '&', 100, false);
-  for (auto elem : queryElems) {
-    auto [nameEsc, valueEsc] = split(elem, '=');
-    SmallString<64> nameBuf;
-    bool err = false;
-    auto name = wpi::UnescapeURI(nameEsc, nameBuf, &err);
-    // note: ignores duplicates
-    if (!err) {
-      m_elems.try_emplace(name, valueEsc);
-    }
-  }
-}
-
-std::optional<std::string_view> HttpQueryMap::Get(
-    std::string_view name, wpi::SmallVectorImpl<char>& buf) const {
-  auto it = m_elems.find(name);
-  if (it == m_elems.end()) {
-    return {};
-  }
-  bool err = false;
-  auto val = wpi::UnescapeURI(it->second, buf, &err);
-  if (err) {
-    return {};
-  }
-  return val;
-}
-
-HttpPath::HttpPath(std::string_view path) {
-  // special-case root path to be a single empty element
-  if (path == "/") {
-    m_pathEnds.emplace_back(0);
-    return;
-  }
-  wpi::SmallVector<std::string_view, 16> pathElems;
-  split(path, pathElems, '/', 100, false);
-  for (auto elem : pathElems) {
-    SmallString<64> buf;
-    bool err = false;
-    auto val = wpi::UnescapeURI(elem, buf, &err);
-    if (err) {
-      m_pathEnds.clear();
-      return;
-    }
-    m_pathBuf += val;
-    m_pathEnds.emplace_back(m_pathBuf.size());
-  }
-}
-
-bool HttpPath::startswith(size_t start,
-                          span<const std::string_view> match) const {
-  if (m_pathEnds.size() < (start + match.size())) {
-    return false;
-  }
-  bool first = start == 0;
-  auto p = m_pathEnds.begin() + start;
-  for (auto m : match) {
-    auto val = slice(m_pathBuf, first ? 0 : *(p - 1), *p);
-    if (val != m) {
-      return false;
-    }
-    first = false;
-    ++p;
-  }
-  return true;
-}
-
-std::string_view HttpPath::operator[](size_t n) const {
-  return slice(m_pathBuf, n == 0 ? 0 : m_pathEnds[n - 1], m_pathEnds[n]);
-}
-
-bool ParseHttpHeaders(raw_istream& is, SmallVectorImpl<char>* contentType,
-                      SmallVectorImpl<char>* contentLength) {
-  if (contentType) {
-    contentType->clear();
-  }
-  if (contentLength) {
-    contentLength->clear();
-  }
-
-  bool inContentType = false;
-  bool inContentLength = false;
-  SmallString<64> lineBuf;
-  for (;;) {
-    std::string_view line = rtrim(is.getline(lineBuf, 1024));
-    if (is.has_error()) {
-      return false;
-    }
-    if (line.empty()) {
-      return true;  // empty line signals end of headers
-    }
-
-    // header fields start at the beginning of the line
-    if (!std::isspace(line[0])) {
-      inContentType = false;
-      inContentLength = false;
-      std::string_view field;
-      std::tie(field, line) = split(line, ':');
-      field = rtrim(field);
-      if (equals_lower(field, "content-type")) {
-        inContentType = true;
-      } else if (equals_lower(field, "content-length")) {
-        inContentLength = true;
-      } else {
-        continue;  // ignore other fields
-      }
-    }
-
-    // collapse whitespace
-    line = ltrim(line);
-
-    // save field data
-    if (inContentType && contentType) {
-      contentType->append(line.begin(), line.end());
-    } else if (inContentLength && contentLength) {
-      contentLength->append(line.begin(), line.end());
-    }
-  }
-}
-
-bool FindMultipartBoundary(raw_istream& is, std::string_view boundary,
-                           std::string* saveBuf) {
-  SmallString<64> searchBuf;
-  searchBuf.resize(boundary.size() + 2);
-  size_t searchPos = 0;
-
-  // Per the spec, the --boundary should be preceded by \r\n, so do a first
-  // pass of 1-byte reads to throw those away (common case) and keep the
-  // last non-\r\n character in searchBuf.
-  if (!saveBuf) {
-    do {
-      is.read(searchBuf.data(), 1);
-      if (is.has_error()) {
-        return false;
-      }
-    } while (searchBuf[0] == '\r' || searchBuf[0] == '\n');
-    searchPos = 1;
-  }
-
-  // Look for --boundary.  Read boundarysize+2 bytes at a time
-  // during the search to speed up the reads, then fast-scan for -,
-  // and only then match the entire boundary.  This will be slow if
-  // there's a bunch of continuous -'s in the output, but that's unlikely.
-  for (;;) {
-    is.read(searchBuf.data() + searchPos, searchBuf.size() - searchPos);
-    if (is.has_error()) {
-      return false;
-    }
-
-    // Did we find the boundary?
-    if (searchBuf[0] == '-' && searchBuf[1] == '-' &&
-        wpi::substr(searchBuf, 2) == boundary) {
-      return true;
-    }
-
-    // Fast-scan for '-'
-    size_t pos = searchBuf.find('-', searchBuf[0] == '-' ? 1 : 0);
-    if (pos == std::string_view::npos) {
-      if (saveBuf) {
-        saveBuf->append(searchBuf.data(), searchBuf.size());
-      }
-    } else {
-      if (saveBuf) {
-        saveBuf->append(searchBuf.data(), pos);
-      }
-
-      // move '-' and following to start of buffer (next read will fill)
-      std::memmove(searchBuf.data(), searchBuf.data() + pos,
-                   searchBuf.size() - pos);
-      searchPos = searchBuf.size() - pos;
-    }
-  }
-}
-
-HttpLocation::HttpLocation(std::string_view url_, bool* error,
-                           std::string* errorMsg)
-    : url{url_} {
-  // Split apart into components
-  std::string_view query{url};
-
-  // scheme:
-  std::string_view scheme;
-  std::tie(scheme, query) = split(query, ':');
-  if (!equals_lower(scheme, "http")) {
-    *errorMsg = "only supports http URLs";
-    *error = true;
-    return;
-  }
-
-  // "//"
-  if (!starts_with(query, "//")) {
-    *errorMsg = "expected http://...";
-    *error = true;
-    return;
-  }
-  query.remove_prefix(2);
-
-  // user:password@host:port/
-  std::string_view authority;
-  std::tie(authority, query) = split(query, '/');
-
-  auto [userpass, hostport] = split(authority, '@');
-  // split leaves the RHS empty if the split char isn't present...
-  if (hostport.empty()) {
-    hostport = userpass;
-    userpass = {};
-  }
-
-  if (!userpass.empty()) {
-    auto [rawUser, rawPassword] = split(userpass, ':');
-    SmallString<64> userBuf, passBuf;
-    user = UnescapeURI(rawUser, userBuf, error);
-    if (*error) {
-      *errorMsg = fmt::format("could not unescape user \"{}\"", rawUser);
-      return;
-    }
-    password = UnescapeURI(rawPassword, passBuf, error);
-    if (*error) {
-      *errorMsg =
-          fmt::format("could not unescape password \"{}\"", rawPassword);
-      return;
-    }
-  }
-
-  std::string_view portStr;
-  std::tie(host, portStr) = rsplit(hostport, ':');
-  if (host.empty()) {
-    *errorMsg = "host is empty";
-    *error = true;
-    return;
-  }
-  if (portStr.empty()) {
-    port = 80;
-  } else if (auto p = parse_integer<int>(portStr, 10)) {
-    port = p.value();
-  } else {
-    *errorMsg = fmt::format("port \"{}\" is not an integer", portStr);
-    *error = true;
-    return;
-  }
-
-  // path?query#fragment
-  std::tie(query, fragment) = split(query, '#');
-  std::tie(path, query) = split(query, '?');
-
-  // Split query string into parameters
-  while (!query.empty()) {
-    // split out next param and value
-    std::string_view rawParam, rawValue;
-    std::tie(rawParam, query) = split(query, '&');
-    if (rawParam.empty()) {
-      continue;  // ignore "&&"
-    }
-    std::tie(rawParam, rawValue) = split(rawParam, '=');
-
-    // unescape param
-    *error = false;
-    SmallString<64> paramBuf;
-    std::string_view param = UnescapeURI(rawParam, paramBuf, error);
-    if (*error) {
-      *errorMsg = fmt::format("could not unescape parameter \"{}\"", rawParam);
-      return;
-    }
-
-    // unescape value
-    SmallString<64> valueBuf;
-    std::string_view value = UnescapeURI(rawValue, valueBuf, error);
-    if (*error) {
-      *errorMsg = fmt::format("could not unescape value \"{}\"", rawValue);
-      return;
-    }
-
-    params.emplace_back(std::make_pair(param, value));
-  }
-
-  *error = false;
-}
-
-void HttpRequest::SetAuth(const HttpLocation& loc) {
-  if (!loc.user.empty()) {
-    SmallString<64> userpass;
-    userpass += loc.user;
-    userpass += ':';
-    userpass += loc.password;
-    Base64Encode(userpass.str(), &auth);
-  }
-}
-
-bool HttpConnection::Handshake(const HttpRequest& request,
-                               std::string* warnMsg) {
-  // send GET request
-  os << "GET /" << request.path << " HTTP/1.1\r\n";
-  os << "Host: " << request.host << "\r\n";
-  if (!request.auth.empty()) {
-    os << "Authorization: Basic " << request.auth << "\r\n";
-  }
-  os << "\r\n";
-  os.flush();
-
-  // read first line of response
-  SmallString<64> lineBuf;
-  std::string_view line = rtrim(is.getline(lineBuf, 1024));
-  if (is.has_error()) {
-    *warnMsg = "disconnected before response";
-    return false;
-  }
-
-  // see if we got a HTTP 200 response
-  std::string_view httpver, code, codeText;
-  std::tie(httpver, line) = split(line, ' ');
-  std::tie(code, codeText) = split(line, ' ');
-  if (!starts_with(httpver, "HTTP")) {
-    *warnMsg = "did not receive HTTP response";
-    return false;
-  }
-  if (code != "200") {
-    *warnMsg = fmt::format("received {} {} response", code, codeText);
-    return false;
-  }
-
-  // Parse headers
-  if (!ParseHttpHeaders(is, &contentType, &contentLength)) {
-    *warnMsg = "disconnected during headers";
-    return false;
-  }
-
-  return true;
-}
-
-void HttpMultipartScanner::SetBoundary(std::string_view boundary) {
-  m_boundaryWith = "\n--";
-  m_boundaryWith += boundary;
-  m_boundaryWithout = "\n";
-  m_boundaryWithout += boundary;
-  m_dashes = kUnknown;
-}
-
-void HttpMultipartScanner::Reset(bool saveSkipped) {
-  m_saveSkipped = saveSkipped;
-  m_state = kBoundary;
-  m_posWith = 0;
-  m_posWithout = 0;
-  m_buf.resize(0);
-}
-
-std::string_view HttpMultipartScanner::Execute(std::string_view in) {
-  if (m_state == kDone) {
-    Reset(m_saveSkipped);
-  }
-  if (m_saveSkipped) {
-    m_buf += in;
-  }
-
-  size_t pos = 0;
-  if (m_state == kBoundary) {
-    for (char ch : in) {
-      ++pos;
-      if (m_dashes != kWithout) {
-        if (ch == m_boundaryWith[m_posWith]) {
-          ++m_posWith;
-          if (m_posWith == m_boundaryWith.size()) {
-            // Found the boundary; transition to padding
-            m_state = kPadding;
-            m_dashes = kWith;  // no longer accept plain 'boundary'
-            break;
-          }
-        } else if (ch == m_boundaryWith[0]) {
-          m_posWith = 1;
-        } else {
-          m_posWith = 0;
-        }
-      }
-
-      if (m_dashes != kWith) {
-        if (ch == m_boundaryWithout[m_posWithout]) {
-          ++m_posWithout;
-          if (m_posWithout == m_boundaryWithout.size()) {
-            // Found the boundary; transition to padding
-            m_state = kPadding;
-            m_dashes = kWithout;  // no longer accept '--boundary'
-            break;
-          }
-        } else if (ch == m_boundaryWithout[0]) {
-          m_posWithout = 1;
-        } else {
-          m_posWithout = 0;
-        }
-      }
-    }
-  }
-
-  if (m_state == kPadding) {
-    for (char ch : drop_front(in, pos)) {
-      ++pos;
-      if (ch == '\n') {
-        // Found the LF; return remaining input buffer (following it)
-        m_state = kDone;
-        if (m_saveSkipped) {
-          m_buf.resize(m_buf.size() - in.size() + pos);
-        }
-        return drop_front(in, pos);
-      }
-    }
-  }
-
-  // We consumed the entire input
-  return {};
-}
-
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/cpp/MappedFileRegion.cpp b/wpiutil/src/main/native/cpp/MappedFileRegion.cpp
new file mode 100644
index 0000000..006e395
--- /dev/null
+++ b/wpiutil/src/main/native/cpp/MappedFileRegion.cpp
@@ -0,0 +1,133 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "wpi/MappedFileRegion.h"
+
+#include <sys/types.h>
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>  // NOLINT(build/include_order)
+
+#include <memoryapi.h>
+#include <sysinfoapi.h>
+
+#else  // _WIN32
+
+#include <sys/mman.h>
+#include <unistd.h>
+
+#endif  // _WIN32
+
+#ifdef _MSC_VER
+#include <io.h>
+#endif
+
+#ifdef _WIN32
+#include "wpi/WindowsError.h"
+#endif
+
+using namespace wpi;
+
+MappedFileRegion::MappedFileRegion(fs::file_t f, uint64_t length,
+                                   uint64_t offset, MapMode mapMode,
+                                   std::error_code& ec)
+    : m_size(length) {
+#ifdef _WIN32
+  if (f == INVALID_HANDLE_VALUE) {
+    ec = std::make_error_code(std::errc::bad_file_descriptor);
+    return;
+  }
+
+  HANDLE fileMappingHandle = ::CreateFileMappingW(
+      f, 0, mapMode == kReadOnly ? PAGE_READONLY : PAGE_READWRITE, length >> 32,
+      length & 0xffffffff, 0);
+  if (fileMappingHandle == nullptr) {
+    ec = wpi::mapWindowsError(GetLastError());
+    return;
+  }
+
+  DWORD dwDesiredAccess = 0;
+  switch (mapMode) {
+    case kReadOnly:
+      dwDesiredAccess = FILE_MAP_READ;
+      break;
+    case kReadWrite:
+      dwDesiredAccess = FILE_MAP_WRITE;
+      break;
+    case kPriv:
+      dwDesiredAccess = FILE_MAP_WRITE | FILE_MAP_COPY;
+      break;
+  }
+  m_mapping = ::MapViewOfFile(fileMappingHandle, dwDesiredAccess, offset >> 32,
+                              offset & 0xffffffff, length);
+  if (m_mapping == nullptr) {
+    ec = wpi::mapWindowsError(GetLastError());
+    ::CloseHandle(fileMappingHandle);
+    return;
+  }
+
+  // Close the file mapping handle, as it's kept alive by the file mapping. But
+  // neither the file mapping nor the file mapping handle keep the file handle
+  // alive, so we need to keep a reference to the file in case all other handles
+  // are closed and the file is deleted, which may cause invalid data to be read
+  // from the file.
+  ::CloseHandle(fileMappingHandle);
+  if (!::DuplicateHandle(::GetCurrentProcess(), f, ::GetCurrentProcess(),
+                         &m_fileHandle, 0, 0, DUPLICATE_SAME_ACCESS)) {
+    ec = wpi::mapWindowsError(GetLastError());
+    ::UnmapViewOfFile(m_mapping);
+    m_mapping = nullptr;
+    return;
+  }
+#else
+  m_mapping =
+      ::mmap(nullptr, length,
+             mapMode == kReadOnly ? PROT_READ : (PROT_READ | PROT_WRITE),
+             mapMode == kPriv ? MAP_PRIVATE : MAP_SHARED, f, offset);
+  if (m_mapping == MAP_FAILED) {
+    ec = std::error_code(errno, std::generic_category());
+    m_mapping = nullptr;
+  }
+#endif
+}
+
+void MappedFileRegion::Flush() {
+#ifdef _WIN32
+  ::FlushViewOfFile(m_mapping, 0);
+  ::FlushFileBuffers(m_fileHandle);
+#else
+  ::msync(m_mapping, m_size, MS_ASYNC);
+#endif
+}
+
+void MappedFileRegion::Unmap() {
+  if (!m_mapping) {
+    return;
+  }
+#ifdef _WIN32
+  ::UnmapViewOfFile(m_mapping);
+  ::CloseHandle(m_fileHandle);
+#else
+  ::munmap(m_mapping, m_size);
+#endif
+  m_mapping = nullptr;
+}
+
+size_t MappedFileRegion::GetAlignment() {
+#ifdef _WIN32
+  SYSTEM_INFO SysInfo;
+  ::GetSystemInfo(&SysInfo);
+  return SysInfo.dwAllocationGranularity;
+#else
+  static long pageSize = ::getpagesize();  // NOLINT
+  if (pageSize < 0) {
+    pageSize = 4096;
+  }
+  return pageSize;
+#endif
+}
diff --git a/wpiutil/src/main/native/cpp/MessagePack.cpp b/wpiutil/src/main/native/cpp/MessagePack.cpp
new file mode 100644
index 0000000..60a2f01
--- /dev/null
+++ b/wpiutil/src/main/native/cpp/MessagePack.cpp
@@ -0,0 +1,45 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include "wpi/MessagePack.h"
+
+using namespace mpack;
+
+mpack_error_t mpack::mpack_expect_str(mpack_reader_t* reader, std::string* out,
+                                      uint32_t maxLen) {
+  uint32_t count = mpack_expect_str_max(reader, maxLen);
+  mpack_error_t err = mpack_reader_error(reader);
+  if (err != mpack_ok) {
+    return err;
+  }
+  const char* bytes = mpack_read_bytes_inplace(reader, count);
+  if (bytes) {
+    out->assign(bytes, count);
+  } else {
+    return mpack_reader_error(reader);
+  }
+  mpack_done_str(reader);
+  return mpack_ok;
+}
+
+mpack_error_t mpack::mpack_read_str(mpack_reader_t* reader, mpack_tag_t* tag,
+                                    std::string* out, uint32_t maxLen) {
+  uint32_t count = mpack_tag_str_length(tag);
+  mpack_error_t err = mpack_reader_error(reader);
+  if (err != mpack_ok) {
+    return err;
+  }
+  if (count > maxLen) {
+    mpack_reader_flag_error(reader, mpack_error_too_big);
+    return mpack_error_too_big;
+  }
+  const char* bytes = mpack_read_bytes_inplace(reader, count);
+  if (bytes) {
+    out->assign(bytes, count);
+  } else {
+    return mpack_reader_error(reader);
+  }
+  mpack_done_str(reader);
+  return mpack_ok;
+}
diff --git a/wpiutil/src/main/native/cpp/MimeTypes.cpp b/wpiutil/src/main/native/cpp/MimeTypes.cpp
deleted file mode 100644
index 5f5bf59..0000000
--- a/wpiutil/src/main/native/cpp/MimeTypes.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/MimeTypes.h"
-
-#include "wpi/StringExtras.h"
-#include "wpi/StringMap.h"
-
-namespace wpi {
-
-// derived partially from
-// https://github.com/DEGoodmanWilson/libmime/blob/stable/0.1.2/mime/mime.cpp
-std::string_view MimeTypeFromPath(std::string_view path) {
-  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
-  static StringMap<const char*> mimeTypes{
-      // text
-      {"css", "text/css"},
-      {"csv", "text/csv"},
-      {"htm", "text/html"},
-      {"html", "text/html"},
-      {"js", "text/javascript"},
-      {"json", "application/json"},
-      {"map", "application/json"},
-      {"md", "text/markdown"},
-      {"txt", "text/plain"},
-      {"xml", "text/xml"},
-
-      // images
-      {"apng", "image/apng"},
-      {"bmp", "image/bmp"},
-      {"gif", "image/gif"},
-      {"cur", "image/x-icon"},
-      {"ico", "image/x-icon"},
-      {"jpg", "image/jpeg"},
-      {"jpeg", "image/jpeg"},
-      {"png", "image/png"},
-      {"svg", "image/svg+xml"},
-      {"tif", "image/tiff"},
-      {"tiff", "image/tiff"},
-      {"webp", "image/webp"},
-
-      // fonts
-      {"otf", "font/otf"},
-      {"ttf", "font/ttf"},
-      {"woff", "font/woff"},
-
-      // misc
-      {"pdf", "application/pdf"},
-      {"zip", "application/zip"},
-  };
-
-  static const char* defaultType = "application/octet-stream";
-
-  auto pos = path.find_last_of("/");
-  if (pos != std::string_view::npos) {
-    path = wpi::substr(path, pos + 1);
-  }
-  auto dot_pos = path.find_last_of(".");
-  if (dot_pos > 0 && dot_pos != std::string_view::npos) {
-    auto type = mimeTypes.find(wpi::substr(path, dot_pos + 1));
-    if (type != mimeTypes.end()) {
-      return type->getValue();
-    }
-  }
-  return defaultType;
-}
-
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/cpp/MulticastHandleManager.cpp b/wpiutil/src/main/native/cpp/MulticastHandleManager.cpp
deleted file mode 100644
index d249a1c..0000000
--- a/wpiutil/src/main/native/cpp/MulticastHandleManager.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "MulticastHandleManager.h"
-
-using namespace wpi;
-
-MulticastHandleManager& wpi::GetMulticastManager() {
-  static MulticastHandleManager manager;
-  return manager;
-}
diff --git a/wpiutil/src/main/native/cpp/MulticastHandleManager.h b/wpiutil/src/main/native/cpp/MulticastHandleManager.h
deleted file mode 100644
index be8d061..0000000
--- a/wpiutil/src/main/native/cpp/MulticastHandleManager.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <memory>
-
-#include "wpi/DenseMap.h"
-#include "wpi/MulticastServiceAnnouncer.h"
-#include "wpi/MulticastServiceResolver.h"
-#include "wpi/UidVector.h"
-
-namespace wpi {
-struct MulticastHandleManager {
-  wpi::mutex mutex;
-  wpi::UidVector<int, 8> handleIds;
-  wpi::DenseMap<size_t, std::unique_ptr<wpi::MulticastServiceResolver>>
-      resolvers;
-  wpi::DenseMap<size_t, std::unique_ptr<wpi::MulticastServiceAnnouncer>>
-      announcers;
-};
-
-MulticastHandleManager& GetMulticastManager();
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/cpp/MulticastServiceAnnouncer.cpp b/wpiutil/src/main/native/cpp/MulticastServiceAnnouncer.cpp
deleted file mode 100644
index 736a03d..0000000
--- a/wpiutil/src/main/native/cpp/MulticastServiceAnnouncer.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/MulticastServiceAnnouncer.h"
-
-#include <wpi/SmallVector.h>
-
-#include "MulticastHandleManager.h"
-
-extern "C" {
-WPI_MulticastServiceAnnouncerHandle WPI_CreateMulticastServiceAnnouncer(
-    const char* serviceName, const char* serviceType, int32_t port,
-    int32_t txtCount, const char** keys, const char** values)
-
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-
-  wpi::SmallVector<std::pair<std::string_view, std::string_view>, 8> txts;
-
-  for (int32_t i = 0; i < txtCount; i++) {
-    txts.emplace_back(
-        std::pair<std::string_view, std::string_view>{keys[i], values[i]});
-  }
-
-  auto announcer = std::make_unique<wpi::MulticastServiceAnnouncer>(
-      serviceName, serviceType, port, txts);
-
-  size_t index = manager.handleIds.emplace_back(3);
-  manager.announcers[index] = std::move(announcer);
-
-  return index;
-}
-
-void WPI_FreeMulticastServiceAnnouncer(
-    WPI_MulticastServiceAnnouncerHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  manager.announcers[handle] = nullptr;
-  manager.handleIds.erase(handle);
-}
-
-void WPI_StartMulticastServiceAnnouncer(
-    WPI_MulticastServiceAnnouncerHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& announcer = manager.announcers[handle];
-  announcer->Start();
-}
-
-void WPI_StopMulticastServiceAnnouncer(
-    WPI_MulticastServiceAnnouncerHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& announcer = manager.announcers[handle];
-  announcer->Stop();
-}
-
-int32_t WPI_GetMulticastServiceAnnouncerHasImplementation(
-    WPI_MulticastServiceAnnouncerHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& announcer = manager.announcers[handle];
-  return announcer->HasImplementation();
-}
-}  // extern "C"
diff --git a/wpiutil/src/main/native/cpp/MulticastServiceResolver.cpp b/wpiutil/src/main/native/cpp/MulticastServiceResolver.cpp
deleted file mode 100644
index b834f17..0000000
--- a/wpiutil/src/main/native/cpp/MulticastServiceResolver.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/MulticastServiceResolver.h"
-
-#include "MulticastHandleManager.h"
-#include "wpi/MemAlloc.h"
-
-extern "C" {
-WPI_MulticastServiceResolverHandle WPI_CreateMulticastServiceResolver(
-    const char* serviceType)
-
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-
-  auto resolver = std::make_unique<wpi::MulticastServiceResolver>(serviceType);
-
-  size_t index = manager.handleIds.emplace_back(2);
-  manager.resolvers[index] = std::move(resolver);
-
-  return index;
-}
-
-void WPI_FreeMulticastServiceResolver(
-    WPI_MulticastServiceResolverHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  manager.resolvers[handle] = nullptr;
-  manager.handleIds.erase(handle);
-}
-
-void WPI_StartMulticastServiceResolver(
-    WPI_MulticastServiceResolverHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& resolver = manager.resolvers[handle];
-  resolver->Start();
-}
-
-void WPI_StopMulticastServiceResolver(
-    WPI_MulticastServiceResolverHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& resolver = manager.resolvers[handle];
-  resolver->Stop();
-}
-
-int32_t WPI_GetMulticastServiceResolverHasImplementation(
-    WPI_MulticastServiceResolverHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& resolver = manager.resolvers[handle];
-  return resolver->HasImplementation();
-}
-
-WPI_EventHandle WPI_GetMulticastServiceResolverEventHandle(
-    WPI_MulticastServiceResolverHandle handle) {
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& resolver = manager.resolvers[handle];
-  return resolver->GetEventHandle();
-}
-
-WPI_ServiceData* WPI_GetMulticastServiceResolverData(
-    WPI_MulticastServiceResolverHandle handle, int32_t* dataCount) {
-  std::vector<wpi::MulticastServiceResolver::ServiceData> allData;
-  {
-    auto& manager = wpi::GetMulticastManager();
-    std::scoped_lock lock{manager.mutex};
-    auto& resolver = manager.resolvers[handle];
-    allData = resolver->GetData();
-  }
-  if (allData.empty()) {
-    *dataCount = 0;
-    return nullptr;
-  }
-  size_t allocSize = sizeof(WPI_ServiceData) * allData.size();
-
-  for (auto&& data : allData) {
-    // Include space for hostName and serviceType (+ terminators)
-    allocSize += data.hostName.size() + data.serviceName.size() + 2;
-
-    size_t keysTotalLength = 0;
-    size_t valuesTotalLength = 0;
-    // Include space for all keys and values, and pointer array
-    for (auto&& t : data.txt) {
-      allocSize += sizeof(const char*);
-      keysTotalLength += (t.first.size() + 1);
-      allocSize += sizeof(const char*);
-      valuesTotalLength += (t.second.size() + 1);
-    }
-    allocSize += keysTotalLength;
-    allocSize += valuesTotalLength;
-  }
-
-  uint8_t* cDataRaw = reinterpret_cast<uint8_t*>(wpi::safe_malloc(allocSize));
-  if (!cDataRaw) {
-    return nullptr;
-  }
-  WPI_ServiceData* rootArray = reinterpret_cast<WPI_ServiceData*>(cDataRaw);
-  cDataRaw += (sizeof(WPI_ServiceData) + allData.size());
-  WPI_ServiceData* currentData = rootArray;
-
-  for (auto&& data : allData) {
-    currentData->ipv4Address = data.ipv4Address;
-    currentData->port = data.port;
-    currentData->txtCount = data.txt.size();
-
-    std::memcpy(cDataRaw, data.hostName.c_str(), data.hostName.size() + 1);
-    currentData->hostName = reinterpret_cast<const char*>(cDataRaw);
-    cDataRaw += data.hostName.size() + 1;
-
-    std::memcpy(cDataRaw, data.serviceName.c_str(),
-                data.serviceName.size() + 1);
-    currentData->serviceName = reinterpret_cast<const char*>(cDataRaw);
-    cDataRaw += data.serviceName.size() + 1;
-
-    char** valuesPtrArr = reinterpret_cast<char**>(cDataRaw);
-    cDataRaw += (sizeof(char**) * data.txt.size());
-    char** keysPtrArr = reinterpret_cast<char**>(cDataRaw);
-    cDataRaw += (sizeof(char**) * data.txt.size());
-
-    currentData->txtKeys = const_cast<const char**>(keysPtrArr);
-    currentData->txtValues = const_cast<const char**>(valuesPtrArr);
-
-    for (size_t i = 0; i < data.txt.size(); i++) {
-      keysPtrArr[i] = reinterpret_cast<char*>(cDataRaw);
-      std::memcpy(keysPtrArr[i], data.txt[i].first.c_str(),
-                  data.txt[i].first.size() + 1);
-      cDataRaw += (data.txt[i].first.size() + 1);
-
-      valuesPtrArr[i] = reinterpret_cast<char*>(cDataRaw);
-      std::memcpy(valuesPtrArr[i], data.txt[i].second.c_str(),
-                  data.txt[i].second.size() + 1);
-      cDataRaw += (data.txt[i].second.size() + 1);
-    }
-    currentData++;
-  }
-
-  return rootArray;
-}
-
-void WPI_FreeServiceData(WPI_ServiceData* serviceData, int32_t length) {
-  std::free(serviceData);
-}
-}  // extern "C"
diff --git a/wpiutil/src/main/native/cpp/ParallelTcpConnector.cpp b/wpiutil/src/main/native/cpp/ParallelTcpConnector.cpp
deleted file mode 100644
index 5a8394a..0000000
--- a/wpiutil/src/main/native/cpp/ParallelTcpConnector.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/ParallelTcpConnector.h"
-
-#include <fmt/format.h>
-
-#include "wpi/Logger.h"
-#include "wpi/uv/GetAddrInfo.h"
-#include "wpi/uv/Loop.h"
-#include "wpi/uv/Tcp.h"
-#include "wpi/uv/Timer.h"
-#include "wpi/uv/util.h"
-
-using namespace wpi;
-
-ParallelTcpConnector::ParallelTcpConnector(
-    wpi::uv::Loop& loop, wpi::uv::Timer::Time reconnectRate,
-    wpi::Logger& logger, std::function<void(wpi::uv::Tcp& tcp)> connected,
-    const private_init&)
-    : m_loop{loop},
-      m_logger{logger},
-      m_reconnectRate{reconnectRate},
-      m_connected{std::move(connected)},
-      m_reconnectTimer{uv::Timer::Create(loop)} {
-  m_reconnectTimer->timeout.connect([this] {
-    if (!IsConnected()) {
-      WPI_DEBUG1(m_logger, "{}", "timed out, reconnecting");
-      Connect();
-    }
-  });
-}
-
-ParallelTcpConnector::~ParallelTcpConnector() = default;
-
-void ParallelTcpConnector::Close() {
-  CancelAll();
-  m_reconnectTimer->Close();
-}
-
-void ParallelTcpConnector::SetServers(
-    wpi::span<const std::pair<std::string, unsigned int>> servers) {
-  m_servers.assign(servers.begin(), servers.end());
-  if (!IsConnected()) {
-    Connect();
-  }
-}
-
-void ParallelTcpConnector::Disconnected() {
-  if (m_isConnected) {
-    m_isConnected = false;
-    Connect();
-  }
-}
-
-void ParallelTcpConnector::Succeeded(uv::Tcp& tcp) {
-  if (!m_isConnected) {
-    m_isConnected = true;
-    m_reconnectTimer->Stop();
-    CancelAll(&tcp);
-  }
-}
-
-void ParallelTcpConnector::Connect() {
-  if (IsConnected()) {
-    return;
-  }
-
-  CancelAll();
-  m_reconnectTimer->Start(m_reconnectRate);
-
-  WPI_DEBUG3(m_logger, "{}", "starting new connection attempts");
-
-  // kick off parallel lookups
-  for (auto&& server : m_servers) {
-    auto req = std::make_shared<uv::GetAddrInfoReq>();
-    m_resolvers.emplace_back(req);
-
-    req->resolved.connect(
-        [this, req = req.get()](const addrinfo& addrinfo) {
-          if (IsConnected()) {
-            return;
-          }
-
-          // kick off parallel connection attempts
-          for (auto ai = &addrinfo; ai; ai = ai->ai_next) {
-            auto tcp = uv::Tcp::Create(m_loop);
-            m_attempts.emplace_back(tcp);
-
-            auto connreq = std::make_shared<uv::TcpConnectReq>();
-            connreq->connected.connect(
-                [this, tcp = tcp.get()] {
-                  if (m_logger.min_level() <= wpi::WPI_LOG_DEBUG4) {
-                    std::string ip;
-                    unsigned int port = 0;
-                    uv::AddrToName(tcp->GetPeer(), &ip, &port);
-                    WPI_DEBUG4(m_logger,
-                               "successful connection ({}) to {} port {}",
-                               static_cast<void*>(tcp), ip, port);
-                  }
-                  if (IsConnected()) {
-                    tcp->Shutdown([tcp] { tcp->Close(); });
-                    return;
-                  }
-                  if (m_connected) {
-                    m_connected(*tcp);
-                  }
-                },
-                shared_from_this());
-
-            connreq->error = [selfWeak = weak_from_this(),
-                              tcp = tcp.get()](uv::Error err) {
-              if (auto self = selfWeak.lock()) {
-                WPI_DEBUG1(self->m_logger, "connect failure ({}): {}",
-                           static_cast<void*>(tcp), err.str());
-              }
-            };
-
-            if (m_logger.min_level() <= wpi::WPI_LOG_DEBUG4) {
-              std::string ip;
-              unsigned int port = 0;
-              uv::AddrToName(*reinterpret_cast<sockaddr_storage*>(ai->ai_addr),
-                             &ip, &port);
-              WPI_DEBUG4(
-                  m_logger,
-                  "Info({}) starting connection attempt ({}) to {} port {}",
-                  static_cast<void*>(req), static_cast<void*>(tcp.get()), ip,
-                  port);
-            }
-            tcp->Connect(*ai->ai_addr, connreq);
-          }
-        },
-        shared_from_this());
-
-    req->error = [req = req.get(), selfWeak = weak_from_this()](uv::Error err) {
-      if (auto self = selfWeak.lock()) {
-        WPI_DEBUG1(self->m_logger, "GetAddrInfo({}) failure: {}",
-                   static_cast<void*>(req), err.str());
-      }
-    };
-
-    WPI_DEBUG4(m_logger, "starting GetAddrInfo({}) for {} port {}",
-               static_cast<void*>(req.get()), server.first, server.second);
-    addrinfo hints;
-    std::memset(&hints, 0, sizeof(hints));
-    hints.ai_family = AF_UNSPEC;
-    hints.ai_socktype = SOCK_STREAM;
-    hints.ai_protocol = IPPROTO_TCP;
-    hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
-    uv::GetAddrInfo(m_loop, req, server.first, fmt::format("{}", server.second),
-                    &hints);
-  }
-}
-
-void ParallelTcpConnector::CancelAll(wpi::uv::Tcp* except) {
-  WPI_DEBUG4(m_logger, "{}", "canceling previous attempts");
-  for (auto&& resolverWeak : m_resolvers) {
-    if (auto resolver = resolverWeak.lock()) {
-      WPI_DEBUG4(m_logger, "canceling GetAddrInfo({})",
-                 static_cast<void*>(resolver.get()));
-      resolver->Cancel();
-    }
-  }
-  m_resolvers.clear();
-
-  for (auto&& tcpWeak : m_attempts) {
-    if (auto tcp = tcpWeak.lock()) {
-      if (tcp.get() != except) {
-        WPI_DEBUG4(m_logger, "canceling connection attempt ({})",
-                   static_cast<void*>(tcp.get()));
-        tcp->Close();
-      }
-    }
-  }
-  m_attempts.clear();
-}
diff --git a/wpiutil/src/main/native/cpp/PortForwarder.cpp b/wpiutil/src/main/native/cpp/PortForwarder.cpp
deleted file mode 100644
index a423d48..0000000
--- a/wpiutil/src/main/native/cpp/PortForwarder.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/PortForwarder.h"
-
-#include "fmt/format.h"
-#include "wpi/DenseMap.h"
-#include "wpi/EventLoopRunner.h"
-#include "wpi/uv/GetAddrInfo.h"
-#include "wpi/uv/Tcp.h"
-#include "wpi/uv/Timer.h"
-
-using namespace wpi;
-
-struct PortForwarder::Impl {
- public:
-  EventLoopRunner runner;
-  DenseMap<unsigned int, std::weak_ptr<uv::Tcp>> servers;
-};
-
-PortForwarder::PortForwarder() : m_impl{new Impl} {}
-
-PortForwarder& PortForwarder::GetInstance() {
-  static PortForwarder instance;
-  return instance;
-}
-
-static void CopyStream(uv::Stream& in, std::weak_ptr<uv::Stream> outWeak) {
-  in.data.connect([&in, outWeak](uv::Buffer& buf, size_t len) {
-    uv::Buffer buf2 = buf.Dup();
-    buf2.len = len;
-    auto out = outWeak.lock();
-    if (!out) {
-      buf2.Deallocate();
-      in.Close();
-      return;
-    }
-    out->Write({buf2}, [](auto bufs, uv::Error) {
-      for (auto buf : bufs) {
-        buf.Deallocate();
-      }
-    });
-  });
-}
-
-void PortForwarder::Add(unsigned int port, std::string_view remoteHost,
-                        unsigned int remotePort) {
-  m_impl->runner.ExecSync([&](uv::Loop& loop) {
-    auto server = uv::Tcp::Create(loop);
-
-    // bind to local port
-    server->Bind("", port);
-
-    // when we get a connection, accept it
-    server->connection.connect([serverPtr = server.get(),
-                                host = std::string{remoteHost}, remotePort] {
-      auto& loop = serverPtr->GetLoopRef();
-      auto client = serverPtr->Accept();
-      if (!client) {
-        return;
-      }
-
-      // close on error
-      client->error.connect(
-          [clientPtr = client.get()](uv::Error err) { clientPtr->Close(); });
-
-      // connected flag
-      auto connected = std::make_shared<bool>(false);
-      client->SetData(connected);
-
-      auto remote = uv::Tcp::Create(loop);
-      remote->error.connect(
-          [remotePtr = remote.get(),
-           clientWeak = std::weak_ptr<uv::Tcp>(client)](uv::Error err) {
-            remotePtr->Close();
-            if (auto client = clientWeak.lock()) {
-              client->Close();
-            }
-          });
-
-      // resolve address
-      uv::GetAddrInfo(
-          loop,
-          [clientWeak = std::weak_ptr<uv::Tcp>(client),
-           remoteWeak = std::weak_ptr<uv::Tcp>(remote)](const addrinfo& addr) {
-            auto remote = remoteWeak.lock();
-            if (!remote) {
-              return;
-            }
-
-            // connect to remote address/port
-            remote->Connect(*addr.ai_addr, [remotePtr = remote.get(),
-                                            remoteWeak, clientWeak] {
-              auto client = clientWeak.lock();
-              if (!client) {
-                remotePtr->Close();
-                return;
-              }
-              *(client->GetData<bool>()) = true;
-
-              // close both when either side closes
-              client->end.connect([clientPtr = client.get(), remoteWeak] {
-                clientPtr->Close();
-                if (auto remote = remoteWeak.lock()) {
-                  remote->Close();
-                }
-              });
-              remotePtr->end.connect([remotePtr, clientWeak] {
-                remotePtr->Close();
-                if (auto client = clientWeak.lock()) {
-                  client->Close();
-                }
-              });
-
-              // copy bidirectionally
-              client->StartRead();
-              remotePtr->StartRead();
-              CopyStream(*client, remoteWeak);
-              CopyStream(*remotePtr, clientWeak);
-            });
-          },
-          host, fmt::to_string(remotePort));
-
-      // time out for connection
-      uv::Timer::SingleShot(loop, uv::Timer::Time{500},
-                            [connectedWeak = std::weak_ptr<bool>(connected),
-                             clientWeak = std::weak_ptr<uv::Tcp>(client),
-                             remoteWeak = std::weak_ptr<uv::Tcp>(remote)] {
-                              if (auto connected = connectedWeak.lock()) {
-                                if (!*connected) {
-                                  if (auto client = clientWeak.lock()) {
-                                    client->Close();
-                                  }
-                                  if (auto remote = remoteWeak.lock()) {
-                                    remote->Close();
-                                  }
-                                }
-                              }
-                            });
-    });
-
-    // start listening for incoming connections
-    server->Listen();
-
-    m_impl->servers[port] = server;
-  });
-}
-
-void PortForwarder::Remove(unsigned int port) {
-  m_impl->runner.ExecSync([&](uv::Loop& loop) {
-    if (auto server = m_impl->servers.lookup(port).lock()) {
-      server->Close();
-      m_impl->servers.erase(port);
-    }
-  });
-}
diff --git a/wpiutil/src/main/native/cpp/SafeThread.cpp b/wpiutil/src/main/native/cpp/SafeThread.cpp
index bbecc5c..ba1eba3 100644
--- a/wpiutil/src/main/native/cpp/SafeThread.cpp
+++ b/wpiutil/src/main/native/cpp/SafeThread.cpp
@@ -4,10 +4,50 @@
 
 #include "wpi/SafeThread.h"
 
+#include <atomic>
+
 using namespace wpi;
 
+// thread start/stop notifications for bindings that need to set up
+// per-thread state
+
+static void* DefaultOnThreadStart() {
+  return nullptr;
+}
+static void DefaultOnThreadEnd(void*) {}
+
+using OnThreadStartFn = void* (*)();
+using OnThreadEndFn = void (*)(void*);
+static std::atomic<int> gSafeThreadRefcount;
+static std::atomic<OnThreadStartFn> gOnSafeThreadStart{DefaultOnThreadStart};
+static std::atomic<OnThreadEndFn> gOnSafeThreadEnd{DefaultOnThreadEnd};
+
+namespace wpi::impl {
+void SetSafeThreadNotifiers(OnThreadStartFn OnStart, OnThreadEndFn OnEnd) {
+  if (gSafeThreadRefcount != 0) {
+    throw std::runtime_error(
+        "cannot set notifier while safe threads are running");
+  }
+  // Note: there's a race here, but if you're not calling this function on
+  // the main thread before you start anything else, you're using this function
+  // incorrectly
+  gOnSafeThreadStart = OnStart ? OnStart : DefaultOnThreadStart;
+  gOnSafeThreadEnd = OnEnd ? OnEnd : DefaultOnThreadEnd;
+}
+}  // namespace wpi::impl
+
+void SafeThread::Stop() {
+  m_active = false;
+  m_cond.notify_all();
+}
+
+void SafeThreadEvent::Stop() {
+  m_active = false;
+  m_stopEvent.Set();
+}
+
 detail::SafeThreadProxyBase::SafeThreadProxyBase(
-    std::shared_ptr<SafeThread> thr)
+    std::shared_ptr<SafeThreadBase> thr)
     : m_thread(std::move(thr)) {
   if (!m_thread) {
     return;
@@ -28,12 +68,18 @@
   }
 }
 
-void detail::SafeThreadOwnerBase::Start(std::shared_ptr<SafeThread> thr) {
+void detail::SafeThreadOwnerBase::Start(std::shared_ptr<SafeThreadBase> thr) {
   std::scoped_lock lock(m_mutex);
   if (auto thr = m_thread.lock()) {
     return;
   }
-  m_stdThread = std::thread([=] { thr->Main(); });
+  m_stdThread = std::thread([=] {
+    gSafeThreadRefcount++;
+    void* opaque = (gOnSafeThreadStart.load())();
+    thr->Main();
+    (gOnSafeThreadEnd.load())(opaque);
+    gSafeThreadRefcount--;
+  });
   thr->m_threadId = m_stdThread.get_id();
   m_thread = thr;
 }
@@ -41,8 +87,7 @@
 void detail::SafeThreadOwnerBase::Stop() {
   std::scoped_lock lock(m_mutex);
   if (auto thr = m_thread.lock()) {
-    thr->m_active = false;
-    thr->m_cond.notify_all();
+    thr->Stop();
     m_thread.reset();
   }
   if (m_stdThread.joinable()) {
@@ -56,8 +101,7 @@
     auto stdThread = std::move(m_stdThread);
     m_thread.reset();
     lock.unlock();
-    thr->m_active = false;
-    thr->m_cond.notify_all();
+    thr->Stop();
     stdThread.join();
   } else if (m_stdThread.joinable()) {
     m_stdThread.detach();
@@ -85,8 +129,8 @@
   return m_stdThread.native_handle();
 }
 
-std::shared_ptr<SafeThread> detail::SafeThreadOwnerBase::GetThreadSharedPtr()
-    const {
+std::shared_ptr<SafeThreadBase>
+detail::SafeThreadOwnerBase::GetThreadSharedPtr() const {
   std::scoped_lock lock(m_mutex);
   return m_thread.lock();
 }
diff --git a/wpiutil/src/main/native/cpp/SocketError.cpp b/wpiutil/src/main/native/cpp/SocketError.cpp
deleted file mode 100644
index 3f08d1e..0000000
--- a/wpiutil/src/main/native/cpp/SocketError.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/SocketError.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#else
-#include <cerrno>
-#include <cstring>
-#endif
-
-namespace wpi {
-
-int SocketErrno() {
-#ifdef _WIN32
-  return WSAGetLastError();
-#else
-  return errno;
-#endif
-}
-
-std::string SocketStrerror(int code) {
-#ifdef _WIN32
-  LPSTR errstr = nullptr;
-  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0,
-                code, 0, (LPSTR)&errstr, 0, 0);
-  std::string rv(errstr);
-  LocalFree(errstr);
-  return rv;
-#else
-  return std::strerror(code);
-#endif
-}
-
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/cpp/Synchronization.cpp b/wpiutil/src/main/native/cpp/Synchronization.cpp
index da97897..f9ac75b 100644
--- a/wpiutil/src/main/native/cpp/Synchronization.cpp
+++ b/wpiutil/src/main/native/cpp/Synchronization.cpp
@@ -5,6 +5,7 @@
 #include "wpi/Synchronization.h"
 
 #include <algorithm>
+#include <atomic>
 #include <cstring>
 #include <mutex>
 
@@ -16,6 +17,8 @@
 
 using namespace wpi;
 
+static std::atomic_bool gShutdown{false};
+
 namespace {
 
 struct State {
@@ -25,6 +28,8 @@
 };
 
 struct HandleManager {
+  ~HandleManager() { gShutdown = true; }
+
   wpi::mutex mutex;
   wpi::UidVector<int, 8> eventIds;
   wpi::UidVector<int, 8> semaphoreIds;
@@ -40,6 +45,9 @@
 
 WPI_EventHandle wpi::CreateEvent(bool manualReset, bool initialState) {
   auto& manager = GetManager();
+  if (gShutdown) {
+    return {};
+  }
   std::scoped_lock lock{manager.mutex};
 
   auto index = manager.eventIds.emplace_back(0);
@@ -61,6 +69,9 @@
   DestroySignalObject(handle);
 
   auto& manager = GetManager();
+  if (gShutdown) {
+    return;
+  }
   std::scoped_lock lock{manager.mutex};
   manager.eventIds.erase(handle & 0xffffff);
 }
@@ -83,6 +94,9 @@
 
 WPI_SemaphoreHandle wpi::CreateSemaphore(int initialCount, int maximumCount) {
   auto& manager = GetManager();
+  if (gShutdown) {
+    return {};
+  }
   std::scoped_lock lock{manager.mutex};
 
   auto index = manager.semaphoreIds.emplace_back(maximumCount);
@@ -104,6 +118,9 @@
   DestroySignalObject(handle);
 
   auto& manager = GetManager();
+  if (gShutdown) {
+    return;
+  }
   std::scoped_lock lock{manager.mutex};
   manager.eventIds.erase(handle & 0xffffff);
 }
@@ -119,6 +136,9 @@
   int index = handle & 0xffffff;
 
   auto& manager = GetManager();
+  if (gShutdown) {
+    return true;
+  }
   std::scoped_lock lock{manager.mutex};
   auto it = manager.states.find(handle);
   if (it == manager.states.end()) {
@@ -146,22 +166,26 @@
 bool wpi::WaitForObject(WPI_Handle handle, double timeout, bool* timedOut) {
   WPI_Handle signaledValue;
   auto signaled = WaitForObjects(
-      wpi::span(&handle, 1), wpi::span(&signaledValue, 1), timeout, timedOut);
+      std::span(&handle, 1), std::span(&signaledValue, 1), timeout, timedOut);
   if (signaled.empty()) {
     return false;
   }
   return (signaled[0] & 0x80000000ul) == 0;
 }
 
-wpi::span<WPI_Handle> wpi::WaitForObjects(wpi::span<const WPI_Handle> handles,
-                                          wpi::span<WPI_Handle> signaled) {
+std::span<WPI_Handle> wpi::WaitForObjects(std::span<const WPI_Handle> handles,
+                                          std::span<WPI_Handle> signaled) {
   return WaitForObjects(handles, signaled, -1, nullptr);
 }
 
-wpi::span<WPI_Handle> wpi::WaitForObjects(wpi::span<const WPI_Handle> handles,
-                                          wpi::span<WPI_Handle> signaled,
+std::span<WPI_Handle> wpi::WaitForObjects(std::span<const WPI_Handle> handles,
+                                          std::span<WPI_Handle> signaled,
                                           double timeout, bool* timedOut) {
   auto& manager = GetManager();
+  if (gShutdown) {
+    *timedOut = false;
+    return {};
+  }
   std::unique_lock lock{manager.mutex};
   wpi::condition_variable cv;
   bool addedWaiters = false;
@@ -240,6 +264,9 @@
 void wpi::CreateSignalObject(WPI_Handle handle, bool manualReset,
                              bool initialState) {
   auto& manager = GetManager();
+  if (gShutdown) {
+    return;
+  }
   std::scoped_lock lock{manager.mutex};
   auto& state = manager.states[handle];
   state.signaled = initialState ? 1 : 0;
@@ -248,6 +275,9 @@
 
 void wpi::SetSignalObject(WPI_Handle handle) {
   auto& manager = GetManager();
+  if (gShutdown) {
+    return;
+  }
   std::scoped_lock lock{manager.mutex};
   auto it = manager.states.find(handle);
   if (it == manager.states.end()) {
@@ -266,6 +296,9 @@
 
 void wpi::ResetSignalObject(WPI_Handle handle) {
   auto& manager = GetManager();
+  if (gShutdown) {
+    return;
+  }
   std::scoped_lock lock{manager.mutex};
   auto it = manager.states.find(handle);
   if (it != manager.states.end()) {
@@ -275,6 +308,9 @@
 
 void wpi::DestroySignalObject(WPI_Handle handle) {
   auto& manager = GetManager();
+  if (gShutdown) {
+    return;
+  }
   std::scoped_lock lock{manager.mutex};
 
   auto it = manager.states.find(handle);
@@ -332,8 +368,8 @@
 
 int WPI_WaitForObjects(const WPI_Handle* handles, int handles_count,
                        WPI_Handle* signaled) {
-  return wpi::WaitForObjects(wpi::span(handles, handles_count),
-                             wpi::span(signaled, handles_count))
+  return wpi::WaitForObjects(std::span(handles, handles_count),
+                             std::span(signaled, handles_count))
       .size();
 }
 
@@ -341,8 +377,8 @@
                               WPI_Handle* signaled, double timeout,
                               int* timed_out) {
   bool timedOutBool;
-  auto signaledResult = wpi::WaitForObjects(wpi::span(handles, handles_count),
-                                            wpi::span(signaled, handles_count),
+  auto signaledResult = wpi::WaitForObjects(std::span(handles, handles_count),
+                                            std::span(signaled, handles_count),
                                             timeout, &timedOutBool);
   *timed_out = timedOutBool ? 1 : 0;
   return signaledResult.size();
diff --git a/wpiutil/src/main/native/cpp/TCPAcceptor.cpp b/wpiutil/src/main/native/cpp/TCPAcceptor.cpp
deleted file mode 100644
index 8d12ac3..0000000
--- a/wpiutil/src/main/native/cpp/TCPAcceptor.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
-   TCPAcceptor.cpp
-
-   TCPAcceptor class definition. TCPAcceptor provides methods to passively
-   establish TCP/IP connections with clients.
-
-   ------------------------------------------
-
-   Copyright (c) 2013 [Vic Hargrave - http://vichargrave.com]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-#include "wpi/TCPAcceptor.h"
-
-#include <cstdio>
-#include <cstring>
-
-#ifdef _WIN32
-#define _WINSOCK_DEPRECATED_NO_WARNINGS
-#include <WinSock2.h>
-#include <Ws2tcpip.h>
-#pragma comment(lib, "Ws2_32.lib")
-#else
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#endif
-
-#include "wpi/Logger.h"
-#include "wpi/SmallString.h"
-#include "wpi/SocketError.h"
-
-using namespace wpi;
-
-TCPAcceptor::TCPAcceptor(int port, std::string_view address, Logger& logger)
-    : m_lsd(0),
-      m_port(port),
-      m_address(address),
-      m_listening(false),
-      m_logger(logger) {
-  m_shutdown = false;
-#ifdef _WIN32
-  WSAData wsaData;
-  WORD wVersionRequested = MAKEWORD(2, 2);
-  (void)WSAStartup(wVersionRequested, &wsaData);
-#endif
-}
-
-TCPAcceptor::~TCPAcceptor() {
-  if (m_lsd > 0) {
-    shutdown();
-#ifdef _WIN32
-    closesocket(m_lsd);
-#else
-    close(m_lsd);
-#endif
-  }
-#ifdef _WIN32
-  WSACleanup();
-#endif
-}
-
-int TCPAcceptor::start() {
-  if (m_listening) {
-    return 0;
-  }
-
-  m_lsd = socket(PF_INET, SOCK_STREAM, 0);
-  if (m_lsd < 0) {
-    WPI_ERROR(m_logger, "{}", "could not create socket");
-    return -1;
-  }
-  struct sockaddr_in address;
-
-  std::memset(&address, 0, sizeof(address));
-  address.sin_family = PF_INET;
-  if (m_address.size() > 0) {
-#ifdef _WIN32
-    SmallString<128> addr_copy(m_address);
-    addr_copy.push_back('\0');
-    int res = InetPton(PF_INET, addr_copy.data(), &(address.sin_addr));
-#else
-    int res = inet_pton(PF_INET, m_address.c_str(), &(address.sin_addr));
-#endif
-    if (res != 1) {
-      WPI_ERROR(m_logger, "could not resolve {} address", m_address);
-      return -1;
-    }
-  } else {
-    address.sin_addr.s_addr = INADDR_ANY;
-  }
-  address.sin_port = htons(m_port);
-
-#ifdef _WIN32
-  int optval = 1;
-  setsockopt(m_lsd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
-             reinterpret_cast<char*>(&optval), sizeof optval);
-#else
-  int optval = 1;
-  setsockopt(m_lsd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&optval),
-             sizeof optval);
-#endif
-
-  int result = bind(m_lsd, reinterpret_cast<struct sockaddr*>(&address),
-                    sizeof(address));
-  if (result != 0) {
-    WPI_ERROR(m_logger, "bind() to port {} failed: {}", m_port,
-              SocketStrerror());
-    return result;
-  }
-
-  result = listen(m_lsd, 5);
-  if (result != 0) {
-    WPI_ERROR(m_logger, "listen() on port {} failed: {}", m_port,
-              SocketStrerror());
-    return result;
-  }
-  m_listening = true;
-  return result;
-}
-
-void TCPAcceptor::shutdown() {
-  m_shutdown = true;
-#ifdef _WIN32
-  ::shutdown(m_lsd, SD_BOTH);
-
-  // this is ugly, but the easiest way to do this
-  // force wakeup of accept() with a non-blocking connect to ourselves
-  struct sockaddr_in address;
-
-  std::memset(&address, 0, sizeof(address));
-  address.sin_family = PF_INET;
-  SmallString<128> addr_copy;
-  if (m_address.size() > 0)
-    addr_copy = m_address;
-  else
-    addr_copy = "127.0.0.1";
-  addr_copy.push_back('\0');
-  int size = sizeof(address);
-  if (WSAStringToAddress(addr_copy.data(), PF_INET, nullptr,
-                         (struct sockaddr*)&address, &size) != 0)
-    return;
-  address.sin_port = htons(m_port);
-
-  int result = -1, sd = socket(AF_INET, SOCK_STREAM, 0);
-  if (sd < 0)
-    return;
-
-  // Set socket to non-blocking
-  u_long mode = 1;
-  ioctlsocket(sd, FIONBIO, &mode);
-
-  // Try to connect
-  ::connect(sd, (struct sockaddr*)&address, sizeof(address));
-
-  // Close
-  ::closesocket(sd);
-
-#else
-  ::shutdown(m_lsd, SHUT_RDWR);
-  int nullfd = ::open("/dev/null", O_RDONLY);
-  if (nullfd >= 0) {
-    ::dup2(nullfd, m_lsd);
-    ::close(nullfd);
-  }
-#endif
-}
-
-std::unique_ptr<NetworkStream> TCPAcceptor::accept() {
-  if (!m_listening || m_shutdown) {
-    return nullptr;
-  }
-
-  struct sockaddr_in address;
-#ifdef _WIN32
-  int len = sizeof(address);
-#else
-  socklen_t len = sizeof(address);
-#endif
-  std::memset(&address, 0, sizeof(address));
-  int sd = ::accept(m_lsd, reinterpret_cast<struct sockaddr*>(&address), &len);
-  if (sd < 0) {
-    if (!m_shutdown) {
-      WPI_ERROR(m_logger, "accept() on port {} failed: {}", m_port,
-                SocketStrerror());
-    }
-    return nullptr;
-  }
-  if (m_shutdown) {
-#ifdef _WIN32
-    closesocket(sd);
-#else
-    close(sd);
-#endif
-    return nullptr;
-  }
-  return std::unique_ptr<NetworkStream>(new TCPStream(sd, &address));
-}
diff --git a/wpiutil/src/main/native/cpp/TCPConnector.cpp b/wpiutil/src/main/native/cpp/TCPConnector.cpp
deleted file mode 100644
index ed97962..0000000
--- a/wpiutil/src/main/native/cpp/TCPConnector.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
-   TCPConnector.h
-
-   TCPConnector class definition. TCPConnector provides methods to actively
-   establish TCP/IP connections with a server.
-
-   ------------------------------------------
-
-   Copyright (c) 2013 [Vic Hargrave - http://vichargrave.com]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License
-*/
-
-#include "wpi/TCPConnector.h"
-
-#include <fcntl.h>
-
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-
-#ifdef _WIN32
-#include <WS2tcpip.h>
-#include <WinSock2.h>
-#else
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/select.h>
-#include <unistd.h>
-#endif
-
-#include "wpi/Logger.h"
-#include "wpi/SmallString.h"
-#include "wpi/SocketError.h"
-#include "wpi/TCPStream.h"
-
-using namespace wpi;
-
-static int ResolveHostName(const char* hostname, struct in_addr* addr) {
-  struct addrinfo hints;
-  struct addrinfo* res;
-
-  hints.ai_flags = 0;
-  hints.ai_family = AF_INET;
-  hints.ai_socktype = SOCK_STREAM;
-  hints.ai_protocol = 0;
-  hints.ai_addrlen = 0;
-  hints.ai_addr = nullptr;
-  hints.ai_canonname = nullptr;
-  hints.ai_next = nullptr;
-  int result = getaddrinfo(hostname, nullptr, &hints, &res);
-  if (result == 0) {
-    std::memcpy(
-        addr, &(reinterpret_cast<struct sockaddr_in*>(res->ai_addr)->sin_addr),
-        sizeof(struct in_addr));
-    freeaddrinfo(res);
-  }
-  return result;
-}
-
-std::unique_ptr<NetworkStream> TCPConnector::connect(const char* server,
-                                                     int port, Logger& logger,
-                                                     int timeout) {
-#ifdef _WIN32
-  struct WSAHelper {
-    WSAHelper() {
-      WSAData wsaData;
-      WORD wVersionRequested = MAKEWORD(2, 2);
-      WSAStartup(wVersionRequested, &wsaData);
-    }
-    ~WSAHelper() { WSACleanup(); }
-  };
-  static WSAHelper helper;
-#endif
-  struct sockaddr_in address;
-
-  std::memset(&address, 0, sizeof(address));
-  address.sin_family = AF_INET;
-  if (ResolveHostName(server, &(address.sin_addr)) != 0) {
-#ifdef _WIN32
-    SmallString<128> addr_copy(server);
-    addr_copy.push_back('\0');
-    int res = InetPton(PF_INET, addr_copy.data(), &(address.sin_addr));
-#else
-    int res = inet_pton(PF_INET, server, &(address.sin_addr));
-#endif
-    if (res != 1) {
-      WPI_ERROR(logger, "could not resolve {} address", server);
-      return nullptr;
-    }
-  }
-  address.sin_port = htons(port);
-
-  if (timeout == 0) {
-    int sd = socket(AF_INET, SOCK_STREAM, 0);
-    if (sd < 0) {
-      WPI_ERROR(logger, "{}", "could not create socket");
-      return nullptr;
-    }
-    if (::connect(sd, reinterpret_cast<struct sockaddr*>(&address),
-                  sizeof(address)) != 0) {
-      WPI_ERROR(logger, "connect() to {} port {} failed: {}", server, port,
-                SocketStrerror());
-#ifdef _WIN32
-      closesocket(sd);
-#else
-      ::close(sd);
-#endif
-      return nullptr;
-    }
-    return std::unique_ptr<NetworkStream>(new TCPStream(sd, &address));
-  }
-
-  fd_set sdset;
-  struct timeval tv;
-  socklen_t len;
-  int result = -1, valopt, sd = socket(AF_INET, SOCK_STREAM, 0);
-  if (sd < 0) {
-    WPI_ERROR(logger, "{}", "could not create socket");
-    return nullptr;
-  }
-
-// Set socket to non-blocking
-#ifdef _WIN32
-  u_long mode = 1;
-  if (ioctlsocket(sd, FIONBIO, &mode) == SOCKET_ERROR)
-    WPI_WARNING(logger, "could not set socket to non-blocking: {}",
-                SocketStrerror());
-#else
-  int arg;
-  arg = fcntl(sd, F_GETFL, nullptr);
-  if (arg < 0) {
-    WPI_WARNING(logger, "could not set socket to non-blocking: {}",
-                SocketStrerror());
-  } else {
-    arg |= O_NONBLOCK;
-    if (fcntl(sd, F_SETFL, arg) < 0) {
-      WPI_WARNING(logger, "could not set socket to non-blocking: {}",
-                  SocketStrerror());
-    }
-  }
-#endif
-
-  // Connect with time limit
-  if ((result = ::connect(sd, reinterpret_cast<struct sockaddr*>(&address),
-                          sizeof(address))) < 0) {
-    int my_errno = SocketErrno();
-#ifdef _WIN32
-    if (my_errno == WSAEWOULDBLOCK || my_errno == WSAEINPROGRESS) {
-#else
-    if (my_errno == EWOULDBLOCK || my_errno == EINPROGRESS) {
-#endif
-      tv.tv_sec = timeout;
-      tv.tv_usec = 0;
-      FD_ZERO(&sdset);
-      FD_SET(sd, &sdset);
-      if (select(sd + 1, nullptr, &sdset, nullptr, &tv) > 0) {
-        len = sizeof(int);
-        getsockopt(sd, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&valopt),
-                   &len);
-        if (valopt) {
-          WPI_ERROR(logger, "select() to {} port {} error {} - {}", server,
-                    port, valopt, SocketStrerror(valopt));
-        } else {
-          // connection established
-          result = 0;
-        }
-      } else {
-        WPI_INFO(logger, "connect() to {} port {} timed out", server, port);
-      }
-    } else {
-      WPI_ERROR(logger, "connect() to {} port {} error {} - {}", server, port,
-                SocketErrno(), SocketStrerror());
-    }
-  }
-
-// Return socket to blocking mode
-#ifdef _WIN32
-  mode = 0;
-  if (ioctlsocket(sd, FIONBIO, &mode) == SOCKET_ERROR)
-    WPI_WARNING(logger, "could not set socket to blocking: {}",
-                SocketStrerror());
-#else
-  arg = fcntl(sd, F_GETFL, nullptr);
-  if (arg < 0) {
-    WPI_WARNING(logger, "could not set socket to blocking: {}",
-                SocketStrerror());
-  } else {
-    arg &= (~O_NONBLOCK);
-    if (fcntl(sd, F_SETFL, arg) < 0) {
-      WPI_WARNING(logger, "could not set socket to blocking: {}",
-                  SocketStrerror());
-    }
-  }
-#endif
-
-  // Create stream object if connected, close if not.
-  if (result == -1) {
-#ifdef _WIN32
-    closesocket(sd);
-#else
-    ::close(sd);
-#endif
-    return nullptr;
-  }
-  return std::unique_ptr<NetworkStream>(new TCPStream(sd, &address));
-}
diff --git a/wpiutil/src/main/native/cpp/TCPConnector_parallel.cpp b/wpiutil/src/main/native/cpp/TCPConnector_parallel.cpp
deleted file mode 100644
index 26258cf..0000000
--- a/wpiutil/src/main/native/cpp/TCPConnector_parallel.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/TCPConnector.h"  // NOLINT(build/include_order)
-
-#include <atomic>
-#include <chrono>
-#include <thread>
-#include <tuple>
-
-#include "wpi/SmallSet.h"
-#include "wpi/condition_variable.h"
-#include "wpi/mutex.h"
-
-using namespace wpi;
-
-// MSVC < 1900 doesn't have support for thread_local
-#if !defined(_MSC_VER) || _MSC_VER >= 1900
-// clang check for availability of thread_local
-#if !defined(__has_feature) || __has_feature(cxx_thread_local)
-#define HAVE_THREAD_LOCAL
-#endif
-#endif
-
-std::unique_ptr<NetworkStream> TCPConnector::connect_parallel(
-    span<const std::pair<const char*, int>> servers, Logger& logger,
-    int timeout) {
-  if (servers.empty()) {
-    return nullptr;
-  }
-
-  // structure to make sure we don't start duplicate workers
-  struct GlobalState {
-    wpi::mutex mtx;
-#ifdef HAVE_THREAD_LOCAL
-    SmallSet<std::pair<std::string, int>, 16> active;
-#else
-    SmallSet<std::tuple<std::thread::id, std::string, int>, 16> active;
-#endif
-  };
-#ifdef HAVE_THREAD_LOCAL
-  thread_local auto global = std::make_shared<GlobalState>();
-#else
-  static auto global = std::make_shared<GlobalState>();
-  auto this_id = std::this_thread::get_id();
-#endif
-  auto local = global;  // copy to an automatic variable for lambda capture
-
-  // structure shared between threads and this function
-  struct Result {
-    wpi::mutex mtx;
-    wpi::condition_variable cv;
-    std::unique_ptr<NetworkStream> stream;
-    std::atomic<unsigned int> count{0};
-    std::atomic<bool> done{false};
-  };
-  auto result = std::make_shared<Result>();
-
-  // start worker threads; this is I/O bound so we don't limit to # of procs
-  Logger* plogger = &logger;
-  unsigned int num_workers = 0;
-  for (const auto& server : servers) {
-    std::pair<std::string, int> server_copy{std::string{server.first},
-                                            server.second};
-#ifdef HAVE_THREAD_LOCAL
-    const auto& active_tracker = server_copy;
-#else
-    std::tuple<std::thread::id, std::string, int> active_tracker{
-        this_id, server_copy.first, server_copy.second};
-#endif
-
-    // don't start a new worker if we had a previously still-active connection
-    // attempt to the same server
-    {
-      std::scoped_lock lock(local->mtx);
-      if (local->active.count(active_tracker) > 0) {
-        continue;  // already in set
-      }
-    }
-
-    ++num_workers;
-
-    // start the worker
-    std::thread([=] {
-      if (!result->done) {
-        // add to global state
-        {
-          std::scoped_lock lock(local->mtx);
-          local->active.insert(active_tracker);
-        }
-
-        // try to connect
-        auto stream = connect(server_copy.first.c_str(), server_copy.second,
-                              *plogger, timeout);
-
-        // remove from global state
-        {
-          std::scoped_lock lock(local->mtx);
-          local->active.erase(active_tracker);
-        }
-
-        // successful connection
-        if (stream) {
-          std::scoped_lock lock(result->mtx);
-          if (!result->done.exchange(true)) {
-            result->stream = std::move(stream);
-          }
-        }
-      }
-      ++result->count;
-      result->cv.notify_all();
-    }).detach();
-  }
-
-  // wait for a result, timeout, or all finished
-  std::unique_lock lock(result->mtx);
-  if (timeout == 0) {
-    result->cv.wait(
-        lock, [&] { return result->stream || result->count >= num_workers; });
-  } else {
-    auto timeout_time =
-        std::chrono::steady_clock::now() + std::chrono::seconds(timeout);
-    result->cv.wait_until(lock, timeout_time, [&] {
-      return result->stream || result->count >= num_workers;
-    });
-  }
-
-  // no need to wait for remaining worker threads; shared_ptr will clean up
-  return std::move(result->stream);
-}
diff --git a/wpiutil/src/main/native/cpp/TCPStream.cpp b/wpiutil/src/main/native/cpp/TCPStream.cpp
deleted file mode 100644
index 4567161..0000000
--- a/wpiutil/src/main/native/cpp/TCPStream.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
-   TCPStream.h
-
-   TCPStream class definition. TCPStream provides methods to transfer
-   data between peers over a TCP/IP connection.
-
-   ------------------------------------------
-
-   Copyright (c) 2013 [Vic Hargrave - http://vichargrave.com]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-#include "wpi/TCPStream.h"
-
-#include <fcntl.h>
-
-#ifdef _WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#else
-#include <arpa/inet.h>
-#include <netinet/tcp.h>
-#include <unistd.h>
-#endif
-
-#include <cerrno>
-
-using namespace wpi;
-
-TCPStream::TCPStream(int sd, sockaddr_in* address)
-    : m_sd(sd), m_blocking(true) {
-  char ip[50];
-#ifdef _WIN32
-  InetNtop(PF_INET, &(address->sin_addr.s_addr), ip, sizeof(ip) - 1);
-#else
-  inet_ntop(PF_INET, reinterpret_cast<in_addr*>(&(address->sin_addr.s_addr)),
-            ip, sizeof(ip) - 1);
-#ifdef SO_NOSIGPIPE
-  // disable SIGPIPE on Mac OS X
-  int set = 1;
-  setsockopt(m_sd, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&set),
-             sizeof set);
-#endif
-#endif
-  m_peerIP = ip;
-  m_peerPort = ntohs(address->sin_port);
-}
-
-TCPStream::~TCPStream() {
-  close();
-}
-
-size_t TCPStream::send(const char* buffer, size_t len, Error* err) {
-  if (m_sd < 0) {
-    *err = kConnectionClosed;
-    return 0;
-  }
-#ifdef _WIN32
-  WSABUF wsaBuf;
-  wsaBuf.buf = const_cast<char*>(buffer);
-  wsaBuf.len = (ULONG)len;
-  DWORD rv;
-  bool result = true;
-  while (WSASend(m_sd, &wsaBuf, 1, &rv, 0, nullptr, nullptr) == SOCKET_ERROR) {
-    if (WSAGetLastError() != WSAEWOULDBLOCK) {
-      result = false;
-      break;
-    }
-    if (!m_blocking) {
-      *err = kWouldBlock;
-      return 0;
-    }
-    Sleep(1);
-  }
-  if (!result) {
-    char Buffer[128];
-#ifdef _MSC_VER
-    sprintf_s(Buffer, "Send() failed: WSA error=%d\n", WSAGetLastError());
-#else
-    std::snprintf(Buffer, sizeof(Buffer), "Send() failed: WSA error=%d\n",
-                  WSAGetLastError());
-#endif
-    OutputDebugStringA(Buffer);
-    *err = kConnectionReset;
-    return 0;
-  }
-#else
-#ifdef MSG_NOSIGNAL
-  // disable SIGPIPE on Linux
-  ssize_t rv = ::send(m_sd, buffer, len, MSG_NOSIGNAL);
-#else
-  ssize_t rv = ::send(m_sd, buffer, len, 0);
-#endif
-  if (rv < 0) {
-    if (!m_blocking && (errno == EAGAIN || errno == EWOULDBLOCK)) {
-      *err = kWouldBlock;
-    } else {
-      *err = kConnectionReset;
-    }
-    return 0;
-  }
-#endif
-  return static_cast<size_t>(rv);
-}
-
-size_t TCPStream::receive(char* buffer, size_t len, Error* err, int timeout) {
-  if (m_sd < 0) {
-    *err = kConnectionClosed;
-    return 0;
-  }
-#ifdef _WIN32
-  int rv;
-#else
-  ssize_t rv;
-#endif
-  if (timeout <= 0) {
-#ifdef _WIN32
-    rv = recv(m_sd, buffer, len, 0);
-#else
-    rv = read(m_sd, buffer, len);
-#endif
-  } else if (WaitForReadEvent(timeout)) {
-#ifdef _WIN32
-    rv = recv(m_sd, buffer, len, 0);
-#else
-    rv = read(m_sd, buffer, len);
-#endif
-  } else {
-    *err = kConnectionTimedOut;
-    return 0;
-  }
-  if (rv < 0) {
-#ifdef _WIN32
-    if (!m_blocking && WSAGetLastError() == WSAEWOULDBLOCK) {
-#else
-    if (!m_blocking && (errno == EAGAIN || errno == EWOULDBLOCK)) {
-#endif
-      *err = kWouldBlock;
-    } else {
-      *err = kConnectionReset;
-    }
-    return 0;
-  }
-  return static_cast<size_t>(rv);
-}
-
-void TCPStream::close() {
-  if (m_sd >= 0) {
-#ifdef _WIN32
-    ::shutdown(m_sd, SD_BOTH);
-    closesocket(m_sd);
-#else
-    ::shutdown(m_sd, SHUT_RDWR);
-    ::close(m_sd);
-#endif
-  }
-  m_sd = -1;
-}
-
-std::string_view TCPStream::getPeerIP() const {
-  return m_peerIP;
-}
-
-int TCPStream::getPeerPort() const {
-  return m_peerPort;
-}
-
-void TCPStream::setNoDelay() {
-  if (m_sd < 0) {
-    return;
-  }
-  int optval = 1;
-  setsockopt(m_sd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&optval),
-             sizeof optval);
-}
-
-bool TCPStream::setBlocking(bool enabled) {
-  if (m_sd < 0) {
-    return true;  // silently accept
-  }
-#ifdef _WIN32
-  u_long mode = enabled ? 0 : 1;
-  if (ioctlsocket(m_sd, FIONBIO, &mode) == SOCKET_ERROR) {
-    return false;
-  }
-#else
-  int flags = fcntl(m_sd, F_GETFL, nullptr);
-  if (flags < 0) {
-    return false;
-  }
-  if (enabled) {
-    flags &= ~O_NONBLOCK;
-  } else {
-    flags |= O_NONBLOCK;
-  }
-  if (fcntl(m_sd, F_SETFL, flags) < 0) {
-    return false;
-  }
-#endif
-  return true;
-}
-
-int TCPStream::getNativeHandle() const {
-  return m_sd;
-}
-
-bool TCPStream::WaitForReadEvent(int timeout) {
-  fd_set sdset;
-  struct timeval tv;
-
-  tv.tv_sec = timeout;
-  tv.tv_usec = 0;
-  FD_ZERO(&sdset);
-  FD_SET(m_sd, &sdset);
-  if (select(m_sd + 1, &sdset, nullptr, nullptr, &tv) > 0) {
-    return true;
-  }
-  return false;
-}
diff --git a/wpiutil/src/main/native/cpp/UDPClient.cpp b/wpiutil/src/main/native/cpp/UDPClient.cpp
deleted file mode 100644
index 108ef54..0000000
--- a/wpiutil/src/main/native/cpp/UDPClient.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/UDPClient.h"
-
-#ifdef _WIN32
-#include <WinSock2.h>
-#include <Ws2tcpip.h>
-#pragma comment(lib, "Ws2_32.lib")
-#else
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#endif
-
-#include "wpi/Logger.h"
-#include "wpi/SmallString.h"
-#include "wpi/SocketError.h"
-
-using namespace wpi;
-
-UDPClient::UDPClient(Logger& logger) : UDPClient("", logger) {}
-
-UDPClient::UDPClient(std::string_view address, Logger& logger)
-    : m_lsd(0), m_port(0), m_address(address), m_logger(logger) {}
-
-UDPClient::UDPClient(UDPClient&& other)
-    : m_lsd(other.m_lsd),
-      m_port(other.m_port),
-      m_address(std::move(other.m_address)),
-      m_logger(other.m_logger) {
-  other.m_lsd = 0;
-  other.m_port = 0;
-}
-
-UDPClient::~UDPClient() {
-  if (m_lsd > 0) {
-    shutdown();
-  }
-}
-
-UDPClient& UDPClient::operator=(UDPClient&& other) {
-  if (this == &other) {
-    return *this;
-  }
-  shutdown();
-  m_logger = other.m_logger;
-  m_lsd = other.m_lsd;
-  m_address = std::move(other.m_address);
-  m_port = other.m_port;
-  other.m_lsd = 0;
-  other.m_port = 0;
-  return *this;
-}
-
-int UDPClient::start() {
-  return start(0);
-}
-
-int UDPClient::start(int port) {
-  if (m_lsd > 0) {
-    return 0;
-  }
-
-#ifdef _WIN32
-  WSAData wsaData;
-  WORD wVersionRequested = MAKEWORD(2, 2);
-  WSAStartup(wVersionRequested, &wsaData);
-#endif
-
-  m_lsd = socket(AF_INET, SOCK_DGRAM, 0);
-
-  if (m_lsd < 0) {
-    WPI_ERROR(m_logger, "{}", "could not create socket");
-    return -1;
-  }
-
-  struct sockaddr_in addr;
-  std::memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  if (m_address.size() > 0) {
-#ifdef _WIN32
-    SmallString<128> addr_copy(m_address);
-    addr_copy.push_back('\0');
-    int res = InetPton(PF_INET, addr_copy.data(), &(addr.sin_addr));
-#else
-    int res = inet_pton(PF_INET, m_address.c_str(), &(addr.sin_addr));
-#endif
-    if (res != 1) {
-      WPI_ERROR(m_logger, "could not resolve {} address", m_address);
-      return -1;
-    }
-  } else {
-    addr.sin_addr.s_addr = INADDR_ANY;
-  }
-  addr.sin_port = htons(port);
-
-  if (port != 0) {
-#ifdef _WIN32
-    int optval = 1;
-    setsockopt(m_lsd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
-               reinterpret_cast<char*>(&optval), sizeof optval);
-#else
-    int optval = 1;
-    setsockopt(m_lsd, SOL_SOCKET, SO_REUSEADDR,
-               reinterpret_cast<char*>(&optval), sizeof optval);
-#endif
-  }
-
-  int result = bind(m_lsd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
-  if (result != 0) {
-    WPI_ERROR(m_logger, "bind() failed: {}", SocketStrerror());
-    return result;
-  }
-  m_port = port;
-  return 0;
-}
-
-void UDPClient::shutdown() {
-  if (m_lsd > 0) {
-#ifdef _WIN32
-    ::shutdown(m_lsd, SD_BOTH);
-    closesocket(m_lsd);
-    WSACleanup();
-#else
-    ::shutdown(m_lsd, SHUT_RDWR);
-    close(m_lsd);
-#endif
-    m_lsd = 0;
-    m_port = 0;
-  }
-}
-
-int UDPClient::send(span<const uint8_t> data, std::string_view server,
-                    int port) {
-  // server must be a resolvable IP address
-  struct sockaddr_in addr;
-  std::memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  SmallString<128> remoteAddr{server};
-  if (remoteAddr.empty()) {
-    WPI_ERROR(m_logger, "{}", "server must be passed");
-    return -1;
-  }
-
-#ifdef _WIN32
-  int res = InetPton(AF_INET, remoteAddr.c_str(), &(addr.sin_addr));
-#else
-  int res = inet_pton(AF_INET, remoteAddr.c_str(), &(addr.sin_addr));
-#endif
-  if (res != 1) {
-    WPI_ERROR(m_logger, "could not resolve {} address", server);
-    return -1;
-  }
-  addr.sin_port = htons(port);
-
-  // sendto should not block
-  int result =
-      sendto(m_lsd, reinterpret_cast<const char*>(data.data()), data.size(), 0,
-             reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
-  return result;
-}
-
-int UDPClient::send(std::string_view data, std::string_view server, int port) {
-  // server must be a resolvable IP address
-  struct sockaddr_in addr;
-  std::memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  SmallString<128> remoteAddr{server};
-  if (remoteAddr.empty()) {
-    WPI_ERROR(m_logger, "{}", "server must be passed");
-    return -1;
-  }
-
-#ifdef _WIN32
-  int res = InetPton(AF_INET, remoteAddr.c_str(), &(addr.sin_addr));
-#else
-  int res = inet_pton(AF_INET, remoteAddr.c_str(), &(addr.sin_addr));
-#endif
-  if (res != 1) {
-    WPI_ERROR(m_logger, "could not resolve {} address", server);
-    return -1;
-  }
-  addr.sin_port = htons(port);
-
-  // sendto should not block
-  int result = sendto(m_lsd, data.data(), data.size(), 0,
-                      reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
-  return result;
-}
-
-int UDPClient::receive(uint8_t* data_received, int receive_len) {
-  if (m_port == 0) {
-    return -1;  // return if not receiving
-  }
-  return recv(m_lsd, reinterpret_cast<char*>(data_received), receive_len, 0);
-}
-
-int UDPClient::receive(uint8_t* data_received, int receive_len,
-                       SmallVectorImpl<char>* addr_received,
-                       int* port_received) {
-  if (m_port == 0) {
-    return -1;  // return if not receiving
-  }
-
-  struct sockaddr_in remote;
-  socklen_t remote_len = sizeof(remote);
-  std::memset(&remote, 0, sizeof(remote));
-
-  int result =
-      recvfrom(m_lsd, reinterpret_cast<char*>(data_received), receive_len, 0,
-               reinterpret_cast<sockaddr*>(&remote), &remote_len);
-
-  char ip[50];
-#ifdef _WIN32
-  InetNtop(PF_INET, &(remote.sin_addr.s_addr), ip, sizeof(ip) - 1);
-#else
-  inet_ntop(PF_INET, reinterpret_cast<in_addr*>(&(remote.sin_addr.s_addr)), ip,
-            sizeof(ip) - 1);
-#endif
-
-  ip[49] = '\0';
-  int addr_len = std::strlen(ip);
-  addr_received->clear();
-  addr_received->append(&ip[0], &ip[addr_len]);
-
-  *port_received = ntohs(remote.sin_port);
-
-  return result;
-}
-
-int UDPClient::set_timeout(double timeout) {
-  if (timeout < 0) {
-    return -1;
-  }
-  struct timeval tv;
-  tv.tv_sec = timeout;             // truncating will give seconds
-  timeout -= tv.tv_sec;            // remove seconds portion
-  tv.tv_usec = timeout * 1000000;  // fractions of a second to us
-  int ret = setsockopt(m_lsd, SOL_SOCKET, SO_RCVTIMEO,
-                       reinterpret_cast<char*>(&tv), sizeof(tv));
-  if (ret < 0) {
-    WPI_ERROR(m_logger, "{}", "set timeout failed");
-  }
-  return ret;
-}
diff --git a/wpiutil/src/main/native/cpp/WebSocket.cpp b/wpiutil/src/main/native/cpp/WebSocket.cpp
deleted file mode 100644
index 4bb49d3..0000000
--- a/wpiutil/src/main/native/cpp/WebSocket.cpp
+++ /dev/null
@@ -1,656 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/WebSocket.h"
-
-#include <random>
-
-#include "fmt/format.h"
-#include "wpi/Base64.h"
-#include "wpi/HttpParser.h"
-#include "wpi/SmallString.h"
-#include "wpi/SmallVector.h"
-#include "wpi/StringExtras.h"
-#include "wpi/raw_uv_ostream.h"
-#include "wpi/sha1.h"
-#include "wpi/uv/Stream.h"
-
-using namespace wpi;
-
-namespace {
-class WebSocketWriteReq : public uv::WriteReq {
- public:
-  explicit WebSocketWriteReq(
-      std::function<void(span<uv::Buffer>, uv::Error)> callback)
-      : m_callback{std::move(callback)} {
-    finish.connect([this](uv::Error err) {
-      span<uv::Buffer> bufs{m_bufs};
-      for (auto&& buf : bufs.subspan(0, m_startUser)) {
-        buf.Deallocate();
-      }
-      m_callback(bufs.subspan(m_startUser), err);
-    });
-  }
-
-  std::function<void(span<uv::Buffer>, uv::Error)> m_callback;
-  SmallVector<uv::Buffer, 4> m_bufs;
-  size_t m_startUser;
-};
-}  // namespace
-
-class WebSocket::ClientHandshakeData {
- public:
-  ClientHandshakeData() {
-    // key is a random nonce
-    static std::random_device rd;
-    static std::default_random_engine gen{rd()};
-    std::uniform_int_distribution<unsigned int> dist(0, 255);
-    char nonce[16];  // the nonce sent to the server
-    for (char& v : nonce) {
-      v = static_cast<char>(dist(gen));
-    }
-    raw_svector_ostream os(key);
-    Base64Encode(os, {nonce, 16});
-  }
-  ~ClientHandshakeData() {
-    if (auto t = timer.lock()) {
-      t->Stop();
-      t->Close();
-    }
-  }
-
-  SmallString<64> key;                       // the key sent to the server
-  SmallVector<std::string, 2> protocols;     // valid protocols
-  HttpParser parser{HttpParser::kResponse};  // server response parser
-  bool hasUpgrade = false;
-  bool hasConnection = false;
-  bool hasAccept = false;
-  bool hasProtocol = false;
-
-  std::weak_ptr<uv::Timer> timer;
-};
-
-static std::string_view AcceptHash(std::string_view key,
-                                   SmallVectorImpl<char>& buf) {
-  SHA1 hash;
-  hash.Update(key);
-  hash.Update("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
-  SmallString<64> hashBuf;
-  return Base64Encode(hash.RawFinal(hashBuf), buf);
-}
-
-WebSocket::WebSocket(uv::Stream& stream, bool server, const private_init&)
-    : m_stream{stream}, m_server{server} {
-  // Connect closed and error signals to ourselves
-  m_stream.closed.connect([this]() { SetClosed(1006, "handle closed"); });
-  m_stream.error.connect([this](uv::Error err) {
-    Terminate(1006, fmt::format("stream error: {}", err.name()));
-  });
-
-  // Start reading
-  m_stream.StopRead();  // we may have been reading
-  m_stream.StartRead();
-  m_stream.data.connect(
-      [this](uv::Buffer& buf, size_t size) { HandleIncoming(buf, size); });
-  m_stream.end.connect(
-      [this]() { Terminate(1006, "remote end closed connection"); });
-}
-
-WebSocket::~WebSocket() = default;
-
-std::shared_ptr<WebSocket> WebSocket::CreateClient(
-    uv::Stream& stream, std::string_view uri, std::string_view host,
-    span<const std::string_view> protocols, const ClientOptions& options) {
-  auto ws = std::make_shared<WebSocket>(stream, false, private_init{});
-  stream.SetData(ws);
-  ws->StartClient(uri, host, protocols, options);
-  return ws;
-}
-
-std::shared_ptr<WebSocket> WebSocket::CreateServer(uv::Stream& stream,
-                                                   std::string_view key,
-                                                   std::string_view version,
-                                                   std::string_view protocol) {
-  auto ws = std::make_shared<WebSocket>(stream, true, private_init{});
-  stream.SetData(ws);
-  ws->StartServer(key, version, protocol);
-  return ws;
-}
-
-void WebSocket::Close(uint16_t code, std::string_view reason) {
-  SendClose(code, reason);
-  if (m_state != FAILED && m_state != CLOSED) {
-    m_state = CLOSING;
-  }
-}
-
-void WebSocket::Fail(uint16_t code, std::string_view reason) {
-  if (m_state == FAILED || m_state == CLOSED) {
-    return;
-  }
-  SendClose(code, reason);
-  SetClosed(code, reason, true);
-  Shutdown();
-}
-
-void WebSocket::Terminate(uint16_t code, std::string_view reason) {
-  if (m_state == FAILED || m_state == CLOSED) {
-    return;
-  }
-  SetClosed(code, reason);
-  Shutdown();
-}
-
-void WebSocket::StartClient(std::string_view uri, std::string_view host,
-                            span<const std::string_view> protocols,
-                            const ClientOptions& options) {
-  // Create client handshake data
-  m_clientHandshake = std::make_unique<ClientHandshakeData>();
-
-  // Build client request
-  SmallVector<uv::Buffer, 4> bufs;
-  raw_uv_ostream os{bufs, 4096};
-
-  os << "GET " << uri << " HTTP/1.1\r\n";
-  os << "Host: " << host << "\r\n";
-  os << "Upgrade: websocket\r\n";
-  os << "Connection: Upgrade\r\n";
-  os << "Sec-WebSocket-Key: " << m_clientHandshake->key << "\r\n";
-  os << "Sec-WebSocket-Version: 13\r\n";
-
-  // protocols (if provided)
-  if (!protocols.empty()) {
-    os << "Sec-WebSocket-Protocol: ";
-    bool first = true;
-    for (auto protocol : protocols) {
-      if (!first) {
-        os << ", ";
-      } else {
-        first = false;
-      }
-      os << protocol;
-      // also save for later checking against server response
-      m_clientHandshake->protocols.emplace_back(protocol);
-    }
-    os << "\r\n";
-  }
-
-  // other headers
-  for (auto&& header : options.extraHeaders) {
-    os << header.first << ": " << header.second << "\r\n";
-  }
-
-  // finish headers
-  os << "\r\n";
-
-  // Send client request
-  m_stream.Write(bufs, [](auto bufs, uv::Error) {
-    for (auto& buf : bufs) {
-      buf.Deallocate();
-    }
-  });
-
-  // Set up client response handling
-  m_clientHandshake->parser.status.connect([this](std::string_view status) {
-    unsigned int code = m_clientHandshake->parser.GetStatusCode();
-    if (code != 101) {
-      Terminate(code, status);
-    }
-  });
-  m_clientHandshake->parser.header.connect(
-      [this](std::string_view name, std::string_view value) {
-        value = trim(value);
-        if (equals_lower(name, "upgrade")) {
-          if (!equals_lower(value, "websocket")) {
-            return Terminate(1002, "invalid upgrade response value");
-          }
-          m_clientHandshake->hasUpgrade = true;
-        } else if (equals_lower(name, "connection")) {
-          if (!equals_lower(value, "upgrade")) {
-            return Terminate(1002, "invalid connection response value");
-          }
-          m_clientHandshake->hasConnection = true;
-        } else if (equals_lower(name, "sec-websocket-accept")) {
-          // Check against expected response
-          SmallString<64> acceptBuf;
-          if (!equals(value, AcceptHash(m_clientHandshake->key, acceptBuf))) {
-            return Terminate(1002, "invalid accept key");
-          }
-          m_clientHandshake->hasAccept = true;
-        } else if (equals_lower(name, "sec-websocket-extensions")) {
-          // No extensions are supported
-          if (!value.empty()) {
-            return Terminate(1010, "unsupported extension");
-          }
-        } else if (equals_lower(name, "sec-websocket-protocol")) {
-          // Make sure it was one of the provided protocols
-          bool match = false;
-          for (auto&& protocol : m_clientHandshake->protocols) {
-            if (equals_lower(value, protocol)) {
-              match = true;
-              break;
-            }
-          }
-          if (!match) {
-            return Terminate(1003, "unsupported protocol");
-          }
-          m_clientHandshake->hasProtocol = true;
-          m_protocol = value;
-        }
-      });
-  m_clientHandshake->parser.headersComplete.connect([this](bool) {
-    if (!m_clientHandshake->hasUpgrade || !m_clientHandshake->hasConnection ||
-        !m_clientHandshake->hasAccept ||
-        (!m_clientHandshake->hasProtocol &&
-         !m_clientHandshake->protocols.empty())) {
-      return Terminate(1002, "invalid response");
-    }
-    if (m_state == CONNECTING) {
-      m_state = OPEN;
-      open(m_protocol);
-    }
-  });
-
-  // Start handshake timer if a timeout was specified
-  if (options.handshakeTimeout != (uv::Timer::Time::max)()) {
-    auto timer = uv::Timer::Create(m_stream.GetLoopRef());
-    timer->timeout.connect(
-        [this]() { Terminate(1006, "connection timed out"); });
-    timer->Start(options.handshakeTimeout);
-    m_clientHandshake->timer = timer;
-  }
-}
-
-void WebSocket::StartServer(std::string_view key, std::string_view version,
-                            std::string_view protocol) {
-  m_protocol = protocol;
-
-  // Build server response
-  SmallVector<uv::Buffer, 4> bufs;
-  raw_uv_ostream os{bufs, 4096};
-
-  // Handle unsupported version
-  if (version != "13") {
-    os << "HTTP/1.1 426 Upgrade Required\r\n";
-    os << "Upgrade: WebSocket\r\n";
-    os << "Sec-WebSocket-Version: 13\r\n\r\n";
-    m_stream.Write(bufs, [this](auto bufs, uv::Error) {
-      for (auto& buf : bufs) {
-        buf.Deallocate();
-      }
-      // XXX: Should we support sending a new handshake on the same connection?
-      // XXX: "this->" is required by GCC 5.5 (bug)
-      this->Terminate(1003, "unsupported protocol version");
-    });
-    return;
-  }
-
-  os << "HTTP/1.1 101 Switching Protocols\r\n";
-  os << "Upgrade: websocket\r\n";
-  os << "Connection: Upgrade\r\n";
-
-  // accept hash
-  SmallString<64> acceptBuf;
-  os << "Sec-WebSocket-Accept: " << AcceptHash(key, acceptBuf) << "\r\n";
-
-  if (!protocol.empty()) {
-    os << "Sec-WebSocket-Protocol: " << protocol << "\r\n";
-  }
-
-  // end headers
-  os << "\r\n";
-
-  // Send server response
-  m_stream.Write(bufs, [this](auto bufs, uv::Error) {
-    for (auto& buf : bufs) {
-      buf.Deallocate();
-    }
-    if (m_state == CONNECTING) {
-      m_state = OPEN;
-      open(m_protocol);
-    }
-  });
-}
-
-void WebSocket::SendClose(uint16_t code, std::string_view reason) {
-  SmallVector<uv::Buffer, 4> bufs;
-  if (code != 1005) {
-    raw_uv_ostream os{bufs, 4096};
-    const uint8_t codeMsb[] = {static_cast<uint8_t>((code >> 8) & 0xff),
-                               static_cast<uint8_t>(code & 0xff)};
-    os << span{codeMsb};
-    os << reason;
-  }
-  Send(kFlagFin | kOpClose, bufs, [](auto bufs, uv::Error) {
-    for (auto&& buf : bufs) {
-      buf.Deallocate();
-    }
-  });
-}
-
-void WebSocket::SetClosed(uint16_t code, std::string_view reason, bool failed) {
-  if (m_state == FAILED || m_state == CLOSED) {
-    return;
-  }
-  m_state = failed ? FAILED : CLOSED;
-  closed(code, reason);
-}
-
-void WebSocket::Shutdown() {
-  m_stream.Shutdown([this] { m_stream.Close(); });
-}
-
-void WebSocket::HandleIncoming(uv::Buffer& buf, size_t size) {
-  // ignore incoming data if we're failed or closed
-  if (m_state == FAILED || m_state == CLOSED) {
-    return;
-  }
-
-  std::string_view data{buf.base, size};
-
-  // Handle connecting state (mainly on client)
-  if (m_state == CONNECTING) {
-    if (m_clientHandshake) {
-      data = m_clientHandshake->parser.Execute(data);
-      // check for parser failure
-      if (m_clientHandshake->parser.HasError()) {
-        return Terminate(1003, "invalid response");
-      }
-      if (m_state != OPEN) {
-        return;  // not done with handshake yet
-      }
-
-      // we're done with the handshake, so release its memory
-      m_clientHandshake.reset();
-
-      // fall through to process additional data after handshake
-    } else {
-      return Terminate(1003, "got data on server before response");
-    }
-  }
-
-  // Message processing
-  while (!data.empty()) {
-    if (m_frameSize == UINT64_MAX) {
-      // Need at least two bytes to determine header length
-      if (m_header.size() < 2u) {
-        size_t toCopy = (std::min)(2u - m_header.size(), data.size());
-        m_header.append(data.data(), data.data() + toCopy);
-        data.remove_prefix(toCopy);
-        if (m_header.size() < 2u) {
-          return;  // need more data
-        }
-
-        // Validate RSV bits are zero
-        if ((m_header[0] & 0x70) != 0) {
-          return Fail(1002, "nonzero RSV");
-        }
-      }
-
-      // Once we have first two bytes, we can calculate the header size
-      if (m_headerSize == 0) {
-        m_headerSize = 2;
-        uint8_t len = m_header[1] & kLenMask;
-        if (len == 126) {
-          m_headerSize += 2;
-        } else if (len == 127) {
-          m_headerSize += 8;
-        }
-        bool masking = (m_header[1] & kFlagMasking) != 0;
-        if (masking) {
-          m_headerSize += 4;  // masking key
-        }
-        // On server side, incoming messages MUST be masked
-        // On client side, incoming messages MUST NOT be masked
-        if (m_server && !masking) {
-          return Fail(1002, "client data not masked");
-        }
-        if (!m_server && masking) {
-          return Fail(1002, "server data masked");
-        }
-      }
-
-      // Need to complete header to calculate message size
-      if (m_header.size() < m_headerSize) {
-        size_t toCopy = (std::min)(m_headerSize - m_header.size(), data.size());
-        m_header.append(data.data(), data.data() + toCopy);
-        data.remove_prefix(toCopy);
-        if (m_header.size() < m_headerSize) {
-          return;  // need more data
-        }
-      }
-
-      if (m_header.size() >= m_headerSize) {
-        // get payload length
-        uint8_t len = m_header[1] & kLenMask;
-        if (len == 126) {
-          m_frameSize = (static_cast<uint16_t>(m_header[2]) << 8) |
-                        static_cast<uint16_t>(m_header[3]);
-        } else if (len == 127) {
-          m_frameSize = (static_cast<uint64_t>(m_header[2]) << 56) |
-                        (static_cast<uint64_t>(m_header[3]) << 48) |
-                        (static_cast<uint64_t>(m_header[4]) << 40) |
-                        (static_cast<uint64_t>(m_header[5]) << 32) |
-                        (static_cast<uint64_t>(m_header[6]) << 24) |
-                        (static_cast<uint64_t>(m_header[7]) << 16) |
-                        (static_cast<uint64_t>(m_header[8]) << 8) |
-                        static_cast<uint64_t>(m_header[9]);
-        } else {
-          m_frameSize = len;
-        }
-
-        // limit maximum size
-        if ((m_payload.size() + m_frameSize) > m_maxMessageSize) {
-          return Fail(1009, "message too large");
-        }
-      }
-    }
-
-    if (m_frameSize != UINT64_MAX) {
-      size_t need = m_frameStart + m_frameSize - m_payload.size();
-      size_t toCopy = (std::min)(need, data.size());
-      m_payload.append(data.data(), data.data() + toCopy);
-      data.remove_prefix(toCopy);
-      need -= toCopy;
-      if (need == 0) {
-        // We have a complete frame
-        // If the message had masking, unmask it
-        if ((m_header[1] & kFlagMasking) != 0) {
-          uint8_t key[4] = {
-              m_header[m_headerSize - 4], m_header[m_headerSize - 3],
-              m_header[m_headerSize - 2], m_header[m_headerSize - 1]};
-          int n = 0;
-          for (uint8_t& ch : span{m_payload}.subspan(m_frameStart)) {
-            ch ^= key[n++];
-            if (n >= 4) {
-              n = 0;
-            }
-          }
-        }
-
-        // Handle message
-        bool fin = (m_header[0] & kFlagFin) != 0;
-        uint8_t opcode = m_header[0] & kOpMask;
-        switch (opcode) {
-          case kOpCont:
-            switch (m_fragmentOpcode) {
-              case kOpText:
-                if (!m_combineFragments || fin) {
-                  text(std::string_view{reinterpret_cast<char*>(
-                                            m_payload.data()),
-                                        m_payload.size()},
-                       fin);
-                }
-                break;
-              case kOpBinary:
-                if (!m_combineFragments || fin) {
-                  binary(m_payload, fin);
-                }
-                break;
-              default:
-                // no preceding message?
-                return Fail(1002, "invalid continuation message");
-            }
-            if (fin) {
-              m_fragmentOpcode = 0;
-            }
-            break;
-          case kOpText:
-            if (m_fragmentOpcode != 0) {
-              return Fail(1002, "incomplete fragment");
-            }
-            if (!m_combineFragments || fin) {
-              text(std::string_view{reinterpret_cast<char*>(m_payload.data()),
-                                    m_payload.size()},
-                   fin);
-            }
-            if (!fin) {
-              m_fragmentOpcode = opcode;
-            }
-            break;
-          case kOpBinary:
-            if (m_fragmentOpcode != 0) {
-              return Fail(1002, "incomplete fragment");
-            }
-            if (!m_combineFragments || fin) {
-              binary(m_payload, fin);
-            }
-            if (!fin) {
-              m_fragmentOpcode = opcode;
-            }
-            break;
-          case kOpClose: {
-            uint16_t code;
-            std::string_view reason;
-            if (!fin) {
-              code = 1002;
-              reason = "cannot fragment control frames";
-            } else if (m_payload.size() < 2) {
-              code = 1005;
-            } else {
-              code = (static_cast<uint16_t>(m_payload[0]) << 8) |
-                     static_cast<uint16_t>(m_payload[1]);
-              reason = drop_front(
-                  {reinterpret_cast<char*>(m_payload.data()), m_payload.size()},
-                  2);
-            }
-            // Echo the close if we didn't previously send it
-            if (m_state != CLOSING) {
-              SendClose(code, reason);
-            }
-            SetClosed(code, reason);
-            // If we're the server, shutdown the connection.
-            if (m_server) {
-              Shutdown();
-            }
-            break;
-          }
-          case kOpPing:
-            if (!fin) {
-              return Fail(1002, "cannot fragment control frames");
-            }
-            ping(m_payload);
-            break;
-          case kOpPong:
-            if (!fin) {
-              return Fail(1002, "cannot fragment control frames");
-            }
-            pong(m_payload);
-            break;
-          default:
-            return Fail(1002, "invalid message opcode");
-        }
-
-        // Prepare for next message
-        m_header.clear();
-        m_headerSize = 0;
-        if (!m_combineFragments || fin) {
-          m_payload.clear();
-        }
-        m_frameStart = m_payload.size();
-        m_frameSize = UINT64_MAX;
-      }
-    }
-  }
-}
-
-void WebSocket::Send(
-    uint8_t opcode, span<const uv::Buffer> data,
-    std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-  // If we're not open, emit an error and don't send the data
-  if (m_state != OPEN) {
-    int err;
-    if (m_state == CONNECTING) {
-      err = UV_EAGAIN;
-    } else {
-      err = UV_ESHUTDOWN;
-    }
-    SmallVector<uv::Buffer, 4> bufs{data.begin(), data.end()};
-    callback(bufs, uv::Error{err});
-    return;
-  }
-
-  auto req = std::make_shared<WebSocketWriteReq>(std::move(callback));
-  raw_uv_ostream os{req->m_bufs, 4096};
-
-  // opcode (includes FIN bit)
-  os << static_cast<unsigned char>(opcode);
-
-  // payload length
-  uint64_t size = 0;
-  for (auto&& buf : data) {
-    size += buf.len;
-  }
-  if (size < 126) {
-    os << static_cast<unsigned char>((m_server ? 0x00 : kFlagMasking) | size);
-  } else if (size <= 0xffff) {
-    os << static_cast<unsigned char>((m_server ? 0x00 : kFlagMasking) | 126);
-    const uint8_t sizeMsb[] = {static_cast<uint8_t>((size >> 8) & 0xff),
-                               static_cast<uint8_t>(size & 0xff)};
-    os << span{sizeMsb};
-  } else {
-    os << static_cast<unsigned char>((m_server ? 0x00 : kFlagMasking) | 127);
-    const uint8_t sizeMsb[] = {static_cast<uint8_t>((size >> 56) & 0xff),
-                               static_cast<uint8_t>((size >> 48) & 0xff),
-                               static_cast<uint8_t>((size >> 40) & 0xff),
-                               static_cast<uint8_t>((size >> 32) & 0xff),
-                               static_cast<uint8_t>((size >> 24) & 0xff),
-                               static_cast<uint8_t>((size >> 16) & 0xff),
-                               static_cast<uint8_t>((size >> 8) & 0xff),
-                               static_cast<uint8_t>(size & 0xff)};
-    os << span{sizeMsb};
-  }
-
-  // clients need to mask the input data
-  if (!m_server) {
-    // generate masking key
-    static std::random_device rd;
-    static std::default_random_engine gen{rd()};
-    std::uniform_int_distribution<unsigned int> dist(0, 255);
-    uint8_t key[4];
-    for (uint8_t& v : key) {
-      v = dist(gen);
-    }
-    os << span<const uint8_t>{key, 4};
-    // copy and mask data
-    int n = 0;
-    for (auto&& buf : data) {
-      for (auto&& ch : buf.data()) {
-        os << static_cast<unsigned char>(static_cast<uint8_t>(ch) ^ key[n++]);
-        if (n >= 4) {
-          n = 0;
-        }
-      }
-    }
-    req->m_startUser = req->m_bufs.size();
-    req->m_bufs.append(data.begin(), data.end());
-    // don't send the user bufs as we copied their data
-    m_stream.Write(span{req->m_bufs}.subspan(0, req->m_startUser), req);
-  } else {
-    // servers can just send the buffers directly without masking
-    req->m_startUser = req->m_bufs.size();
-    req->m_bufs.append(data.begin(), data.end());
-    m_stream.Write(req->m_bufs, req);
-  }
-}
diff --git a/wpiutil/src/main/native/cpp/WebSocketServer.cpp b/wpiutil/src/main/native/cpp/WebSocketServer.cpp
deleted file mode 100644
index 1562f3b..0000000
--- a/wpiutil/src/main/native/cpp/WebSocketServer.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/WebSocketServer.h"
-
-#include <utility>
-
-#include "wpi/StringExtras.h"
-#include "wpi/fmt/raw_ostream.h"
-#include "wpi/raw_uv_ostream.h"
-#include "wpi/uv/Buffer.h"
-#include "wpi/uv/Stream.h"
-
-using namespace wpi;
-
-WebSocketServerHelper::WebSocketServerHelper(HttpParser& req) {
-  req.header.connect([this](std::string_view name, std::string_view value) {
-    if (equals_lower(name, "host")) {
-      m_gotHost = true;
-    } else if (equals_lower(name, "upgrade")) {
-      if (equals_lower(value, "websocket")) {
-        m_websocket = true;
-      }
-    } else if (equals_lower(name, "sec-websocket-key")) {
-      m_key = value;
-    } else if (equals_lower(name, "sec-websocket-version")) {
-      m_version = value;
-    } else if (equals_lower(name, "sec-websocket-protocol")) {
-      // Protocols are comma delimited, repeated headers add to list
-      SmallVector<std::string_view, 2> protocols;
-      split(value, protocols, ",", -1, false);
-      for (auto protocol : protocols) {
-        protocol = trim(protocol);
-        if (!protocol.empty()) {
-          m_protocols.emplace_back(protocol);
-        }
-      }
-    }
-  });
-  req.headersComplete.connect([&req, this](bool) {
-    if (req.IsUpgrade() && IsUpgrade()) {
-      upgrade();
-    }
-  });
-}
-
-std::pair<bool, std::string_view> WebSocketServerHelper::MatchProtocol(
-    span<const std::string_view> protocols) {
-  if (protocols.empty() && m_protocols.empty()) {
-    return {true, {}};
-  }
-  for (auto protocol : protocols) {
-    for (auto&& clientProto : m_protocols) {
-      if (protocol == clientProto) {
-        return {true, protocol};
-      }
-    }
-  }
-  return {false, {}};
-}
-
-WebSocketServer::WebSocketServer(uv::Stream& stream,
-                                 span<const std::string_view> protocols,
-                                 ServerOptions options, const private_init&)
-    : m_stream{stream},
-      m_helper{m_req},
-      m_protocols{protocols.begin(), protocols.end()},
-      m_options{std::move(options)} {
-  // Header handling
-  m_req.header.connect([this](std::string_view name, std::string_view value) {
-    if (equals_lower(name, "host")) {
-      if (m_options.checkHost) {
-        if (!m_options.checkHost(value)) {
-          Abort(401, "Unrecognized Host");
-        }
-      }
-    }
-  });
-  m_req.url.connect([this](std::string_view name) {
-    if (m_options.checkUrl) {
-      if (!m_options.checkUrl(name)) {
-        Abort(404, "Not Found");
-      }
-    }
-  });
-  m_req.headersComplete.connect([this](bool) {
-    // We only accept websocket connections
-    if (!m_helper.IsUpgrade() || !m_req.IsUpgrade()) {
-      Abort(426, "Upgrade Required");
-    }
-  });
-
-  // Handle upgrade event
-  m_helper.upgrade.connect([this] {
-    if (m_aborted) {
-      return;
-    }
-
-    // Negotiate sub-protocol
-    SmallVector<std::string_view, 2> protocols{m_protocols.begin(),
-                                               m_protocols.end()};
-    std::string_view protocol = m_helper.MatchProtocol(protocols).second;
-
-    // Disconnect our header reader
-    m_dataConn.disconnect();
-
-    // Accepting the stream may destroy this (as it replaces the stream user
-    // data), so grab a shared pointer first.
-    auto self = shared_from_this();
-
-    // Accept the upgrade
-    auto ws = m_helper.Accept(m_stream, protocol);
-
-    // Connect the websocket open event to our connected event.
-    ws->open.connect_extended(
-        [self, s = ws.get()](auto conn, std::string_view) {
-          self->connected(self->m_req.GetUrl(), *s);
-          conn.disconnect();  // one-shot
-        });
-  });
-
-  // Set up stream
-  stream.StartRead();
-  m_dataConn =
-      stream.data.connect_connection([this](uv::Buffer& buf, size_t size) {
-        if (m_aborted) {
-          return;
-        }
-        m_req.Execute(std::string_view{buf.base, size});
-        if (m_req.HasError()) {
-          Abort(400, "Bad Request");
-        }
-      });
-  m_errorConn =
-      stream.error.connect_connection([this](uv::Error) { m_stream.Close(); });
-  m_endConn = stream.end.connect_connection([this] { m_stream.Close(); });
-}
-
-std::shared_ptr<WebSocketServer> WebSocketServer::Create(
-    uv::Stream& stream, span<const std::string_view> protocols,
-    const ServerOptions& options) {
-  auto server = std::make_shared<WebSocketServer>(stream, protocols, options,
-                                                  private_init{});
-  stream.SetData(server);
-  return server;
-}
-
-void WebSocketServer::Abort(uint16_t code, std::string_view reason) {
-  if (m_aborted) {
-    return;
-  }
-  m_aborted = true;
-
-  // Build response
-  SmallVector<uv::Buffer, 4> bufs;
-  raw_uv_ostream os{bufs, 1024};
-
-  // Handle unsupported version
-  fmt::print(os, "HTTP/1.1 {} {}\r\n", code, reason);
-  if (code == 426) {
-    os << "Upgrade: WebSocket\r\n";
-  }
-  os << "\r\n";
-  m_stream.Write(bufs, [this](auto bufs, uv::Error) {
-    for (auto& buf : bufs) {
-      buf.Deallocate();
-    }
-    m_stream.Shutdown([this] { m_stream.Close(); });
-  });
-}
diff --git a/wpiutil/src/main/native/cpp/fs.cpp b/wpiutil/src/main/native/cpp/fs.cpp
index 34d6cca..fad6a66 100644
--- a/wpiutil/src/main/native/cpp/fs.cpp
+++ b/wpiutil/src/main/native/cpp/fs.cpp
@@ -82,17 +82,6 @@
 const file_t kInvalidFile = INVALID_HANDLE_VALUE;
 
 static DWORD nativeDisposition(CreationDisposition Disp, OpenFlags Flags) {
-  // This is a compatibility hack.  Really we should respect the creation
-  // disposition, but a lot of old code relied on the implicit assumption that
-  // OF_Append implied it would open an existing file.  Since the disposition is
-  // now explicit and defaults to CD_CreateAlways, this assumption would cause
-  // any usage of OF_Append to append to a new file, even if the file already
-  // existed.  A better solution might have two new creation dispositions:
-  // CD_AppendAlways and CD_AppendNew.  This would also address the problem of
-  // OF_Append being used on a read-only descriptor, which doesn't make sense.
-  if (Flags & OF_Append)
-    return OPEN_ALWAYS;
-
   switch (Disp) {
     case CD_CreateAlways:
       return CREATE_ALWAYS;
@@ -251,12 +240,6 @@
     Result |= O_RDWR;
   }
 
-  // This is for compatibility with old code that assumed F_Append implied
-  // would open an existing file.  See Windows/Path.inc for a longer comment.
-  if (Flags & F_Append) {
-    Disp = CD_OpenAlways;
-  }
-
   if (Disp == CD_CreateNew) {
     Result |= O_CREAT;  // Create if it doesn't exist.
     Result |= O_EXCL;   // Fail if it does.
diff --git a/wpiutil/src/main/native/cpp/hostname.cpp b/wpiutil/src/main/native/cpp/hostname.cpp
deleted file mode 100644
index d907023..0000000
--- a/wpiutil/src/main/native/cpp/hostname.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/hostname.h"
-
-#include <cstdlib>
-#include <string>
-#include <string_view>
-
-#include "uv.h"
-#include "wpi/SmallVector.h"
-
-namespace wpi {
-
-std::string GetHostname() {
-  std::string rv;
-  char name[256];
-  size_t size = sizeof(name);
-
-  int err = uv_os_gethostname(name, &size);
-  if (err == 0) {
-    rv.assign(name, size);
-  } else if (err == UV_ENOBUFS) {
-    char* name2 = static_cast<char*>(std::malloc(size));
-    err = uv_os_gethostname(name2, &size);
-    if (err == 0) {
-      rv.assign(name2, size);
-    }
-    std::free(name2);
-  }
-
-  return rv;
-}
-
-std::string_view GetHostname(SmallVectorImpl<char>& name) {
-  // Use a tmp array to not require the SmallVector to be too large.
-  char tmpName[256];
-  size_t size = sizeof(tmpName);
-
-  name.clear();
-
-  int err = uv_os_gethostname(tmpName, &size);
-  if (err == 0) {
-    name.append(tmpName, tmpName + size);
-  } else if (err == UV_ENOBUFS) {
-    name.resize(size);
-    err = uv_os_gethostname(name.data(), &size);
-    if (err != 0) {
-      size = 0;
-    }
-  }
-
-  return {name.data(), size};
-}
-
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/cpp/http_parser.cpp b/wpiutil/src/main/native/cpp/http_parser.cpp
deleted file mode 100644
index bc442b2..0000000
--- a/wpiutil/src/main/native/cpp/http_parser.cpp
+++ /dev/null
@@ -1,2475 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include "wpi/http_parser.h"
-#include <assert.h>
-#include <stddef.h>
-#include <ctype.h>
-#include <string.h>
-#include <limits.h>
-
-#ifdef _WIN32
-#pragma warning(disable : 4018 26451)
-#endif
-
-#ifndef ULLONG_MAX
-# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
-#endif
-
-#ifndef MIN
-# define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-#ifndef ARRAY_SIZE
-# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-#endif
-
-#ifndef BIT_AT
-# define BIT_AT(a, i)                                                \
-  (!!((unsigned int) (a)[(unsigned int) (i) >> 3] &                  \
-   (1 << ((unsigned int) (i) & 7))))
-#endif
-
-#ifndef ELEM_AT
-# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
-#endif
-
-#define SET_ERRNO(e)                                                 \
-do {                                                                 \
-  parser->nread = nread;                                             \
-  parser->http_errno = (e);                                          \
-} while(0)
-
-#define CURRENT_STATE() p_state
-#define UPDATE_STATE(V) p_state = (enum state) (V);
-#define RETURN(V)                                                    \
-do {                                                                 \
-  parser->nread = nread;                                             \
-  parser->state = CURRENT_STATE();                                   \
-  return (V);                                                        \
-} while (0);
-#define REEXECUTE()                                                  \
-  goto reexecute;                                                    \
-
-
-#ifdef __GNUC__
-# define LIKELY(X) __builtin_expect(!!(X), 1)
-# define UNLIKELY(X) __builtin_expect(!!(X), 0)
-#else
-# define LIKELY(X) (X)
-# define UNLIKELY(X) (X)
-#endif
-
-
-/* Run the notify callback FOR, returning ER if it fails */
-#define CALLBACK_NOTIFY_(FOR, ER)                                    \
-do {                                                                 \
-  assert(HTTP_PARSER_ERRNO(parser) == HPE_OK);                       \
-                                                                     \
-  if (LIKELY(settings->on_##FOR)) {                                  \
-    parser->state = CURRENT_STATE();                                 \
-    if (UNLIKELY(0 != settings->on_##FOR(parser))) {                 \
-      SET_ERRNO(HPE_CB_##FOR);                                       \
-    }                                                                \
-    UPDATE_STATE(parser->state);                                     \
-                                                                     \
-    /* We either errored above or got paused; get out */             \
-    if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {             \
-      return (ER);                                                   \
-    }                                                                \
-  }                                                                  \
-} while (0)
-
-/* Run the notify callback FOR and consume the current byte */
-#define CALLBACK_NOTIFY(FOR)            CALLBACK_NOTIFY_(FOR, p - data + 1)
-
-/* Run the notify callback FOR and don't consume the current byte */
-#define CALLBACK_NOTIFY_NOADVANCE(FOR)  CALLBACK_NOTIFY_(FOR, p - data)
-
-/* Run data callback FOR with LEN bytes, returning ER if it fails */
-#define CALLBACK_DATA_(FOR, LEN, ER)                                 \
-do {                                                                 \
-  assert(HTTP_PARSER_ERRNO(parser) == HPE_OK);                       \
-                                                                     \
-  if (FOR##_mark) {                                                  \
-    if (LIKELY(settings->on_##FOR)) {                                \
-      parser->state = CURRENT_STATE();                               \
-      if (UNLIKELY(0 !=                                              \
-                   settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \
-        SET_ERRNO(HPE_CB_##FOR);                                     \
-      }                                                              \
-      UPDATE_STATE(parser->state);                                   \
-                                                                     \
-      /* We either errored above or got paused; get out */           \
-      if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {           \
-        return (ER);                                                 \
-      }                                                              \
-    }                                                                \
-    FOR##_mark = NULL;                                               \
-  }                                                                  \
-} while (0)
-
-/* Run the data callback FOR and consume the current byte */
-#define CALLBACK_DATA(FOR)                                           \
-    CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
-
-/* Run the data callback FOR and don't consume the current byte */
-#define CALLBACK_DATA_NOADVANCE(FOR)                                 \
-    CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
-
-/* Set the mark FOR; non-destructive if mark is already set */
-#define MARK(FOR)                                                    \
-do {                                                                 \
-  if (!FOR##_mark) {                                                 \
-    FOR##_mark = p;                                                  \
-  }                                                                  \
-} while (0)
-
-/* Don't allow the total size of the HTTP headers (including the status
- * line) to exceed HTTP_MAX_HEADER_SIZE.  This check is here to protect
- * embedders against denial-of-service attacks where the attacker feeds
- * us a never-ending header that the embedder keeps buffering.
- *
- * This check is arguably the responsibility of embedders but we're doing
- * it on the embedder's behalf because most won't bother and this way we
- * make the web a little safer.  HTTP_MAX_HEADER_SIZE is still far bigger
- * than any reasonable request or response so this should never affect
- * day-to-day operation.
- */
-#define COUNT_HEADER_SIZE(V)                                         \
-do {                                                                 \
-  nread += (V);                                                      \
-  if (UNLIKELY(nread > (HTTP_MAX_HEADER_SIZE))) {                    \
-    SET_ERRNO(HPE_HEADER_OVERFLOW);                                  \
-    goto error;                                                      \
-  }                                                                  \
-} while (0)
-
-
-#define PROXY_CONNECTION "proxy-connection"
-#define CONNECTION "connection"
-#define CONTENT_LENGTH "content-length"
-#define TRANSFER_ENCODING "transfer-encoding"
-#define UPGRADE "upgrade"
-#define CHUNKED "chunked"
-#define KEEP_ALIVE "keep-alive"
-#define CLOSE "close"
-
-namespace wpi {
-
-
-static const char *method_strings[] =
-  {
-#define XX(num, name, string) #string,
-  HTTP_METHOD_MAP(XX)
-#undef XX
-  };
-
-
-/* Tokens as defined by rfc 2616. Also lowercases them.
- *        token       = 1*<any CHAR except CTLs or separators>
- *     separators     = "(" | ")" | "<" | ">" | "@"
- *                    | "," | ";" | ":" | "\" | <">
- *                    | "/" | "[" | "]" | "?" | "="
- *                    | "{" | "}" | SP | HT
- */
-static const char tokens[256] = {
-/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
-       ' ',     '!',      0,      '#',     '$',     '%',     '&',    '\'',
-/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
-        0,       0,      '*',     '+',      0,      '-',     '.',      0,
-/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
-       '0',     '1',     '2',     '3',     '4',     '5',     '6',     '7',
-/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
-       '8',     '9',      0,       0,       0,       0,       0,       0,
-/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
-        0,      'a',     'b',     'c',     'd',     'e',     'f',     'g',
-/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
-       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
-/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
-       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
-/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
-       'x',     'y',     'z',      0,       0,       0,      '^',     '_',
-/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
-       '`',     'a',     'b',     'c',     'd',     'e',     'f',     'g',
-/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
-       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
-/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
-       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
-/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
-       'x',     'y',     'z',      0,      '|',      0,      '~',       0 };
-
-
-static const int8_t unhex[256] =
-  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
-  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  };
-
-
-#if HTTP_PARSER_STRICT
-# define T(v) 0
-#else
-# define T(v) v
-#endif
-
-
-static const uint8_t normal_url_char[32] = {
-/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
-        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
-/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
-        0    | T(2)   |   0    |   0    | T(16)  |   0    |   0    |   0,
-/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
-        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
-/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
-        0    |   0    |   0    |   0    |   0    |   0    |   0    |   0,
-/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
-        0    |   2    |   4    |   0    |   16   |   32   |   64   |  128,
-/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |   0,
-/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |  128,
-/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
-        1    |   2    |   4    |   8    |   16   |   32   |   64   |   0, };
-
-#undef T
-
-enum state
-  { s_dead = 1 /* important that this is > 0 */
-
-  , s_start_req_or_res
-  , s_res_or_resp_H
-  , s_start_res
-  , s_res_H
-  , s_res_HT
-  , s_res_HTT
-  , s_res_HTTP
-  , s_res_http_major
-  , s_res_http_dot
-  , s_res_http_minor
-  , s_res_http_end
-  , s_res_first_status_code
-  , s_res_status_code
-  , s_res_status_start
-  , s_res_status
-  , s_res_line_almost_done
-
-  , s_start_req
-
-  , s_req_method
-  , s_req_spaces_before_url
-  , s_req_schema
-  , s_req_schema_slash
-  , s_req_schema_slash_slash
-  , s_req_server_start
-  , s_req_server
-  , s_req_server_with_at
-  , s_req_path
-  , s_req_query_string_start
-  , s_req_query_string
-  , s_req_fragment_start
-  , s_req_fragment
-  , s_req_http_start
-  , s_req_http_H
-  , s_req_http_HT
-  , s_req_http_HTT
-  , s_req_http_HTTP
-  , s_req_http_major
-  , s_req_http_dot
-  , s_req_http_minor
-  , s_req_http_end
-  , s_req_line_almost_done
-
-  , s_header_field_start
-  , s_header_field
-  , s_header_value_discard_ws
-  , s_header_value_discard_ws_almost_done
-  , s_header_value_discard_lws
-  , s_header_value_start
-  , s_header_value
-  , s_header_value_lws
-
-  , s_header_almost_done
-
-  , s_chunk_size_start
-  , s_chunk_size
-  , s_chunk_parameters
-  , s_chunk_size_almost_done
-
-  , s_headers_almost_done
-  , s_headers_done
-
-  /* Important: 's_headers_done' must be the last 'header' state. All
-   * states beyond this must be 'body' states. It is used for overflow
-   * checking. See the PARSING_HEADER() macro.
-   */
-
-  , s_chunk_data
-  , s_chunk_data_almost_done
-  , s_chunk_data_done
-
-  , s_body_identity
-  , s_body_identity_eof
-
-  , s_message_done
-  };
-
-
-#define PARSING_HEADER(state) (state <= s_headers_done)
-
-
-enum header_states
-  { h_general = 0
-  , h_C
-  , h_CO
-  , h_CON
-
-  , h_matching_connection
-  , h_matching_proxy_connection
-  , h_matching_content_length
-  , h_matching_transfer_encoding
-  , h_matching_upgrade
-
-  , h_connection
-  , h_content_length
-  , h_content_length_num
-  , h_content_length_ws
-  , h_transfer_encoding
-  , h_upgrade
-
-  , h_matching_transfer_encoding_chunked
-  , h_matching_connection_token_start
-  , h_matching_connection_keep_alive
-  , h_matching_connection_close
-  , h_matching_connection_upgrade
-  , h_matching_connection_token
-
-  , h_transfer_encoding_chunked
-  , h_connection_keep_alive
-  , h_connection_close
-  , h_connection_upgrade
-  };
-
-enum http_host_state
-  {
-    s_http_host_dead = 1
-  , s_http_userinfo_start
-  , s_http_userinfo
-  , s_http_host_start
-  , s_http_host_v6_start
-  , s_http_host
-  , s_http_host_v6
-  , s_http_host_v6_end
-  , s_http_host_v6_zone_start
-  , s_http_host_v6_zone
-  , s_http_host_port_start
-  , s_http_host_port
-};
-
-/* Macros for character classes; depends on strict-mode  */
-#define CR                  '\r'
-#define LF                  '\n'
-#define LOWER(c)            (unsigned char)(c | 0x20)
-#define IS_ALPHA(c)         (LOWER(c) >= 'a' && LOWER(c) <= 'z')
-#define IS_NUM(c)           ((c) >= '0' && (c) <= '9')
-#define IS_ALPHANUM(c)      (IS_ALPHA(c) || IS_NUM(c))
-#define IS_HEX(c)           (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
-#define IS_MARK(c)          ((c) == '-' || (c) == '_' || (c) == '.' || \
-  (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
-  (c) == ')')
-#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
-  (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
-  (c) == '$' || (c) == ',')
-
-#define STRICT_TOKEN(c)     ((c == ' ') ? 0 : tokens[(unsigned char)c])
-
-#if HTTP_PARSER_STRICT
-#define TOKEN(c)            STRICT_TOKEN(c)
-#define IS_URL_CHAR(c)      (BIT_AT(normal_url_char, (unsigned char)c))
-#define IS_HOST_CHAR(c)     (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
-#else
-#define TOKEN(c)            tokens[(unsigned char)c]
-#define IS_URL_CHAR(c)                                                         \
-  (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
-#define IS_HOST_CHAR(c)                                                        \
-  (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
-#endif
-
-/**
- * Verify that a char is a valid visible (printable) US-ASCII
- * character or %x80-FF
- **/
-#define IS_HEADER_CHAR(ch)                                                     \
-  (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127))
-
-#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
-
-
-#if HTTP_PARSER_STRICT
-# define STRICT_CHECK(cond)                                          \
-do {                                                                 \
-  if (cond) {                                                        \
-    SET_ERRNO(HPE_STRICT);                                           \
-    goto error;                                                      \
-  }                                                                  \
-} while (0)
-# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
-#else
-# define STRICT_CHECK(cond)
-# define NEW_MESSAGE() start_state
-#endif
-
-
-/* Map errno values to strings for human-readable output */
-#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
-static struct {
-  const char *name;
-  const char *description;
-} http_strerror_tab[] = {
-  HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)
-};
-#undef HTTP_STRERROR_GEN
-
-int http_message_needs_eof(const http_parser *parser);
-
-/* Our URL parser.
- *
- * This is designed to be shared by http_parser_execute() for URL validation,
- * hence it has a state transition + byte-for-byte interface. In addition, it
- * is meant to be embedded in http_parser_parse_url(), which does the dirty
- * work of turning state transitions URL components for its API.
- *
- * This function should only be invoked with non-space characters. It is
- * assumed that the caller cares about (and can detect) the transition between
- * URL and non-URL states by looking for these.
- */
-static enum state
-parse_url_char(enum state s, const char ch)
-{
-  if (ch == ' ' || ch == '\r' || ch == '\n') {
-    return s_dead;
-  }
-
-#if HTTP_PARSER_STRICT
-  if (ch == '\t' || ch == '\f') {
-    return s_dead;
-  }
-#endif
-
-  switch (s) {
-    case s_req_spaces_before_url:
-      /* Proxied requests are followed by scheme of an absolute URI (alpha).
-       * All methods except CONNECT are followed by '/' or '*'.
-       */
-
-      if (ch == '/' || ch == '*') {
-        return s_req_path;
-      }
-
-      if (IS_ALPHA(ch)) {
-        return s_req_schema;
-      }
-
-      break;
-
-    case s_req_schema:
-      if (IS_ALPHA(ch)) {
-        return s;
-      }
-
-      if (ch == ':') {
-        return s_req_schema_slash;
-      }
-
-      break;
-
-    case s_req_schema_slash:
-      if (ch == '/') {
-        return s_req_schema_slash_slash;
-      }
-
-      break;
-
-    case s_req_schema_slash_slash:
-      if (ch == '/') {
-        return s_req_server_start;
-      }
-
-      break;
-
-    case s_req_server_with_at:
-      if (ch == '@') {
-        return s_dead;
-      }
-
-    /* fall through */
-    case s_req_server_start:
-    case s_req_server:
-      if (ch == '/') {
-        return s_req_path;
-      }
-
-      if (ch == '?') {
-        return s_req_query_string_start;
-      }
-
-      if (ch == '@') {
-        return s_req_server_with_at;
-      }
-
-      if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {
-        return s_req_server;
-      }
-
-      break;
-
-    case s_req_path:
-      if (IS_URL_CHAR(ch)) {
-        return s;
-      }
-
-      switch (ch) {
-        case '?':
-          return s_req_query_string_start;
-
-        case '#':
-          return s_req_fragment_start;
-      }
-
-      break;
-
-    case s_req_query_string_start:
-    case s_req_query_string:
-      if (IS_URL_CHAR(ch)) {
-        return s_req_query_string;
-      }
-
-      switch (ch) {
-        case '?':
-          /* allow extra '?' in query string */
-          return s_req_query_string;
-
-        case '#':
-          return s_req_fragment_start;
-      }
-
-      break;
-
-    case s_req_fragment_start:
-      if (IS_URL_CHAR(ch)) {
-        return s_req_fragment;
-      }
-
-      switch (ch) {
-        case '?':
-          return s_req_fragment;
-
-        case '#':
-          return s;
-      }
-
-      break;
-
-    case s_req_fragment:
-      if (IS_URL_CHAR(ch)) {
-        return s;
-      }
-
-      switch (ch) {
-        case '?':
-        case '#':
-          return s;
-      }
-
-      break;
-
-    default:
-      break;
-  }
-
-  /* We should never fall out of the switch above unless there's an error */
-  return s_dead;
-}
-
-size_t http_parser_execute (http_parser *parser,
-                            const http_parser_settings *settings,
-                            const char *data,
-                            size_t len)
-{
-  char c, ch;
-  int8_t unhex_val;
-  const char *p = data;
-  const char *header_field_mark = 0;
-  const char *header_value_mark = 0;
-  const char *url_mark = 0;
-  const char *body_mark = 0;
-  const char *status_mark = 0;
-  enum state p_state = (enum state) parser->state;
-  const unsigned int lenient = parser->lenient_http_headers;
-  uint32_t nread = parser->nread;
-
-  /* We're in an error state. Don't bother doing anything. */
-  if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
-    return 0;
-  }
-
-  if (len == 0) {
-    switch (CURRENT_STATE()) {
-      case s_body_identity_eof:
-        /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
-         * we got paused.
-         */
-        CALLBACK_NOTIFY_NOADVANCE(message_complete);
-        return 0;
-
-      case s_dead:
-      case s_start_req_or_res:
-      case s_start_res:
-      case s_start_req:
-        return 0;
-
-      default:
-        SET_ERRNO(HPE_INVALID_EOF_STATE);
-        return 1;
-    }
-  }
-
-
-  if (CURRENT_STATE() == s_header_field)
-    header_field_mark = data;
-  if (CURRENT_STATE() == s_header_value)
-    header_value_mark = data;
-  switch (CURRENT_STATE()) {
-  case s_req_path:
-  case s_req_schema:
-  case s_req_schema_slash:
-  case s_req_schema_slash_slash:
-  case s_req_server_start:
-  case s_req_server:
-  case s_req_server_with_at:
-  case s_req_query_string_start:
-  case s_req_query_string:
-  case s_req_fragment_start:
-  case s_req_fragment:
-    url_mark = data;
-    break;
-  case s_res_status:
-    status_mark = data;
-    break;
-  default:
-    break;
-  }
-
-  for (p=data; p != data + len; p++) {
-    ch = *p;
-
-    if (PARSING_HEADER(CURRENT_STATE()))
-      COUNT_HEADER_SIZE(1);
-
-reexecute:
-    switch (CURRENT_STATE()) {
-
-      case s_dead:
-        /* this state is used after a 'Connection: close' message
-         * the parser will error out if it reads another message
-         */
-        if (LIKELY(ch == CR || ch == LF))
-          break;
-
-        SET_ERRNO(HPE_CLOSED_CONNECTION);
-        goto error;
-
-      case s_start_req_or_res:
-      {
-        if (ch == CR || ch == LF)
-          break;
-        parser->flags = 0;
-        parser->content_length = ULLONG_MAX;
-
-        if (ch == 'H') {
-          UPDATE_STATE(s_res_or_resp_H);
-
-          CALLBACK_NOTIFY(message_begin);
-        } else {
-          parser->type = HTTP_REQUEST;
-          UPDATE_STATE(s_start_req);
-          REEXECUTE();
-        }
-
-        break;
-      }
-
-      case s_res_or_resp_H:
-        if (ch == 'T') {
-          parser->type = HTTP_RESPONSE;
-          UPDATE_STATE(s_res_HT);
-        } else {
-          if (UNLIKELY(ch != 'E')) {
-            SET_ERRNO(HPE_INVALID_CONSTANT);
-            goto error;
-          }
-
-          parser->type = HTTP_REQUEST;
-          parser->method = HTTP_HEAD;
-          parser->index = 2;
-          UPDATE_STATE(s_req_method);
-        }
-        break;
-
-      case s_start_res:
-      {
-        parser->flags = 0;
-        parser->content_length = ULLONG_MAX;
-
-        switch (ch) {
-          case 'H':
-            UPDATE_STATE(s_res_H);
-            break;
-
-          case CR:
-          case LF:
-            break;
-
-          default:
-            SET_ERRNO(HPE_INVALID_CONSTANT);
-            goto error;
-        }
-
-        CALLBACK_NOTIFY(message_begin);
-        break;
-      }
-
-      case s_res_H:
-        STRICT_CHECK(ch != 'T');
-        UPDATE_STATE(s_res_HT);
-        break;
-
-      case s_res_HT:
-        STRICT_CHECK(ch != 'T');
-        UPDATE_STATE(s_res_HTT);
-        break;
-
-      case s_res_HTT:
-        STRICT_CHECK(ch != 'P');
-        UPDATE_STATE(s_res_HTTP);
-        break;
-
-      case s_res_HTTP:
-        STRICT_CHECK(ch != '/');
-        UPDATE_STATE(s_res_http_major);
-        break;
-
-      case s_res_http_major:
-        if (UNLIKELY(!IS_NUM(ch))) {
-          SET_ERRNO(HPE_INVALID_VERSION);
-          goto error;
-        }
-
-        parser->http_major = ch - '0';
-        UPDATE_STATE(s_res_http_dot);
-        break;
-
-      case s_res_http_dot:
-      {
-        if (UNLIKELY(ch != '.')) {
-          SET_ERRNO(HPE_INVALID_VERSION);
-          goto error;
-        }
-
-        UPDATE_STATE(s_res_http_minor);
-        break;
-      }
-
-      case s_res_http_minor:
-        if (UNLIKELY(!IS_NUM(ch))) {
-          SET_ERRNO(HPE_INVALID_VERSION);
-          goto error;
-        }
-
-        parser->http_minor = ch - '0';
-        UPDATE_STATE(s_res_http_end);
-        break;
-
-      case s_res_http_end:
-      {
-        if (UNLIKELY(ch != ' ')) {
-          SET_ERRNO(HPE_INVALID_VERSION);
-          goto error;
-        }
-
-        UPDATE_STATE(s_res_first_status_code);
-        break;
-      }
-
-      case s_res_first_status_code:
-      {
-        if (!IS_NUM(ch)) {
-          if (ch == ' ') {
-            break;
-          }
-
-          SET_ERRNO(HPE_INVALID_STATUS);
-          goto error;
-        }
-        parser->status_code = ch - '0';
-        UPDATE_STATE(s_res_status_code);
-        break;
-      }
-
-      case s_res_status_code:
-      {
-        if (!IS_NUM(ch)) {
-          switch (ch) {
-            case ' ':
-              UPDATE_STATE(s_res_status_start);
-              break;
-            case CR:
-            case LF:
-              UPDATE_STATE(s_res_status_start);
-              REEXECUTE();
-              break;
-            default:
-              SET_ERRNO(HPE_INVALID_STATUS);
-              goto error;
-          }
-          break;
-        }
-
-        parser->status_code *= 10;
-        parser->status_code += ch - '0';
-
-        if (UNLIKELY(parser->status_code > 999)) {
-          SET_ERRNO(HPE_INVALID_STATUS);
-          goto error;
-        }
-
-        break;
-      }
-
-      case s_res_status_start:
-      {
-        MARK(status);
-        UPDATE_STATE(s_res_status);
-        parser->index = 0;
-
-        if (ch == CR || ch == LF)
-          REEXECUTE();
-
-        break;
-      }
-
-      case s_res_status:
-        if (ch == CR) {
-          UPDATE_STATE(s_res_line_almost_done);
-          CALLBACK_DATA(status);
-          break;
-        }
-
-        if (ch == LF) {
-          UPDATE_STATE(s_header_field_start);
-          CALLBACK_DATA(status);
-          break;
-        }
-
-        break;
-
-      case s_res_line_almost_done:
-        STRICT_CHECK(ch != LF);
-        UPDATE_STATE(s_header_field_start);
-        break;
-
-      case s_start_req:
-      {
-        if (ch == CR || ch == LF)
-          break;
-        parser->flags = 0;
-        parser->content_length = ULLONG_MAX;
-
-        if (UNLIKELY(!IS_ALPHA(ch))) {
-          SET_ERRNO(HPE_INVALID_METHOD);
-          goto error;
-        }
-
-        parser->method = (enum http_method) 0;
-        parser->index = 1;
-        switch (ch) {
-          case 'A': parser->method = HTTP_ACL; break;
-          case 'B': parser->method = HTTP_BIND; break;
-          case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
-          case 'D': parser->method = HTTP_DELETE; break;
-          case 'G': parser->method = HTTP_GET; break;
-          case 'H': parser->method = HTTP_HEAD; break;
-          case 'L': parser->method = HTTP_LOCK; /* or LINK */ break;
-          case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break;
-          case 'N': parser->method = HTTP_NOTIFY; break;
-          case 'O': parser->method = HTTP_OPTIONS; break;
-          case 'P': parser->method = HTTP_POST;
-            /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
-            break;
-          case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break;
-          case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH, SOURCE */ break;
-          case 'T': parser->method = HTTP_TRACE; break;
-          case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break;
-          default:
-            SET_ERRNO(HPE_INVALID_METHOD);
-            goto error;
-        }
-        UPDATE_STATE(s_req_method);
-
-        CALLBACK_NOTIFY(message_begin);
-
-        break;
-      }
-
-      case s_req_method:
-      {
-        const char *matcher;
-        if (UNLIKELY(ch == '\0')) {
-          SET_ERRNO(HPE_INVALID_METHOD);
-          goto error;
-        }
-
-        matcher = method_strings[parser->method];
-        if (ch == ' ' && matcher[parser->index] == '\0') {
-          UPDATE_STATE(s_req_spaces_before_url);
-        } else if (ch == matcher[parser->index]) {
-          ; /* nada */
-        } else if ((ch >= 'A' && ch <= 'Z') || ch == '-') {
-
-          switch (parser->method << 16 | parser->index << 8 | ch) {
-#define XX(meth, pos, ch, new_meth) \
-            case (HTTP_##meth << 16 | pos << 8 | ch): \
-              parser->method = HTTP_##new_meth; break;
-
-            XX(POST,      1, 'U', PUT)
-            XX(POST,      1, 'A', PATCH)
-            XX(POST,      1, 'R', PROPFIND)
-            XX(PUT,       2, 'R', PURGE)
-            XX(CONNECT,   1, 'H', CHECKOUT)
-            XX(CONNECT,   2, 'P', COPY)
-            XX(MKCOL,     1, 'O', MOVE)
-            XX(MKCOL,     1, 'E', MERGE)
-            XX(MKCOL,     1, '-', MSEARCH)
-            XX(MKCOL,     2, 'A', MKACTIVITY)
-            XX(MKCOL,     3, 'A', MKCALENDAR)
-            XX(SUBSCRIBE, 1, 'E', SEARCH)
-            XX(SUBSCRIBE, 1, 'O', SOURCE)
-            XX(REPORT,    2, 'B', REBIND)
-            XX(PROPFIND,  4, 'P', PROPPATCH)
-            XX(LOCK,      1, 'I', LINK)
-            XX(UNLOCK,    2, 'S', UNSUBSCRIBE)
-            XX(UNLOCK,    2, 'B', UNBIND)
-            XX(UNLOCK,    3, 'I', UNLINK)
-#undef XX
-            default:
-              SET_ERRNO(HPE_INVALID_METHOD);
-              goto error;
-          }
-        } else {
-          SET_ERRNO(HPE_INVALID_METHOD);
-          goto error;
-        }
-
-        ++parser->index;
-        break;
-      }
-
-      case s_req_spaces_before_url:
-      {
-        if (ch == ' ') break;
-
-        MARK(url);
-        if (parser->method == HTTP_CONNECT) {
-          UPDATE_STATE(s_req_server_start);
-        }
-
-        UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
-        if (UNLIKELY(CURRENT_STATE() == s_dead)) {
-          SET_ERRNO(HPE_INVALID_URL);
-          goto error;
-        }
-
-        break;
-      }
-
-      case s_req_schema:
-      case s_req_schema_slash:
-      case s_req_schema_slash_slash:
-      case s_req_server_start:
-      {
-        switch (ch) {
-          /* No whitespace allowed here */
-          case ' ':
-          case CR:
-          case LF:
-            SET_ERRNO(HPE_INVALID_URL);
-            goto error;
-          default:
-            UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
-            if (UNLIKELY(CURRENT_STATE() == s_dead)) {
-              SET_ERRNO(HPE_INVALID_URL);
-              goto error;
-            }
-        }
-
-        break;
-      }
-
-      case s_req_server:
-      case s_req_server_with_at:
-      case s_req_path:
-      case s_req_query_string_start:
-      case s_req_query_string:
-      case s_req_fragment_start:
-      case s_req_fragment:
-      {
-        switch (ch) {
-          case ' ':
-            UPDATE_STATE(s_req_http_start);
-            CALLBACK_DATA(url);
-            break;
-          case CR:
-          case LF:
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            UPDATE_STATE((ch == CR) ?
-              s_req_line_almost_done :
-              s_header_field_start);
-            CALLBACK_DATA(url);
-            break;
-          default:
-            UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
-            if (UNLIKELY(CURRENT_STATE() == s_dead)) {
-              SET_ERRNO(HPE_INVALID_URL);
-              goto error;
-            }
-        }
-        break;
-      }
-
-      case s_req_http_start:
-        switch (ch) {
-          case 'H':
-            UPDATE_STATE(s_req_http_H);
-            break;
-          case ' ':
-            break;
-          default:
-            SET_ERRNO(HPE_INVALID_CONSTANT);
-            goto error;
-        }
-        break;
-
-      case s_req_http_H:
-        STRICT_CHECK(ch != 'T');
-        UPDATE_STATE(s_req_http_HT);
-        break;
-
-      case s_req_http_HT:
-        STRICT_CHECK(ch != 'T');
-        UPDATE_STATE(s_req_http_HTT);
-        break;
-
-      case s_req_http_HTT:
-        STRICT_CHECK(ch != 'P');
-        UPDATE_STATE(s_req_http_HTTP);
-        break;
-
-      case s_req_http_HTTP:
-        STRICT_CHECK(ch != '/');
-        UPDATE_STATE(s_req_http_major);
-        break;
-
-      case s_req_http_major:
-        if (UNLIKELY(!IS_NUM(ch))) {
-          SET_ERRNO(HPE_INVALID_VERSION);
-          goto error;
-        }
-
-        parser->http_major = ch - '0';
-        UPDATE_STATE(s_req_http_dot);
-        break;
-
-      case s_req_http_dot:
-      {
-        if (UNLIKELY(ch != '.')) {
-          SET_ERRNO(HPE_INVALID_VERSION);
-          goto error;
-        }
-
-        UPDATE_STATE(s_req_http_minor);
-        break;
-      }
-
-      case s_req_http_minor:
-        if (UNLIKELY(!IS_NUM(ch))) {
-          SET_ERRNO(HPE_INVALID_VERSION);
-          goto error;
-        }
-
-        parser->http_minor = ch - '0';
-        UPDATE_STATE(s_req_http_end);
-        break;
-
-      case s_req_http_end:
-      {
-        if (ch == CR) {
-          UPDATE_STATE(s_req_line_almost_done);
-          break;
-        }
-
-        if (ch == LF) {
-          UPDATE_STATE(s_header_field_start);
-          break;
-        }
-
-        SET_ERRNO(HPE_INVALID_VERSION);
-        goto error;
-        break;
-      }
-
-      /* end of request line */
-      case s_req_line_almost_done:
-      {
-        if (UNLIKELY(ch != LF)) {
-          SET_ERRNO(HPE_LF_EXPECTED);
-          goto error;
-        }
-
-        UPDATE_STATE(s_header_field_start);
-        break;
-      }
-
-      case s_header_field_start:
-      {
-        if (ch == CR) {
-          UPDATE_STATE(s_headers_almost_done);
-          break;
-        }
-
-        if (ch == LF) {
-          /* they might be just sending \n instead of \r\n so this would be
-           * the second \n to denote the end of headers*/
-          UPDATE_STATE(s_headers_almost_done);
-          REEXECUTE();
-        }
-
-        c = TOKEN(ch);
-
-        if (UNLIKELY(!c)) {
-          SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
-          goto error;
-        }
-
-        MARK(header_field);
-
-        parser->index = 0;
-        UPDATE_STATE(s_header_field);
-
-        switch (c) {
-          case 'c':
-            parser->header_state = h_C;
-            break;
-
-          case 'p':
-            parser->header_state = h_matching_proxy_connection;
-            break;
-
-          case 't':
-            parser->header_state = h_matching_transfer_encoding;
-            break;
-
-          case 'u':
-            parser->header_state = h_matching_upgrade;
-            break;
-
-          default:
-            parser->header_state = h_general;
-            break;
-        }
-        break;
-      }
-
-      case s_header_field:
-      {
-        const char* start = p;
-        for (; p != data + len; p++) {
-          ch = *p;
-          c = TOKEN(ch);
-
-          if (!c)
-            break;
-
-          switch (parser->header_state) {
-            case h_general: {
-              size_t limit = data + len - p;
-              limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
-              while (p+1 < data + limit && TOKEN(p[1])) {
-                p++;
-              }
-              break;
-            }
-
-            case h_C:
-              parser->index++;
-              parser->header_state = (c == 'o' ? h_CO : h_general);
-              break;
-
-            case h_CO:
-              parser->index++;
-              parser->header_state = (c == 'n' ? h_CON : h_general);
-              break;
-
-            case h_CON:
-              parser->index++;
-              switch (c) {
-                case 'n':
-                  parser->header_state = h_matching_connection;
-                  break;
-                case 't':
-                  parser->header_state = h_matching_content_length;
-                  break;
-                default:
-                  parser->header_state = h_general;
-                  break;
-              }
-              break;
-
-            /* connection */
-
-            case h_matching_connection:
-              parser->index++;
-              if (parser->index > sizeof(CONNECTION)-1
-                  || c != CONNECTION[parser->index]) {
-                parser->header_state = h_general;
-              } else if (parser->index == sizeof(CONNECTION)-2) {
-                parser->header_state = h_connection;
-              }
-              break;
-
-            /* proxy-connection */
-
-            case h_matching_proxy_connection:
-              parser->index++;
-              if (parser->index > sizeof(PROXY_CONNECTION)-1
-                  || c != PROXY_CONNECTION[parser->index]) {
-                parser->header_state = h_general;
-              } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {
-                parser->header_state = h_connection;
-              }
-              break;
-
-            /* content-length */
-
-            case h_matching_content_length:
-              parser->index++;
-              if (parser->index > sizeof(CONTENT_LENGTH)-1
-                  || c != CONTENT_LENGTH[parser->index]) {
-                parser->header_state = h_general;
-              } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {
-                parser->header_state = h_content_length;
-              }
-              break;
-
-            /* transfer-encoding */
-
-            case h_matching_transfer_encoding:
-              parser->index++;
-              if (parser->index > sizeof(TRANSFER_ENCODING)-1
-                  || c != TRANSFER_ENCODING[parser->index]) {
-                parser->header_state = h_general;
-              } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
-                parser->header_state = h_transfer_encoding;
-              }
-              break;
-
-            /* upgrade */
-
-            case h_matching_upgrade:
-              parser->index++;
-              if (parser->index > sizeof(UPGRADE)-1
-                  || c != UPGRADE[parser->index]) {
-                parser->header_state = h_general;
-              } else if (parser->index == sizeof(UPGRADE)-2) {
-                parser->header_state = h_upgrade;
-              }
-              break;
-
-            case h_connection:
-            case h_content_length:
-            case h_transfer_encoding:
-            case h_upgrade:
-              if (ch != ' ') parser->header_state = h_general;
-              break;
-
-            default:
-              assert(0 && "Unknown header_state");
-              break;
-          }
-        }
-
-        if (p == data + len) {
-          --p;
-          COUNT_HEADER_SIZE(p - start);
-          break;
-        }
-
-        COUNT_HEADER_SIZE(p - start);
-
-        if (ch == ':') {
-          UPDATE_STATE(s_header_value_discard_ws);
-          CALLBACK_DATA(header_field);
-          break;
-        }
-
-        SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
-        goto error;
-      }
-
-      case s_header_value_discard_ws:
-        if (ch == ' ' || ch == '\t') break;
-
-        if (ch == CR) {
-          UPDATE_STATE(s_header_value_discard_ws_almost_done);
-          break;
-        }
-
-        if (ch == LF) {
-          UPDATE_STATE(s_header_value_discard_lws);
-          break;
-        }
-
-        /* fall through */
-
-      case s_header_value_start:
-      {
-        MARK(header_value);
-
-        UPDATE_STATE(s_header_value);
-        parser->index = 0;
-
-        c = LOWER(ch);
-
-        switch (parser->header_state) {
-          case h_upgrade:
-            parser->flags |= F_UPGRADE;
-            parser->header_state = h_general;
-            break;
-
-          case h_transfer_encoding:
-            /* looking for 'Transfer-Encoding: chunked' */
-            if ('c' == c) {
-              parser->header_state = h_matching_transfer_encoding_chunked;
-            } else {
-              parser->header_state = h_general;
-            }
-            break;
-
-          case h_content_length:
-            if (UNLIKELY(!IS_NUM(ch))) {
-              SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
-              goto error;
-            }
-
-            if (parser->flags & F_CONTENTLENGTH) {
-              SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
-              goto error;
-            }
-
-            parser->flags |= F_CONTENTLENGTH;
-            parser->content_length = ch - '0';
-            parser->header_state = h_content_length_num;
-            break;
-
-          case h_connection:
-            /* looking for 'Connection: keep-alive' */
-            if (c == 'k') {
-              parser->header_state = h_matching_connection_keep_alive;
-            /* looking for 'Connection: close' */
-            } else if (c == 'c') {
-              parser->header_state = h_matching_connection_close;
-            } else if (c == 'u') {
-              parser->header_state = h_matching_connection_upgrade;
-            } else {
-              parser->header_state = h_matching_connection_token;
-            }
-            break;
-
-          /* Multi-value `Connection` header */
-          case h_matching_connection_token_start:
-            break;
-
-          default:
-            parser->header_state = h_general;
-            break;
-        }
-        break;
-      }
-
-      case s_header_value:
-      {
-        const char* start = p;
-        enum header_states h_state = (enum header_states) parser->header_state;
-        for (; p != data + len; p++) {
-          ch = *p;
-          if (ch == CR) {
-            UPDATE_STATE(s_header_almost_done);
-            parser->header_state = h_state;
-            CALLBACK_DATA(header_value);
-            break;
-          }
-
-          if (ch == LF) {
-            UPDATE_STATE(s_header_almost_done);
-            COUNT_HEADER_SIZE(p - start);
-            parser->header_state = h_state;
-            CALLBACK_DATA_NOADVANCE(header_value);
-            REEXECUTE();
-          }
-
-          if (!lenient && !IS_HEADER_CHAR(ch)) {
-            SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
-            goto error;
-          }
-
-          c = LOWER(ch);
-
-          switch (h_state) {
-            case h_general:
-            {
-              const char* p_cr;
-              const char* p_lf;
-              size_t limit = data + len - p;
-
-              limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
-
-              p_cr = (const char*) memchr(p, CR, limit);
-              p_lf = (const char*) memchr(p, LF, limit);
-              if (p_cr != NULL) {
-                if (p_lf != NULL && p_cr >= p_lf)
-                  p = p_lf;
-                else
-                  p = p_cr;
-              } else if (UNLIKELY(p_lf != NULL)) {
-                p = p_lf;
-              } else {
-                p = data + len;
-              }
-              --p;
-              break;
-            }
-
-            case h_connection:
-            case h_transfer_encoding:
-              assert(0 && "Shouldn't get here.");
-              break;
-
-            case h_content_length:
-              if (ch == ' ') break;
-              h_state = h_content_length_num;
-              /* fall through */
-
-            case h_content_length_num:
-            {
-              uint64_t t;
-
-              if (ch == ' ') {
-                h_state = h_content_length_ws;
-                break;
-              }
-
-              if (UNLIKELY(!IS_NUM(ch))) {
-                SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
-                parser->header_state = h_state;
-                goto error;
-              }
-
-              t = parser->content_length;
-              t *= 10;
-              t += ch - '0';
-
-              /* Overflow? Test against a conservative limit for simplicity. */
-              if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) {
-                SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
-                parser->header_state = h_state;
-                goto error;
-              }
-
-              parser->content_length = t;
-              break;
-            }
-
-            case h_content_length_ws:
-              if (ch == ' ') break;
-              SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
-              parser->header_state = h_state;
-              goto error;
-
-            /* Transfer-Encoding: chunked */
-            case h_matching_transfer_encoding_chunked:
-              parser->index++;
-              if (parser->index > sizeof(CHUNKED)-1
-                  || c != CHUNKED[parser->index]) {
-                h_state = h_general;
-              } else if (parser->index == sizeof(CHUNKED)-2) {
-                h_state = h_transfer_encoding_chunked;
-              }
-              break;
-
-            case h_matching_connection_token_start:
-              /* looking for 'Connection: keep-alive' */
-              if (c == 'k') {
-                h_state = h_matching_connection_keep_alive;
-              /* looking for 'Connection: close' */
-              } else if (c == 'c') {
-                h_state = h_matching_connection_close;
-              } else if (c == 'u') {
-                h_state = h_matching_connection_upgrade;
-              } else if (STRICT_TOKEN(c)) {
-                h_state = h_matching_connection_token;
-              } else if (c == ' ' || c == '\t') {
-                /* Skip lws */
-              } else {
-                h_state = h_general;
-              }
-              break;
-
-            /* looking for 'Connection: keep-alive' */
-            case h_matching_connection_keep_alive:
-              parser->index++;
-              if (parser->index > sizeof(KEEP_ALIVE)-1
-                  || c != KEEP_ALIVE[parser->index]) {
-                h_state = h_matching_connection_token;
-              } else if (parser->index == sizeof(KEEP_ALIVE)-2) {
-                h_state = h_connection_keep_alive;
-              }
-              break;
-
-            /* looking for 'Connection: close' */
-            case h_matching_connection_close:
-              parser->index++;
-              if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {
-                h_state = h_matching_connection_token;
-              } else if (parser->index == sizeof(CLOSE)-2) {
-                h_state = h_connection_close;
-              }
-              break;
-
-            /* looking for 'Connection: upgrade' */
-            case h_matching_connection_upgrade:
-              parser->index++;
-              if (parser->index > sizeof(UPGRADE) - 1 ||
-                  c != UPGRADE[parser->index]) {
-                h_state = h_matching_connection_token;
-              } else if (parser->index == sizeof(UPGRADE)-2) {
-                h_state = h_connection_upgrade;
-              }
-              break;
-
-            case h_matching_connection_token:
-              if (ch == ',') {
-                h_state = h_matching_connection_token_start;
-                parser->index = 0;
-              }
-              break;
-
-            case h_transfer_encoding_chunked:
-              if (ch != ' ') h_state = h_general;
-              break;
-
-            case h_connection_keep_alive:
-            case h_connection_close:
-            case h_connection_upgrade:
-              if (ch == ',') {
-                if (h_state == h_connection_keep_alive) {
-                  parser->flags |= F_CONNECTION_KEEP_ALIVE;
-                } else if (h_state == h_connection_close) {
-                  parser->flags |= F_CONNECTION_CLOSE;
-                } else if (h_state == h_connection_upgrade) {
-                  parser->flags |= F_CONNECTION_UPGRADE;
-                }
-                h_state = h_matching_connection_token_start;
-                parser->index = 0;
-              } else if (ch != ' ') {
-                h_state = h_matching_connection_token;
-              }
-              break;
-
-            default:
-              UPDATE_STATE(s_header_value);
-              h_state = h_general;
-              break;
-          }
-        }
-        parser->header_state = h_state;
-
-        if (p == data + len)
-          --p;
-
-        COUNT_HEADER_SIZE(p - start);
-        break;
-      }
-
-      case s_header_almost_done:
-      {
-        if (UNLIKELY(ch != LF)) {
-          SET_ERRNO(HPE_LF_EXPECTED);
-          goto error;
-        }
-
-        UPDATE_STATE(s_header_value_lws);
-        break;
-      }
-
-      case s_header_value_lws:
-      {
-        if (ch == ' ' || ch == '\t') {
-          UPDATE_STATE(s_header_value_start);
-          REEXECUTE();
-        }
-
-        /* finished the header */
-        switch (parser->header_state) {
-          case h_connection_keep_alive:
-            parser->flags |= F_CONNECTION_KEEP_ALIVE;
-            break;
-          case h_connection_close:
-            parser->flags |= F_CONNECTION_CLOSE;
-            break;
-          case h_transfer_encoding_chunked:
-            parser->flags |= F_CHUNKED;
-            break;
-          case h_connection_upgrade:
-            parser->flags |= F_CONNECTION_UPGRADE;
-            break;
-          default:
-            break;
-        }
-
-        UPDATE_STATE(s_header_field_start);
-        REEXECUTE();
-      }
-
-      case s_header_value_discard_ws_almost_done:
-      {
-        STRICT_CHECK(ch != LF);
-        UPDATE_STATE(s_header_value_discard_lws);
-        break;
-      }
-
-      case s_header_value_discard_lws:
-      {
-        if (ch == ' ' || ch == '\t') {
-          UPDATE_STATE(s_header_value_discard_ws);
-          break;
-        } else {
-          switch (parser->header_state) {
-            case h_connection_keep_alive:
-              parser->flags |= F_CONNECTION_KEEP_ALIVE;
-              break;
-            case h_connection_close:
-              parser->flags |= F_CONNECTION_CLOSE;
-              break;
-            case h_connection_upgrade:
-              parser->flags |= F_CONNECTION_UPGRADE;
-              break;
-            case h_transfer_encoding_chunked:
-              parser->flags |= F_CHUNKED;
-              break;
-            default:
-              break;
-          }
-
-          /* header value was empty */
-          MARK(header_value);
-          UPDATE_STATE(s_header_field_start);
-          CALLBACK_DATA_NOADVANCE(header_value);
-          REEXECUTE();
-        }
-      }
-
-      case s_headers_almost_done:
-      {
-        STRICT_CHECK(ch != LF);
-
-        if (parser->flags & F_TRAILING) {
-          /* End of a chunked request */
-          UPDATE_STATE(s_message_done);
-          CALLBACK_NOTIFY_NOADVANCE(chunk_complete);
-          REEXECUTE();
-        }
-
-        /* Cannot use chunked encoding and a content-length header together
-           per the HTTP specification. */
-        if ((parser->flags & F_CHUNKED) &&
-            (parser->flags & F_CONTENTLENGTH)) {
-          SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
-          goto error;
-        }
-
-        UPDATE_STATE(s_headers_done);
-
-        /* Set this here so that on_headers_complete() callbacks can see it */
-        if ((parser->flags & F_UPGRADE) &&
-            (parser->flags & F_CONNECTION_UPGRADE)) {
-          /* For responses, "Upgrade: foo" and "Connection: upgrade" are
-           * mandatory only when it is a 101 Switching Protocols response,
-           * otherwise it is purely informational, to announce support.
-           */
-          parser->upgrade =
-              (parser->type == HTTP_REQUEST || parser->status_code == 101);
-        } else {
-          parser->upgrade = (parser->method == HTTP_CONNECT);
-        }
-
-        /* Here we call the headers_complete callback. This is somewhat
-         * different than other callbacks because if the user returns 1, we
-         * will interpret that as saying that this message has no body. This
-         * is needed for the annoying case of receiving a response to a HEAD
-         * request.
-         *
-         * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
-         * we have to simulate it by handling a change in errno below.
-         */
-        if (settings->on_headers_complete) {
-          switch (settings->on_headers_complete(parser)) {
-            case 0:
-              break;
-
-            case 2:
-              parser->upgrade = 1;
-
-              /* fall through */
-            case 1:
-              parser->flags |= F_SKIPBODY;
-              break;
-
-            default:
-              SET_ERRNO(HPE_CB_headers_complete);
-              RETURN(p - data); /* Error */
-          }
-        }
-
-        if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
-          RETURN(p - data);
-        }
-
-        REEXECUTE();
-      }
-
-      case s_headers_done:
-      {
-        int hasBody;
-        STRICT_CHECK(ch != LF);
-
-        parser->nread = 0;
-        nread = 0;
-
-        hasBody = parser->flags & F_CHUNKED ||
-          (parser->content_length > 0 && parser->content_length != ULLONG_MAX);
-        if (parser->upgrade && (parser->method == HTTP_CONNECT ||
-                                (parser->flags & F_SKIPBODY) || !hasBody)) {
-          /* Exit, the rest of the message is in a different protocol. */
-          UPDATE_STATE(NEW_MESSAGE());
-          CALLBACK_NOTIFY(message_complete);
-          RETURN((p - data) + 1);
-        }
-
-        if (parser->flags & F_SKIPBODY) {
-          UPDATE_STATE(NEW_MESSAGE());
-          CALLBACK_NOTIFY(message_complete);
-        } else if (parser->flags & F_CHUNKED) {
-          /* chunked encoding - ignore Content-Length header */
-          UPDATE_STATE(s_chunk_size_start);
-        } else {
-          if (parser->content_length == 0) {
-            /* Content-Length header given but zero: Content-Length: 0\r\n */
-            UPDATE_STATE(NEW_MESSAGE());
-            CALLBACK_NOTIFY(message_complete);
-          } else if (parser->content_length != ULLONG_MAX) {
-            /* Content-Length header given and non-zero */
-            UPDATE_STATE(s_body_identity);
-          } else {
-            if (!http_message_needs_eof(parser)) {
-              /* Assume content-length 0 - read the next */
-              UPDATE_STATE(NEW_MESSAGE());
-              CALLBACK_NOTIFY(message_complete);
-            } else {
-              /* Read body until EOF */
-              UPDATE_STATE(s_body_identity_eof);
-            }
-          }
-        }
-
-        break;
-      }
-
-      case s_body_identity:
-      {
-        uint64_t to_read = MIN(parser->content_length,
-                               (uint64_t) ((data + len) - p));
-
-        assert(parser->content_length != 0
-            && parser->content_length != ULLONG_MAX);
-
-        /* The difference between advancing content_length and p is because
-         * the latter will automaticaly advance on the next loop iteration.
-         * Further, if content_length ends up at 0, we want to see the last
-         * byte again for our message complete callback.
-         */
-        MARK(body);
-        parser->content_length -= to_read;
-        p += to_read - 1;
-
-        if (parser->content_length == 0) {
-          UPDATE_STATE(s_message_done);
-
-          /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
-           *
-           * The alternative to doing this is to wait for the next byte to
-           * trigger the data callback, just as in every other case. The
-           * problem with this is that this makes it difficult for the test
-           * harness to distinguish between complete-on-EOF and
-           * complete-on-length. It's not clear that this distinction is
-           * important for applications, but let's keep it for now.
-           */
-          CALLBACK_DATA_(body, p - body_mark + 1, p - data);
-          REEXECUTE();
-        }
-
-        break;
-      }
-
-      /* read until EOF */
-      case s_body_identity_eof:
-        MARK(body);
-        p = data + len - 1;
-
-        break;
-
-      case s_message_done:
-        UPDATE_STATE(NEW_MESSAGE());
-        CALLBACK_NOTIFY(message_complete);
-        if (parser->upgrade) {
-          /* Exit, the rest of the message is in a different protocol. */
-          RETURN((p - data) + 1);
-        }
-        break;
-
-      case s_chunk_size_start:
-      {
-        assert(nread == 1);
-        assert(parser->flags & F_CHUNKED);
-
-        unhex_val = unhex[(unsigned char)ch];
-        if (UNLIKELY(unhex_val == -1)) {
-          SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
-          goto error;
-        }
-
-        parser->content_length = unhex_val;
-        UPDATE_STATE(s_chunk_size);
-        break;
-      }
-
-      case s_chunk_size:
-      {
-        uint64_t t;
-
-        assert(parser->flags & F_CHUNKED);
-
-        if (ch == CR) {
-          UPDATE_STATE(s_chunk_size_almost_done);
-          break;
-        }
-
-        unhex_val = unhex[(unsigned char)ch];
-
-        if (unhex_val == -1) {
-          if (ch == ';' || ch == ' ') {
-            UPDATE_STATE(s_chunk_parameters);
-            break;
-          }
-
-          SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
-          goto error;
-        }
-
-        t = parser->content_length;
-        t *= 16;
-        t += unhex_val;
-
-        /* Overflow? Test against a conservative limit for simplicity. */
-        if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) {
-          SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
-          goto error;
-        }
-
-        parser->content_length = t;
-        break;
-      }
-
-      case s_chunk_parameters:
-      {
-        assert(parser->flags & F_CHUNKED);
-        /* just ignore this shit. TODO check for overflow */
-        if (ch == CR) {
-          UPDATE_STATE(s_chunk_size_almost_done);
-          break;
-        }
-        break;
-      }
-
-      case s_chunk_size_almost_done:
-      {
-        assert(parser->flags & F_CHUNKED);
-        STRICT_CHECK(ch != LF);
-
-        parser->nread = 0;
-        nread = 0;
-
-        if (parser->content_length == 0) {
-          parser->flags |= F_TRAILING;
-          UPDATE_STATE(s_header_field_start);
-        } else {
-          UPDATE_STATE(s_chunk_data);
-        }
-        CALLBACK_NOTIFY(chunk_header);
-        break;
-      }
-
-      case s_chunk_data:
-      {
-        uint64_t to_read = MIN(parser->content_length,
-                               (uint64_t) ((data + len) - p));
-
-        assert(parser->flags & F_CHUNKED);
-        assert(parser->content_length != 0
-            && parser->content_length != ULLONG_MAX);
-
-        /* See the explanation in s_body_identity for why the content
-         * length and data pointers are managed this way.
-         */
-        MARK(body);
-        parser->content_length -= to_read;
-        p += to_read - 1;
-
-        if (parser->content_length == 0) {
-          UPDATE_STATE(s_chunk_data_almost_done);
-        }
-
-        break;
-      }
-
-      case s_chunk_data_almost_done:
-        assert(parser->flags & F_CHUNKED);
-        assert(parser->content_length == 0);
-        STRICT_CHECK(ch != CR);
-        UPDATE_STATE(s_chunk_data_done);
-        CALLBACK_DATA(body);
-        break;
-
-      case s_chunk_data_done:
-        assert(parser->flags & F_CHUNKED);
-        STRICT_CHECK(ch != LF);
-        parser->nread = 0;
-        nread = 0;
-        UPDATE_STATE(s_chunk_size_start);
-        CALLBACK_NOTIFY(chunk_complete);
-        break;
-
-      default:
-        assert(0 && "unhandled state");
-        SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
-        goto error;
-    }
-  }
-
-  /* Run callbacks for any marks that we have leftover after we ran our of
-   * bytes. There should be at most one of these set, so it's OK to invoke
-   * them in series (unset marks will not result in callbacks).
-   *
-   * We use the NOADVANCE() variety of callbacks here because 'p' has already
-   * overflowed 'data' and this allows us to correct for the off-by-one that
-   * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
-   * value that's in-bounds).
-   */
-
-  assert(((header_field_mark ? 1 : 0) +
-          (header_value_mark ? 1 : 0) +
-          (url_mark ? 1 : 0)  +
-          (body_mark ? 1 : 0) +
-          (status_mark ? 1 : 0)) <= 1);
-
-  CALLBACK_DATA_NOADVANCE(header_field);
-  CALLBACK_DATA_NOADVANCE(header_value);
-  CALLBACK_DATA_NOADVANCE(url);
-  CALLBACK_DATA_NOADVANCE(body);
-  CALLBACK_DATA_NOADVANCE(status);
-
-  RETURN(len);
-
-error:
-  if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
-    SET_ERRNO(HPE_UNKNOWN);
-  }
-
-  RETURN(p - data);
-}
-
-
-/* Does the parser need to see an EOF to find the end of the message? */
-int
-http_message_needs_eof (const http_parser *parser)
-{
-  if (parser->type == HTTP_REQUEST) {
-    return 0;
-  }
-
-  /* See RFC 2616 section 4.4 */
-  if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
-      parser->status_code == 204 ||     /* No Content */
-      parser->status_code == 304 ||     /* Not Modified */
-      parser->flags & F_SKIPBODY) {     /* response to a HEAD request */
-    return 0;
-  }
-
-  if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {
-    return 0;
-  }
-
-  return 1;
-}
-
-
-int
-http_should_keep_alive (const http_parser *parser)
-{
-  if (parser->http_major > 0 && parser->http_minor > 0) {
-    /* HTTP/1.1 */
-    if (parser->flags & F_CONNECTION_CLOSE) {
-      return 0;
-    }
-  } else {
-    /* HTTP/1.0 or earlier */
-    if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
-      return 0;
-    }
-  }
-
-  return !http_message_needs_eof(parser);
-}
-
-
-const char *
-http_method_str (enum http_method m)
-{
-  return ELEM_AT(method_strings, m, "<unknown>");
-}
-
-const char *
-http_status_str (enum http_status s)
-{
-  switch (s) {
-#define XX(num, name, string) case HTTP_STATUS_##name: return #string;
-    HTTP_STATUS_MAP(XX)
-#undef XX
-    default: return "<unknown>";
-  }
-}
-
-void
-http_parser_init (http_parser *parser, enum http_parser_type t)
-{
-  void *data = parser->data; /* preserve application data */
-  memset(parser, 0, sizeof(*parser));
-  parser->data = data;
-  parser->type = t;
-  parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
-  parser->http_errno = HPE_OK;
-}
-
-void
-http_parser_settings_init(http_parser_settings *settings)
-{
-  memset(settings, 0, sizeof(*settings));
-}
-
-const char *
-http_errno_name(enum http_errno err) {
-  assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
-  return http_strerror_tab[err].name;
-}
-
-const char *
-http_errno_description(enum http_errno err) {
-  assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
-  return http_strerror_tab[err].description;
-}
-
-static enum http_host_state
-http_parse_host_char(enum http_host_state s, const char ch) {
-  switch(s) {
-    case s_http_userinfo:
-    case s_http_userinfo_start:
-      if (ch == '@') {
-        return s_http_host_start;
-      }
-
-      if (IS_USERINFO_CHAR(ch)) {
-        return s_http_userinfo;
-      }
-      break;
-
-    case s_http_host_start:
-      if (ch == '[') {
-        return s_http_host_v6_start;
-      }
-
-      if (IS_HOST_CHAR(ch)) {
-        return s_http_host;
-      }
-
-      break;
-
-    case s_http_host:
-      if (IS_HOST_CHAR(ch)) {
-        return s_http_host;
-      }
-
-    /* fall through */
-    case s_http_host_v6_end:
-      if (ch == ':') {
-        return s_http_host_port_start;
-      }
-
-      break;
-
-    case s_http_host_v6:
-      if (ch == ']') {
-        return s_http_host_v6_end;
-      }
-
-    /* fall through */
-    case s_http_host_v6_start:
-      if (IS_HEX(ch) || ch == ':' || ch == '.') {
-        return s_http_host_v6;
-      }
-
-      if (s == s_http_host_v6 && ch == '%') {
-        return s_http_host_v6_zone_start;
-      }
-      break;
-
-    case s_http_host_v6_zone:
-      if (ch == ']') {
-        return s_http_host_v6_end;
-      }
-
-    /* fall through */
-    case s_http_host_v6_zone_start:
-      /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
-      if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
-          ch == '~') {
-        return s_http_host_v6_zone;
-      }
-      break;
-
-    case s_http_host_port:
-    case s_http_host_port_start:
-      if (IS_NUM(ch)) {
-        return s_http_host_port;
-      }
-
-      break;
-
-    default:
-      break;
-  }
-  return s_http_host_dead;
-}
-
-static int
-http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
-  enum http_host_state s;
-
-  const char *p;
-  size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;
-
-  assert(u->field_set & (1 << UF_HOST));
-
-  u->field_data[UF_HOST].len = 0;
-
-  s = found_at ? s_http_userinfo_start : s_http_host_start;
-
-  for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {
-    enum http_host_state new_s = http_parse_host_char(s, *p);
-
-    if (new_s == s_http_host_dead) {
-      return 1;
-    }
-
-    switch(new_s) {
-      case s_http_host:
-        if (s != s_http_host) {
-          u->field_data[UF_HOST].off = p - buf;
-        }
-        u->field_data[UF_HOST].len++;
-        break;
-
-      case s_http_host_v6:
-        if (s != s_http_host_v6) {
-          u->field_data[UF_HOST].off = p - buf;
-        }
-        u->field_data[UF_HOST].len++;
-        break;
-
-      case s_http_host_v6_zone_start:
-      case s_http_host_v6_zone:
-        u->field_data[UF_HOST].len++;
-        break;
-
-      case s_http_host_port:
-        if (s != s_http_host_port) {
-          u->field_data[UF_PORT].off = p - buf;
-          u->field_data[UF_PORT].len = 0;
-          u->field_set |= (1 << UF_PORT);
-        }
-        u->field_data[UF_PORT].len++;
-        break;
-
-      case s_http_userinfo:
-        if (s != s_http_userinfo) {
-          u->field_data[UF_USERINFO].off = p - buf ;
-          u->field_data[UF_USERINFO].len = 0;
-          u->field_set |= (1 << UF_USERINFO);
-        }
-        u->field_data[UF_USERINFO].len++;
-        break;
-
-      default:
-        break;
-    }
-    s = new_s;
-  }
-
-  /* Make sure we don't end somewhere unexpected */
-  switch (s) {
-    case s_http_host_start:
-    case s_http_host_v6_start:
-    case s_http_host_v6:
-    case s_http_host_v6_zone_start:
-    case s_http_host_v6_zone:
-    case s_http_host_port_start:
-    case s_http_userinfo:
-    case s_http_userinfo_start:
-      return 1;
-    default:
-      break;
-  }
-
-  return 0;
-}
-
-void
-http_parser_url_init(struct http_parser_url *u) {
-  memset(u, 0, sizeof(*u));
-}
-
-int
-http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
-                      struct http_parser_url *u)
-{
-  enum state s;
-  const char *p;
-  enum http_parser_url_fields uf, old_uf;
-  int found_at = 0;
-
-  if (buflen == 0) {
-    return 1;
-  }
-
-  u->port = u->field_set = 0;
-  s = is_connect ? s_req_server_start : s_req_spaces_before_url;
-  old_uf = UF_MAX;
-
-  for (p = buf; p < buf + buflen; p++) {
-    s = parse_url_char(s, *p);
-
-    /* Figure out the next field that we're operating on */
-    switch (s) {
-      case s_dead:
-        return 1;
-
-      /* Skip delimeters */
-      case s_req_schema_slash:
-      case s_req_schema_slash_slash:
-      case s_req_server_start:
-      case s_req_query_string_start:
-      case s_req_fragment_start:
-        continue;
-
-      case s_req_schema:
-        uf = UF_SCHEMA;
-        break;
-
-      case s_req_server_with_at:
-        found_at = 1;
-
-      /* fall through */
-      case s_req_server:
-        uf = UF_HOST;
-        break;
-
-      case s_req_path:
-        uf = UF_PATH;
-        break;
-
-      case s_req_query_string:
-        uf = UF_QUERY;
-        break;
-
-      case s_req_fragment:
-        uf = UF_FRAGMENT;
-        break;
-
-      default:
-        assert(!"Unexpected state");
-        return 1;
-    }
-
-    /* Nothing's changed; soldier on */
-    if (uf == old_uf) {
-      u->field_data[uf].len++;
-      continue;
-    }
-
-    u->field_data[uf].off = p - buf;
-    u->field_data[uf].len = 1;
-
-    u->field_set |= (1 << uf);
-    old_uf = uf;
-  }
-
-  /* host must be present if there is a schema */
-  /* parsing http:///toto will fail */
-  if ((u->field_set & (1 << UF_SCHEMA)) &&
-      (u->field_set & (1 << UF_HOST)) == 0) {
-    return 1;
-  }
-
-  if (u->field_set & (1 << UF_HOST)) {
-    if (http_parse_host(buf, u, found_at) != 0) {
-      return 1;
-    }
-  }
-
-  /* CONNECT requests can only contain "hostname:port" */
-  if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {
-    return 1;
-  }
-
-  if (u->field_set & (1 << UF_PORT)) {
-    uint16_t off;
-    uint16_t len;
-    const char* p;
-    const char* end;
-    unsigned long v;
-
-    off = u->field_data[UF_PORT].off;
-    len = u->field_data[UF_PORT].len;
-    end = buf + off + len;
-
-    /* NOTE: The characters are already validated and are in the [0-9] range */
-    assert(off + len <= buflen && "Port number overflow");
-    v = 0;
-    for (p = buf + off; p < end; p++) {
-      v *= 10;
-      v += *p - '0';
-
-      /* Ports have a max value of 2^16 */
-      if (v > 0xffff) {
-        return 1;
-      }
-    }
-
-    u->port = (uint16_t) v;
-  }
-
-  return 0;
-}
-
-void
-http_parser_pause(http_parser *parser, int paused) {
-  /* Users should only be pausing/unpausing a parser that is not in an error
-   * state. In non-debug builds, there's not much that we can do about this
-   * other than ignore it.
-   */
-  if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
-      HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
-    uint32_t nread = parser->nread; /* used by the SET_ERRNO macro */
-    SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
-  } else {
-    assert(0 && "Attempting to pause parser in error state");
-  }
-}
-
-int
-http_body_is_final(const struct http_parser *parser) {
-    return parser->state == s_message_done;
-}
-
-unsigned long
-http_parser_version(void) {
-  return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
-         HTTP_PARSER_VERSION_MINOR * 0x00100 |
-         HTTP_PARSER_VERSION_PATCH * 0x00001;
-}
-
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/cpp/jni/DataLogJNI.cpp b/wpiutil/src/main/native/cpp/jni/DataLogJNI.cpp
new file mode 100644
index 0000000..997b90b
--- /dev/null
+++ b/wpiutil/src/main/native/cpp/jni/DataLogJNI.cpp
@@ -0,0 +1,357 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include <jni.h>
+
+#include "edu_wpi_first_util_datalog_DataLogJNI.h"
+#include "wpi/DataLog.h"
+#include "wpi/jni_util.h"
+
+using namespace wpi::java;
+using namespace wpi::log;
+
+extern "C" {
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    create
+ * Signature: (Ljava/lang/String;Ljava/lang/String;DLjava/lang/String;)J
+ */
+JNIEXPORT jlong JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_create
+  (JNIEnv* env, jclass, jstring dir, jstring filename, jdouble period,
+   jstring extraHeader)
+{
+  return reinterpret_cast<jlong>(new DataLog{JStringRef{env, dir},
+                                             JStringRef{env, filename}, period,
+                                             JStringRef{env, extraHeader}});
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    setFilename
+ * Signature: (JLjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_setFilename
+  (JNIEnv* env, jclass, jlong impl, jstring filename)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->SetFilename(JStringRef{env, filename});
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    flush
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_flush
+  (JNIEnv*, jclass, jlong impl)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->Flush();
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    pause
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_pause
+  (JNIEnv*, jclass, jlong impl)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->Pause();
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    resume
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_resume
+  (JNIEnv*, jclass, jlong impl)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->Resume();
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    start
+ * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;J)I
+ */
+JNIEXPORT jint JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_start
+  (JNIEnv* env, jclass, jlong impl, jstring name, jstring type,
+   jstring metadata, jlong timestamp)
+{
+  if (impl == 0) {
+    return 0;
+  }
+  return reinterpret_cast<DataLog*>(impl)->Start(
+      JStringRef{env, name}, JStringRef{env, type}, JStringRef{env, metadata},
+      timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    finish
+ * Signature: (JIJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_finish
+  (JNIEnv*, jclass, jlong impl, jint entry, jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->Finish(entry, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    setMetadata
+ * Signature: (JILjava/lang/String;J)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_setMetadata
+  (JNIEnv* env, jclass, jlong impl, jint entry, jstring metadata,
+   jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->SetMetadata(
+      entry, JStringRef{env, metadata}, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    close
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_close
+  (JNIEnv*, jclass, jlong impl)
+{
+  delete reinterpret_cast<DataLog*>(impl);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendRaw
+ * Signature: (JI[BJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendRaw
+  (JNIEnv* env, jclass, jlong impl, jint entry, jbyteArray value,
+   jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  JByteArrayRef cvalue{env, value};
+  reinterpret_cast<DataLog*>(impl)->AppendRaw(
+      entry,
+      {reinterpret_cast<const uint8_t*>(cvalue.array().data()), cvalue.size()},
+      timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendBoolean
+ * Signature: (JIZJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendBoolean
+  (JNIEnv*, jclass, jlong impl, jint entry, jboolean value, jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendBoolean(entry, value, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendInteger
+ * Signature: (JIJJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendInteger
+  (JNIEnv*, jclass, jlong impl, jint entry, jlong value, jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendInteger(entry, value, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendFloat
+ * Signature: (JIFJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendFloat
+  (JNIEnv*, jclass, jlong impl, jint entry, jfloat value, jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendFloat(entry, value, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendDouble
+ * Signature: (JIDJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendDouble
+  (JNIEnv*, jclass, jlong impl, jint entry, jdouble value, jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendDouble(entry, value, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendString
+ * Signature: (JILjava/lang/String;J)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendString
+  (JNIEnv* env, jclass, jlong impl, jint entry, jstring value, jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendString(entry, JStringRef{env, value},
+                                                 timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendBooleanArray
+ * Signature: (JI[ZJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendBooleanArray
+  (JNIEnv* env, jclass, jlong impl, jint entry, jbooleanArray value,
+   jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendBooleanArray(
+      entry, JBooleanArrayRef{env, value}, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendIntegerArray
+ * Signature: (JI[JJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendIntegerArray
+  (JNIEnv* env, jclass, jlong impl, jint entry, jlongArray value,
+   jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  JLongArrayRef jarr{env, value};
+  if constexpr (sizeof(jlong) == sizeof(int64_t)) {
+    reinterpret_cast<DataLog*>(impl)->AppendIntegerArray(
+        entry,
+        {reinterpret_cast<const int64_t*>(jarr.array().data()),
+         jarr.array().size()},
+        timestamp);
+  } else {
+    wpi::SmallVector<int64_t, 16> arr;
+    arr.reserve(jarr.size());
+    for (auto v : jarr.array()) {
+      arr.push_back(v);
+    }
+    reinterpret_cast<DataLog*>(impl)->AppendIntegerArray(entry, arr, timestamp);
+  }
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendFloatArray
+ * Signature: (JI[FJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendFloatArray
+  (JNIEnv* env, jclass, jlong impl, jint entry, jfloatArray value,
+   jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendFloatArray(
+      entry, JFloatArrayRef{env, value}, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendDoubleArray
+ * Signature: (JI[DJ)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendDoubleArray
+  (JNIEnv* env, jclass, jlong impl, jint entry, jdoubleArray value,
+   jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendDoubleArray(
+      entry, JDoubleArrayRef{env, value}, timestamp);
+}
+
+/*
+ * Class:     edu_wpi_first_util_datalog_DataLogJNI
+ * Method:    appendStringArray
+ * Signature: (JI[Ljava/lang/Object;J)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_datalog_DataLogJNI_appendStringArray
+  (JNIEnv* env, jclass, jlong impl, jint entry, jobjectArray value,
+   jlong timestamp)
+{
+  if (impl == 0) {
+    return;
+  }
+  size_t len = env->GetArrayLength(value);
+  std::vector<std::string> arr;
+  arr.reserve(len);
+  for (size_t i = 0; i < len; ++i) {
+    JLocal<jstring> elem{
+        env, static_cast<jstring>(env->GetObjectArrayElement(value, i))};
+    if (!elem) {
+      return;
+    }
+    arr.emplace_back(JStringRef{env, elem}.str());
+  }
+  reinterpret_cast<DataLog*>(impl)->AppendStringArray(entry, arr, timestamp);
+}
+
+}  // extern "C"
diff --git a/wpiutil/src/main/native/cpp/jni/WPIUtilJNI.cpp b/wpiutil/src/main/native/cpp/jni/WPIUtilJNI.cpp
index e876d9c..5fa4ddf 100644
--- a/wpiutil/src/main/native/cpp/jni/WPIUtilJNI.cpp
+++ b/wpiutil/src/main/native/cpp/jni/WPIUtilJNI.cpp
@@ -4,14 +4,9 @@
 
 #include <jni.h>
 
-#include "../MulticastHandleManager.h"
 #include "edu_wpi_first_util_WPIUtilJNI.h"
-#include "wpi/DenseMap.h"
-#include "wpi/MulticastServiceAnnouncer.h"
-#include "wpi/MulticastServiceResolver.h"
-#include "wpi/PortForwarder.h"
+#include "fmt/format.h"
 #include "wpi/Synchronization.h"
-#include "wpi/UidVector.h"
 #include "wpi/jni_util.h"
 #include "wpi/timestamp.h"
 
@@ -21,8 +16,6 @@
 static uint64_t mockNow = 0;
 
 static JException interruptedEx;
-static JClass serviceDataCls;
-static JGlobal<jobjectArray> serviceDataEmptyArray;
 
 extern "C" {
 
@@ -37,17 +30,6 @@
     return JNI_ERR;
   }
 
-  serviceDataCls = JClass{env, "edu/wpi/first/util/ServiceData"};
-  if (!serviceDataCls) {
-    return JNI_ERR;
-  }
-
-  serviceDataEmptyArray = JGlobal<jobjectArray>{
-      env, env->NewObjectArray(0, serviceDataCls, nullptr)};
-  if (serviceDataEmptyArray == nullptr) {
-    return JNI_ERR;
-  }
-
   return JNI_VERSION_1_6;
 }
 
@@ -57,13 +39,23 @@
     return;
   }
 
-  serviceDataEmptyArray.free(env);
-  serviceDataCls.free(env);
   interruptedEx.free(env);
 }
 
 /*
  * Class:     edu_wpi_first_util_WPIUtilJNI
+ * Method:    writeStderr
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL
+Java_edu_wpi_first_util_WPIUtilJNI_writeStderr
+  (JNIEnv* env, jclass, jstring str)
+{
+  fmt::print(stderr, "{}", JStringRef{env, str});
+}
+
+/*
+ * Class:     edu_wpi_first_util_WPIUtilJNI
  * Method:    enableMockTime
  * Signature: ()V
  */
@@ -130,32 +122,6 @@
 
 /*
  * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    addPortForwarder
- * Signature: (ILjava/lang/String;I)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_addPortForwarder
-  (JNIEnv* env, jclass, jint port, jstring remoteHost, jint remotePort)
-{
-  wpi::PortForwarder::GetInstance().Add(static_cast<unsigned int>(port),
-                                        JStringRef{env, remoteHost}.str(),
-                                        static_cast<unsigned int>(remotePort));
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    removePortForwarder
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_removePortForwarder
-  (JNIEnv* env, jclass, jint port)
-{
-  wpi::PortForwarder::GetInstance().Remove(port);
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
  * Method:    createEvent
  * Signature: (ZZ)I
  */
@@ -281,7 +247,7 @@
   JIntArrayRef handlesArr{env, handles};
   wpi::SmallVector<WPI_Handle, 8> signaledBuf;
   signaledBuf.resize(handlesArr.size());
-  wpi::span<const WPI_Handle> handlesArr2{
+  std::span<const WPI_Handle> handlesArr2{
       reinterpret_cast<const WPI_Handle*>(handlesArr.array().data()),
       handlesArr.size()};
 
@@ -305,7 +271,7 @@
   JIntArrayRef handlesArr{env, handles};
   wpi::SmallVector<WPI_Handle, 8> signaledBuf;
   signaledBuf.resize(handlesArr.size());
-  wpi::span<const WPI_Handle> handlesArr2{
+  std::span<const WPI_Handle> handlesArr2{
       reinterpret_cast<const WPI_Handle*>(handlesArr.array().data()),
       handlesArr.size()};
 
@@ -319,257 +285,4 @@
   return MakeJIntArray(env, signaled);
 }
 
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    createMulticastServiceAnnouncer
- * Signature: (Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/Object;[Ljava/lang/Object;)I
- */
-JNIEXPORT jint JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_createMulticastServiceAnnouncer
-  (JNIEnv* env, jclass, jstring serviceName, jstring serviceType, jint port,
-   jobjectArray keys, jobjectArray values)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-
-  JStringRef serviceNameRef{env, serviceName};
-  JStringRef serviceTypeRef{env, serviceType};
-
-  size_t keysLen = env->GetArrayLength(keys);
-  wpi::SmallVector<std::pair<std::string, std::string>, 8> txtVec;
-  txtVec.reserve(keysLen);
-  for (size_t i = 0; i < keysLen; i++) {
-    JLocal<jstring> key{
-        env, static_cast<jstring>(env->GetObjectArrayElement(keys, i))};
-    JLocal<jstring> value{
-        env, static_cast<jstring>(env->GetObjectArrayElement(values, i))};
-
-    txtVec.emplace_back(std::pair<std::string, std::string>{
-        JStringRef{env, key}.str(), JStringRef{env, value}.str()});
-  }
-
-  auto announcer = std::make_unique<wpi::MulticastServiceAnnouncer>(
-      serviceNameRef.str(), serviceTypeRef.str(), port, txtVec);
-
-  size_t index = manager.handleIds.emplace_back(1);
-
-  manager.announcers[index] = std::move(announcer);
-
-  return static_cast<jint>(index);
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    freeMulticastServiceAnnouncer
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_freeMulticastServiceAnnouncer
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  manager.announcers[handle] = nullptr;
-  manager.handleIds.erase(handle);
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    startMulticastServiceAnnouncer
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_startMulticastServiceAnnouncer
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& announcer = manager.announcers[handle];
-  announcer->Start();
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    stopMulticastServiceAnnouncer
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_stopMulticastServiceAnnouncer
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& announcer = manager.announcers[handle];
-  announcer->Stop();
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    getMulticastServiceAnnouncerHasImplementation
- * Signature: (I)Z
- */
-JNIEXPORT jboolean JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceAnnouncerHasImplementation
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& announcer = manager.announcers[handle];
-  return announcer->HasImplementation();
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    createMulticastServiceResolver
- * Signature: (Ljava/lang/String;)I
- */
-JNIEXPORT jint JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_createMulticastServiceResolver
-  (JNIEnv* env, jclass, jstring serviceType)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  JStringRef serviceTypeRef{env, serviceType};
-
-  auto resolver =
-      std::make_unique<wpi::MulticastServiceResolver>(serviceTypeRef.str());
-
-  size_t index = manager.handleIds.emplace_back(2);
-
-  manager.resolvers[index] = std::move(resolver);
-
-  return static_cast<jint>(index);
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    freeMulticastServiceResolver
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_freeMulticastServiceResolver
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  manager.resolvers[handle] = nullptr;
-  manager.handleIds.erase(handle);
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    startMulticastServiceResolver
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_startMulticastServiceResolver
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& resolver = manager.resolvers[handle];
-  resolver->Start();
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    stopMulticastServiceResolver
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_stopMulticastServiceResolver
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& resolver = manager.resolvers[handle];
-  resolver->Stop();
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    getMulticastServiceResolverHasImplementation
- * Signature: (I)Z
- */
-JNIEXPORT jboolean JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverHasImplementation
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& resolver = manager.resolvers[handle];
-  return resolver->HasImplementation();
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    getMulticastServiceResolverEventHandle
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverEventHandle
-  (JNIEnv* env, jclass, jint handle)
-{
-  auto& manager = wpi::GetMulticastManager();
-  std::scoped_lock lock{manager.mutex};
-  auto& resolver = manager.resolvers[handle];
-  return resolver->GetEventHandle();
-}
-
-/*
- * Class:     edu_wpi_first_util_WPIUtilJNI
- * Method:    getMulticastServiceResolverData
- * Signature: (I)[Ljava/lang/Object;
- */
-JNIEXPORT jobjectArray JNICALL
-Java_edu_wpi_first_util_WPIUtilJNI_getMulticastServiceResolverData
-  (JNIEnv* env, jclass, jint handle)
-{
-  static jmethodID constructor =
-      env->GetMethodID(serviceDataCls, "<init>",
-                       "(JILjava/lang/String;Ljava/lang/String;[Ljava/lang/"
-                       "String;[Ljava/lang/String;)V");
-  auto& manager = wpi::GetMulticastManager();
-  std::vector<wpi::MulticastServiceResolver::ServiceData> allData;
-  {
-    std::scoped_lock lock{manager.mutex};
-    auto& resolver = manager.resolvers[handle];
-    allData = resolver->GetData();
-  }
-  if (allData.empty()) {
-    return serviceDataEmptyArray;
-  }
-
-  JLocal<jobjectArray> returnData{
-      env, env->NewObjectArray(allData.size(), serviceDataCls, nullptr)};
-
-  for (auto&& data : allData) {
-    JLocal<jstring> serviceName{env, MakeJString(env, data.serviceName)};
-    JLocal<jstring> hostName{env, MakeJString(env, data.hostName)};
-
-    wpi::SmallVector<std::string_view, 8> keysRef;
-    wpi::SmallVector<std::string_view, 8> valuesRef;
-
-    size_t index = 0;
-    for (auto&& txt : data.txt) {
-      keysRef.emplace_back(txt.first);
-      valuesRef.emplace_back(txt.second);
-    }
-
-    JLocal<jobjectArray> keys{env, MakeJStringArray(env, keysRef)};
-    JLocal<jobjectArray> values{env, MakeJStringArray(env, valuesRef)};
-
-    JLocal<jobject> dataItem{
-        env, env->NewObject(serviceDataCls, constructor,
-                            static_cast<jlong>(data.ipv4Address),
-                            static_cast<jint>(data.port), serviceName.obj(),
-                            hostName.obj(), keys.obj(), values.obj())};
-
-    env->SetObjectArrayElement(returnData, index, dataItem);
-    index++;
-  }
-
-  return returnData;
-}
-
 }  // extern "C"
diff --git a/wpiutil/src/main/native/cpp/leb128.cpp b/wpiutil/src/main/native/cpp/leb128.cpp
index 9657883..17fbeb9 100644
--- a/wpiutil/src/main/native/cpp/leb128.cpp
+++ b/wpiutil/src/main/native/cpp/leb128.cpp
@@ -7,7 +7,6 @@
 #include "wpi/SpanExtras.h"
 #include "wpi/raw_istream.h"
 #include "wpi/raw_ostream.h"
-#include "wpi/span.h"
 
 namespace wpi {
 
@@ -98,7 +97,7 @@
   return true;
 }
 
-std::optional<uint64_t> Uleb128Reader::ReadOne(span<const uint8_t>* in) {
+std::optional<uint64_t> Uleb128Reader::ReadOne(std::span<const uint8_t>* in) {
   while (!in->empty()) {
     uint8_t byte = in->front();
     *in = wpi::drop_front(*in);
diff --git a/wpiutil/src/main/native/cpp/llvm/ConvertUTFWrapper.cpp b/wpiutil/src/main/native/cpp/llvm/ConvertUTFWrapper.cpp
deleted file mode 100644
index db190d0..0000000
--- a/wpiutil/src/main/native/cpp/llvm/ConvertUTFWrapper.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----===
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "wpi/ConvertUTF.h"
-#include "wpi/SmallVector.h"
-#include <string>
-#include <vector>
-
-namespace wpi {
-
-bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
-  const UTF32 *SourceStart = &Source;
-  const UTF32 *SourceEnd = SourceStart + 1;
-  UTF8 *TargetStart = reinterpret_cast<UTF8 *>(ResultPtr);
-  UTF8 *TargetEnd = TargetStart + 4;
-  ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd,
-                                           &TargetStart, TargetEnd,
-                                           strictConversion);
-  if (CR != conversionOK)
-    return false;
-
-  ResultPtr = reinterpret_cast<char*>(TargetStart);
-  return true;
-}
-
-bool hasUTF16ByteOrderMark(span<const char> S) {
-  return (S.size() >= 2 &&
-          ((S[0] == '\xff' && S[1] == '\xfe') ||
-           (S[0] == '\xfe' && S[1] == '\xff')));
-}
-
-bool convertUTF16ToUTF8String(span<const UTF16> SrcUTF16,
-                              SmallVectorImpl<char> &DstUTF8) {
-  assert(DstUTF8.empty());
-
-  // Avoid OOB by returning early on empty input.
-  if (SrcUTF16.empty())
-    return true;
-
-  const UTF16 *Src = SrcUTF16.begin();
-  const UTF16 *SrcEnd = SrcUTF16.end();
-
-  // Byteswap if necessary.
-  std::vector<UTF16> ByteSwapped;
-  if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
-    ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
-    for (unsigned I = 0, E = ByteSwapped.size(); I != E; ++I)
-      ByteSwapped[I] = (ByteSwapped[I] << 8) | (ByteSwapped[I] >> 8);
-    Src = &ByteSwapped[0];
-    SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
-  }
-
-  // Skip the BOM for conversion.
-  if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE)
-    Src++;
-
-  // Just allocate enough space up front.  We'll shrink it later.  Allocate
-  // enough that we can fit a null terminator without reallocating.
-  DstUTF8.resize(SrcUTF16.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
-  UTF8 *Dst = reinterpret_cast<UTF8*>(&DstUTF8[0]);
-  UTF8 *DstEnd = Dst + DstUTF8.size();
-
-  ConversionResult CR =
-      ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
-  assert(CR != targetExhausted);
-
-  if (CR != conversionOK) {
-    DstUTF8.clear();
-    return false;
-  }
-
-  DstUTF8.resize(reinterpret_cast<char*>(Dst) - &DstUTF8[0]);
-  DstUTF8.push_back(0);
-  DstUTF8.pop_back();
-  return true;
-}
-
-bool convertUTF8ToUTF16String(std::string_view SrcUTF8,
-                              SmallVectorImpl<UTF16> &DstUTF16) {
-  assert(DstUTF16.empty());
-
-  // Avoid OOB by returning early on empty input.
-  if (SrcUTF8.empty()) {
-    DstUTF16.push_back(0);
-    DstUTF16.pop_back();
-    return true;
-  }
-
-  const UTF8 *Src = reinterpret_cast<const UTF8 *>(SrcUTF8.data());
-  const UTF8 *SrcEnd = reinterpret_cast<const UTF8 *>(SrcUTF8.data() + SrcUTF8.size());
-
-  // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding
-  // as UTF-16 should always require the same amount or less code units than the
-  // UTF-8 encoding.  Allocate one extra byte for the null terminator though,
-  // so that someone calling DstUTF16.data() gets a null terminated string.
-  // We resize down later so we don't have to worry that this over allocates.
-  DstUTF16.resize(SrcUTF8.size()+1);
-  UTF16 *Dst = &DstUTF16[0];
-  UTF16 *DstEnd = Dst + DstUTF16.size();
-
-  ConversionResult CR =
-      ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
-  assert(CR != targetExhausted);
-
-  if (CR != conversionOK) {
-    DstUTF16.clear();
-    return false;
-  }
-
-  DstUTF16.resize(Dst - &DstUTF16[0]);
-  DstUTF16.push_back(0);
-  DstUTF16.pop_back();
-  return true;
-}
-
-} // end namespace wpi
-
diff --git a/wpiutil/src/main/native/cpp/llvm/ManagedStatic.cpp b/wpiutil/src/main/native/cpp/llvm/ManagedStatic.cpp
deleted file mode 100644
index a8c82bf..0000000
--- a/wpiutil/src/main/native/cpp/llvm/ManagedStatic.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the ManagedStatic class and wpi_shutdown().
-//
-//===----------------------------------------------------------------------===//
-
-#include "wpi/ManagedStatic.h"
-#include "wpi/mutex.h"
-#include <cassert>
-#include <mutex>
-using namespace wpi;
-
-static const ManagedStaticBase *StaticList = nullptr;
-static wpi::mutex *ManagedStaticMutex = nullptr;
-static std::once_flag mutex_init_flag;
-
-static void initializeMutex() {
-  ManagedStaticMutex = new wpi::mutex();
-}
-
-static wpi::mutex* getManagedStaticMutex() {
-  std::call_once(mutex_init_flag, initializeMutex);
-  return ManagedStaticMutex;
-}
-
-void ManagedStaticBase::RegisterManagedStatic(void* created,
-                                              void (*Deleter)(void*)) const {
-  std::scoped_lock Lock(*getManagedStaticMutex());
-
-  if (!Ptr.load(std::memory_order_relaxed)) {
-    void *Tmp = created;
-
-    Ptr.store(Tmp, std::memory_order_release);
-    DeleterFn = Deleter;
-
-    // Add to list of managed statics.
-    Next = StaticList;
-    StaticList = this;
-  }
-}
-
-void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
-                                              void (*Deleter)(void*)) const {
-  assert(Creator);
-  std::scoped_lock Lock(*getManagedStaticMutex());
-
-  if (!Ptr.load(std::memory_order_relaxed)) {
-    void *Tmp = Creator();
-
-    Ptr.store(Tmp, std::memory_order_release);
-    DeleterFn = Deleter;
-
-    // Add to list of managed statics.
-    Next = StaticList;
-    StaticList = this;
-  }
-}
-
-void ManagedStaticBase::destroy() const {
-  assert(DeleterFn && "ManagedStatic not initialized correctly!");
-  assert(StaticList == this &&
-         "Not destroyed in reverse order of construction?");
-  // Unlink from list.
-  StaticList = Next;
-  Next = nullptr;
-
-  // Destroy memory.
-  DeleterFn(Ptr);
-
-  // Cleanup.
-  Ptr = nullptr;
-  DeleterFn = nullptr;
-}
-
-/// wpi_shutdown - Deallocate and destroy all ManagedStatic variables.
-void wpi::wpi_shutdown() {
-  std::scoped_lock Lock(*getManagedStaticMutex());
-
-  while (StaticList)
-    StaticList->destroy();
-}
diff --git a/wpiutil/src/main/native/cpp/llvm/SmallVector.cpp b/wpiutil/src/main/native/cpp/llvm/SmallVector.cpp
deleted file mode 100644
index 974fec9..0000000
--- a/wpiutil/src/main/native/cpp/llvm/SmallVector.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SmallVector class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "wpi/SmallVector.h"
-#include "wpi/MemAlloc.h"
-using namespace wpi;
-
-/// grow_pod - This is an implementation of the grow() method which only works
-/// on POD-like datatypes and is out of line to reduce code duplication.
-void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity,
-                               size_t TSize) {
-  // Ensure we can fit the new capacity in 32 bits.
-  if (MinCapacity > UINT32_MAX)
-    report_bad_alloc_error("SmallVector capacity overflow during allocation");
-
-  size_t NewCapacity = 2 * capacity() + 1; // Always grow.
-  NewCapacity =
-      std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX));
-
-  void *NewElts;
-  if (BeginX == FirstEl) {
-    NewElts = safe_malloc(NewCapacity * TSize);
-
-    // Copy the elements over.  No need to run dtors on PODs.
-    memcpy(NewElts, this->BeginX, size() * TSize);
-  } else {
-    // If this wasn't grown from the inline copy, grow the allocated space.
-    NewElts = safe_realloc(this->BeginX, NewCapacity * TSize);
-  }
-
-  this->BeginX = NewElts;
-  this->Capacity = NewCapacity;
-}
diff --git a/wpiutil/src/main/native/cpp/raw_socket_istream.cpp b/wpiutil/src/main/native/cpp/raw_socket_istream.cpp
deleted file mode 100644
index c6b759e..0000000
--- a/wpiutil/src/main/native/cpp/raw_socket_istream.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/raw_socket_istream.h"
-
-#include "wpi/NetworkStream.h"
-
-using namespace wpi;
-
-void raw_socket_istream::read_impl(void* data, size_t len) {
-  char* cdata = static_cast<char*>(data);
-  size_t pos = 0;
-
-  while (pos < len) {
-    NetworkStream::Error err;
-    size_t count = m_stream.receive(&cdata[pos], len - pos, &err, m_timeout);
-    if (count == 0) {
-      error_detected();
-      break;
-    }
-    pos += count;
-  }
-  set_read_count(pos);
-}
-
-void raw_socket_istream::close() {
-  m_stream.close();
-}
-
-size_t raw_socket_istream::in_avail() const {
-  return 0;
-}
diff --git a/wpiutil/src/main/native/cpp/raw_socket_ostream.cpp b/wpiutil/src/main/native/cpp/raw_socket_ostream.cpp
deleted file mode 100644
index af01c84..0000000
--- a/wpiutil/src/main/native/cpp/raw_socket_ostream.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/raw_socket_ostream.h"
-
-#include "wpi/NetworkStream.h"
-
-using namespace wpi;
-
-raw_socket_ostream::~raw_socket_ostream() {
-  flush();
-  if (m_shouldClose) {
-    close();
-  }
-}
-
-void raw_socket_ostream::write_impl(const char* data, size_t len) {
-  size_t pos = 0;
-
-  while (pos < len) {
-    NetworkStream::Error err;
-    size_t count = m_stream.send(&data[pos], len - pos, &err);
-    if (count == 0) {
-      error_detected();
-      return;
-    }
-    pos += count;
-  }
-}
-
-uint64_t raw_socket_ostream::current_pos() const {
-  return 0;
-}
-
-void raw_socket_ostream::close() {
-  if (!m_shouldClose) {
-    return;
-  }
-  flush();
-  m_stream.close();
-}
diff --git a/wpiutil/src/main/native/cpp/raw_uv_ostream.cpp b/wpiutil/src/main/native/cpp/raw_uv_ostream.cpp
deleted file mode 100644
index f055a2a..0000000
--- a/wpiutil/src/main/native/cpp/raw_uv_ostream.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/raw_uv_ostream.h"
-
-#include <cstring>
-
-using namespace wpi;
-
-void raw_uv_ostream::write_impl(const char* data, size_t len) {
-  while (len > 0) {
-    // allocate additional buffers as required
-    if (m_left == 0) {
-      m_bufs.emplace_back(m_alloc());
-      // we want bufs() to always be valid, so set len=0 and keep track of the
-      // amount of space remaining separately
-      m_left = m_bufs.back().len;
-      m_bufs.back().len = 0;
-      assert(m_left != 0);
-    }
-
-    size_t amt = (std::min)(m_left, len);
-    auto& buf = m_bufs.back();
-    std::memcpy(buf.base + buf.len, data, amt);
-    data += amt;
-    len -= amt;
-    buf.len += amt;
-    m_left -= amt;
-  }
-}
-
-uint64_t raw_uv_ostream::current_pos() const {
-  uint64_t size = 0;
-  for (auto&& buf : m_bufs) {
-    size += buf.len;
-  }
-  return size;
-}
diff --git a/wpiutil/src/main/native/cpp/sha1.cpp b/wpiutil/src/main/native/cpp/sha1.cpp
index 8ec7cb1..98dc543 100644
--- a/wpiutil/src/main/native/cpp/sha1.cpp
+++ b/wpiutil/src/main/native/cpp/sha1.cpp
@@ -217,7 +217,7 @@
 }
 
 void SHA1::Update(std::string_view s) {
-  raw_mem_istream is(span<const char>(s.data(), s.size()));
+  raw_mem_istream is(std::span<const char>(s.data(), s.size()));
   Update(is);
 }
 
diff --git a/wpiutil/src/main/native/cpp/uv/Async.cpp b/wpiutil/src/main/native/cpp/uv/Async.cpp
deleted file mode 100644
index c9d698e..0000000
--- a/wpiutil/src/main/native/cpp/uv/Async.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Async.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-Async<>::~Async() noexcept {
-  if (auto loop = m_loop.lock()) {
-    Close();
-  } else {
-    ForceClosed();
-  }
-}
-
-std::shared_ptr<Async<>> Async<>::Create(const std::shared_ptr<Loop>& loop) {
-  auto h = std::make_shared<Async>(loop, private_init{});
-  int err = uv_async_init(loop->GetRaw(), h->GetRaw(), [](uv_async_t* handle) {
-    Async& h = *static_cast<Async*>(handle->data);
-    h.wakeup();
-  });
-  if (err < 0) {
-    loop->ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Check.cpp b/wpiutil/src/main/native/cpp/uv/Check.cpp
deleted file mode 100644
index 97265d4..0000000
--- a/wpiutil/src/main/native/cpp/uv/Check.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Check.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Check> Check::Create(Loop& loop) {
-  auto h = std::make_shared<Check>(private_init{});
-  int err = uv_check_init(loop.GetRaw(), h->GetRaw());
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Check::Start() {
-  Invoke(&uv_check_start, GetRaw(), [](uv_check_t* handle) {
-    Check& h = *static_cast<Check*>(handle->data);
-    h.check();
-  });
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/FsEvent.cpp b/wpiutil/src/main/native/cpp/uv/FsEvent.cpp
deleted file mode 100644
index 3c83d1d..0000000
--- a/wpiutil/src/main/native/cpp/uv/FsEvent.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/FsEvent.h"
-
-#include <cstdlib>
-
-#include "wpi/SmallString.h"
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<FsEvent> FsEvent::Create(Loop& loop) {
-  auto h = std::make_shared<FsEvent>(private_init{});
-  int err = uv_fs_event_init(loop.GetRaw(), h->GetRaw());
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void FsEvent::Start(std::string_view path, unsigned int flags) {
-  SmallString<128> pathBuf{path};
-  Invoke(
-      &uv_fs_event_start, GetRaw(),
-      [](uv_fs_event_t* handle, const char* filename, int events, int status) {
-        FsEvent& h = *static_cast<FsEvent*>(handle->data);
-        if (status < 0) {
-          h.ReportError(status);
-        } else {
-          h.fsEvent(filename, events);
-        }
-      },
-      pathBuf.c_str(), flags);
-}
-
-std::string FsEvent::GetPath() {
-  // Per the libuv docs, GetPath() always gives us a null-terminated string.
-  // common case should be small
-  char buf[128];
-  size_t size = 128;
-  int r = uv_fs_event_getpath(GetRaw(), buf, &size);
-  if (r == 0) {
-    return buf;
-  } else if (r == UV_ENOBUFS) {
-    // need to allocate a big enough buffer
-    char* buf2 = static_cast<char*>(std::malloc(size));
-    r = uv_fs_event_getpath(GetRaw(), buf2, &size);
-    if (r == 0) {
-      std::string out{buf2};
-      std::free(buf2);
-      return out;
-    }
-    std::free(buf2);
-  }
-  ReportError(r);
-  return std::string{};
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/GetAddrInfo.cpp b/wpiutil/src/main/native/cpp/uv/GetAddrInfo.cpp
deleted file mode 100644
index 2e6e38f..0000000
--- a/wpiutil/src/main/native/cpp/uv/GetAddrInfo.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/GetAddrInfo.h"
-
-#include "wpi/SmallString.h"
-#include "wpi/uv/Loop.h"
-#include "wpi/uv/util.h"
-
-namespace wpi::uv {
-
-GetAddrInfoReq::GetAddrInfoReq() {
-  error = [this](Error err) { GetLoop().error(err); };
-}
-
-void GetAddrInfo(Loop& loop, const std::shared_ptr<GetAddrInfoReq>& req,
-                 std::string_view node, std::string_view service,
-                 const addrinfo* hints) {
-  SmallString<128> nodeStr{node};
-  SmallString<128> serviceStr{service};
-  int err = uv_getaddrinfo(
-      loop.GetRaw(), req->GetRaw(),
-      [](uv_getaddrinfo_t* req, int status, addrinfo* res) {
-        auto& h = *static_cast<GetAddrInfoReq*>(req->data);
-        if (status < 0) {
-          h.ReportError(status);
-        } else {
-          h.resolved(*res);
-        }
-        uv_freeaddrinfo(res);
-        h.Release();  // this is always a one-shot
-      },
-      node.empty() ? nullptr : nodeStr.c_str(),
-      service.empty() ? nullptr : serviceStr.c_str(), hints);
-  if (err < 0) {
-    loop.ReportError(err);
-  } else {
-    req->Keep();
-  }
-}
-
-void GetAddrInfo(Loop& loop, std::function<void(const addrinfo&)> callback,
-                 std::string_view node, std::string_view service,
-                 const addrinfo* hints) {
-  auto req = std::make_shared<GetAddrInfoReq>();
-  req->resolved.connect(std::move(callback));
-  GetAddrInfo(loop, req, node, service, hints);
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/GetNameInfo.cpp b/wpiutil/src/main/native/cpp/uv/GetNameInfo.cpp
deleted file mode 100644
index 4e662f3..0000000
--- a/wpiutil/src/main/native/cpp/uv/GetNameInfo.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/GetNameInfo.h"
-
-#include "wpi/uv/Loop.h"
-#include "wpi/uv/util.h"
-
-namespace wpi::uv {
-
-GetNameInfoReq::GetNameInfoReq() {
-  error = [this](Error err) { GetLoop().error(err); };
-}
-
-void GetNameInfo(Loop& loop, const std::shared_ptr<GetNameInfoReq>& req,
-                 const sockaddr& addr, int flags) {
-  int err = uv_getnameinfo(
-      loop.GetRaw(), req->GetRaw(),
-      [](uv_getnameinfo_t* req, int status, const char* hostname,
-         const char* service) {
-        auto& h = *static_cast<GetNameInfoReq*>(req->data);
-        if (status < 0) {
-          h.ReportError(status);
-        } else {
-          h.resolved(hostname, service);
-        }
-        h.Release();  // this is always a one-shot
-      },
-      &addr, flags);
-  if (err < 0) {
-    loop.ReportError(err);
-  } else {
-    req->Keep();
-  }
-}
-
-void GetNameInfo(Loop& loop,
-                 std::function<void(const char*, const char*)> callback,
-                 const sockaddr& addr, int flags) {
-  auto req = std::make_shared<GetNameInfoReq>();
-  req->resolved.connect(std::move(callback));
-  GetNameInfo(loop, req, addr, flags);
-}
-
-void GetNameInfo4(Loop& loop, const std::shared_ptr<GetNameInfoReq>& req,
-                  std::string_view ip, unsigned int port, int flags) {
-  sockaddr_in addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    loop.ReportError(err);
-  } else {
-    GetNameInfo(loop, req, reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-}
-
-void GetNameInfo4(Loop& loop,
-                  std::function<void(const char*, const char*)> callback,
-                  std::string_view ip, unsigned int port, int flags) {
-  sockaddr_in addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    loop.ReportError(err);
-  } else {
-    GetNameInfo(loop, std::move(callback),
-                reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-}
-
-void GetNameInfo6(Loop& loop, const std::shared_ptr<GetNameInfoReq>& req,
-                  std::string_view ip, unsigned int port, int flags) {
-  sockaddr_in6 addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    loop.ReportError(err);
-  } else {
-    GetNameInfo(loop, req, reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-}
-
-void GetNameInfo6(Loop& loop,
-                  std::function<void(const char*, const char*)> callback,
-                  std::string_view ip, unsigned int port, int flags) {
-  sockaddr_in6 addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    loop.ReportError(err);
-  } else {
-    GetNameInfo(loop, std::move(callback),
-                reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Handle.cpp b/wpiutil/src/main/native/cpp/uv/Handle.cpp
deleted file mode 100644
index 74c4c60..0000000
--- a/wpiutil/src/main/native/cpp/uv/Handle.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Handle.h"
-
-using namespace wpi::uv;
-
-Handle::~Handle() noexcept {
-  if (!m_closed && m_uv_handle->type != UV_UNKNOWN_HANDLE) {
-    uv_close(m_uv_handle, [](uv_handle_t* uv_handle) { std::free(uv_handle); });
-  } else {
-    std::free(m_uv_handle);
-  }
-}
-
-void Handle::Close() noexcept {
-  if (!IsClosing()) {
-    uv_close(m_uv_handle, [](uv_handle_t* handle) {
-      Handle& h = *static_cast<Handle*>(handle->data);
-      h.closed();
-      h.Release();  // free ourselves
-    });
-    m_closed = true;
-  }
-}
-
-void Handle::AllocBuf(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
-  auto& h = *static_cast<Handle*>(handle->data);
-  *buf = h.m_allocBuf(size);
-}
-
-void Handle::DefaultFreeBuf(Buffer& buf) {
-  buf.Deallocate();
-}
diff --git a/wpiutil/src/main/native/cpp/uv/Idle.cpp b/wpiutil/src/main/native/cpp/uv/Idle.cpp
deleted file mode 100644
index 6bf8602..0000000
--- a/wpiutil/src/main/native/cpp/uv/Idle.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Idle.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Idle> Idle::Create(Loop& loop) {
-  auto h = std::make_shared<Idle>(private_init{});
-  int err = uv_idle_init(loop.GetRaw(), h->GetRaw());
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Idle::Start() {
-  Invoke(&uv_idle_start, GetRaw(), [](uv_idle_t* handle) {
-    Idle& h = *static_cast<Idle*>(handle->data);
-    h.idle();
-  });
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Loop.cpp b/wpiutil/src/main/native/cpp/uv/Loop.cpp
deleted file mode 100644
index c5b7163..0000000
--- a/wpiutil/src/main/native/cpp/uv/Loop.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Loop.h"
-
-using namespace wpi::uv;
-
-Loop::Loop(const private_init&) noexcept {
-#ifndef _WIN32
-  // Ignore SIGPIPE (see https://github.com/joyent/libuv/issues/1254)
-  static bool once = []() {
-    signal(SIGPIPE, SIG_IGN);
-    return true;
-  }();
-  (void)once;
-#endif
-}
-
-Loop::~Loop() noexcept {
-  if (m_loop) {
-    m_loop->data = nullptr;
-    Close();
-  }
-}
-
-std::shared_ptr<Loop> Loop::Create() {
-  auto loop = std::make_shared<Loop>(private_init{});
-  if (uv_loop_init(&loop->m_loopStruct) < 0) {
-    return nullptr;
-  }
-  loop->m_loop = &loop->m_loopStruct;
-  loop->m_loop->data = loop.get();
-  return loop;
-}
-
-std::shared_ptr<Loop> Loop::GetDefault() {
-  static std::shared_ptr<Loop> loop = std::make_shared<Loop>(private_init{});
-  loop->m_loop = uv_default_loop();
-  if (!loop->m_loop) {
-    return nullptr;
-  }
-  loop->m_loop->data = loop.get();
-  return loop;
-}
-
-void Loop::Close() {
-  int err = uv_loop_close(m_loop);
-  if (err < 0) {
-    ReportError(err);
-  }
-}
-
-void Loop::Walk(function_ref<void(Handle&)> callback) {
-  uv_walk(
-      m_loop,
-      [](uv_handle_t* handle, void* func) {
-        auto& h = *static_cast<Handle*>(handle->data);
-        auto& f = *static_cast<function_ref<void(Handle&)>*>(func);
-        f(h);
-      },
-      &callback);
-}
-
-void Loop::Fork() {
-  int err = uv_loop_fork(m_loop);
-  if (err < 0) {
-    ReportError(err);
-  }
-}
diff --git a/wpiutil/src/main/native/cpp/uv/NameToAddr.cpp b/wpiutil/src/main/native/cpp/uv/NameToAddr.cpp
deleted file mode 100644
index 23ec6da..0000000
--- a/wpiutil/src/main/native/cpp/uv/NameToAddr.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/util.h"  // NOLINT(build/include_order)
-
-#include <cstring>
-
-#include "wpi/SmallString.h"
-
-namespace wpi::uv {
-
-int NameToAddr(std::string_view ip, unsigned int port, sockaddr_in* addr) {
-  if (ip.empty()) {
-    std::memset(addr, 0, sizeof(sockaddr_in));
-    addr->sin_family = PF_INET;
-    addr->sin_addr.s_addr = INADDR_ANY;
-    addr->sin_port = htons(port);
-    return 0;
-  } else {
-    SmallString<128> ipBuf{ip};
-    return uv_ip4_addr(ipBuf.c_str(), port, addr);
-  }
-}
-
-int NameToAddr(std::string_view ip, unsigned int port, sockaddr_in6* addr) {
-  if (ip.empty()) {
-    std::memset(addr, 0, sizeof(sockaddr_in6));
-    addr->sin6_family = PF_INET6;
-    addr->sin6_addr = in6addr_any;
-    addr->sin6_port = htons(port);
-    return 0;
-  } else {
-    SmallString<128> ipBuf{ip};
-    return uv_ip6_addr(ipBuf.c_str(), port, addr);
-  }
-}
-
-int NameToAddr(std::string_view ip, in_addr* addr) {
-  if (ip.empty()) {
-    addr->s_addr = INADDR_ANY;
-    return 0;
-  } else {
-    SmallString<128> ipBuf{ip};
-    return uv_inet_pton(AF_INET, ipBuf.c_str(), addr);
-  }
-}
-
-int NameToAddr(std::string_view ip, in6_addr* addr) {
-  if (ip.empty()) {
-    *addr = in6addr_any;
-    return 0;
-  } else {
-    SmallString<128> ipBuf{ip};
-    return uv_inet_pton(AF_INET6, ipBuf.c_str(), addr);
-  }
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/NetworkStream.cpp b/wpiutil/src/main/native/cpp/uv/NetworkStream.cpp
deleted file mode 100644
index 0bc3337..0000000
--- a/wpiutil/src/main/native/cpp/uv/NetworkStream.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/NetworkStream.h"
-
-namespace wpi::uv {
-
-ConnectReq::ConnectReq() {
-  error = [this](Error err) { GetStream().error(err); };
-}
-
-void NetworkStream::Listen(int backlog) {
-  Invoke(&uv_listen, GetRawStream(), backlog,
-         [](uv_stream_t* handle, int status) {
-           auto& h = *static_cast<NetworkStream*>(handle->data);
-           if (status < 0) {
-             h.ReportError(status);
-           } else {
-             h.connection();
-           }
-         });
-}
-
-void NetworkStream::Listen(std::function<void()> callback, int backlog) {
-  connection.connect(std::move(callback));
-  Listen(backlog);
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Pipe.cpp b/wpiutil/src/main/native/cpp/uv/Pipe.cpp
deleted file mode 100644
index b5ca673..0000000
--- a/wpiutil/src/main/native/cpp/uv/Pipe.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Pipe.h"
-
-#include <cstdlib>
-
-#include "wpi/SmallString.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Pipe> Pipe::Create(Loop& loop, bool ipc) {
-  auto h = std::make_shared<Pipe>(private_init{});
-  int err = uv_pipe_init(loop.GetRaw(), h->GetRaw(), ipc ? 1 : 0);
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Pipe::Reuse(std::function<void()> callback, bool ipc) {
-  if (IsClosing()) {
-    return;
-  }
-  if (!m_reuseData) {
-    m_reuseData = std::make_unique<ReuseData>();
-  }
-  m_reuseData->callback = std::move(callback);
-  m_reuseData->ipc = ipc;
-  uv_close(GetRawHandle(), [](uv_handle_t* handle) {
-    Pipe& h = *static_cast<Pipe*>(handle->data);
-    if (!h.m_reuseData) {
-      return;
-    }
-    auto data = std::move(h.m_reuseData);
-    auto err =
-        uv_pipe_init(h.GetLoopRef().GetRaw(), h.GetRaw(), data->ipc ? 1 : 0);
-    if (err < 0) {
-      h.ReportError(err);
-      return;
-    }
-    data->callback();
-  });
-}
-
-std::shared_ptr<Pipe> Pipe::Accept() {
-  auto client = Create(GetLoopRef(), GetRaw()->ipc);
-  if (!client) {
-    return nullptr;
-  }
-  if (!Accept(client)) {
-    client->Release();
-    return nullptr;
-  }
-  return client;
-}
-
-Pipe* Pipe::DoAccept() {
-  return Accept().get();
-}
-
-void Pipe::Bind(std::string_view name) {
-  SmallString<128> nameBuf{name};
-  Invoke(&uv_pipe_bind, GetRaw(), nameBuf.c_str());
-}
-
-void Pipe::Connect(std::string_view name,
-                   const std::shared_ptr<PipeConnectReq>& req) {
-  SmallString<128> nameBuf{name};
-  uv_pipe_connect(req->GetRaw(), GetRaw(), nameBuf.c_str(),
-                  [](uv_connect_t* req, int status) {
-                    auto& h = *static_cast<PipeConnectReq*>(req->data);
-                    if (status < 0) {
-                      h.ReportError(status);
-                    } else {
-                      h.connected();
-                    }
-                    h.Release();  // this is always a one-shot
-                  });
-  req->Keep();
-}
-
-void Pipe::Connect(std::string_view name, std::function<void()> callback) {
-  auto req = std::make_shared<PipeConnectReq>();
-  req->connected.connect(std::move(callback));
-  Connect(name, req);
-}
-
-std::string Pipe::GetSock() {
-  // Per libuv docs, the returned buffer is NOT null terminated.
-  // common case should be small
-  char buf[128];
-  size_t size = 128;
-  int r = uv_pipe_getsockname(GetRaw(), buf, &size);
-  if (r == 0) {
-    return std::string{buf, size};
-  } else if (r == UV_ENOBUFS) {
-    // need to allocate a big enough buffer
-    char* buf2 = static_cast<char*>(std::malloc(size));
-    r = uv_pipe_getsockname(GetRaw(), buf2, &size);
-    if (r == 0) {
-      std::string out{buf2, size};
-      std::free(buf2);
-      return out;
-    }
-    std::free(buf2);
-  }
-  ReportError(r);
-  return std::string{};
-}
-
-std::string Pipe::GetPeer() {
-  // Per libuv docs, the returned buffer is NOT null terminated.
-  // common case should be small
-  char buf[128];
-  size_t size = 128;
-  int r = uv_pipe_getpeername(GetRaw(), buf, &size);
-  if (r == 0) {
-    return std::string{buf, size};
-  } else if (r == UV_ENOBUFS) {
-    // need to allocate a big enough buffer
-    char* buf2 = static_cast<char*>(std::malloc(size));
-    r = uv_pipe_getpeername(GetRaw(), buf2, &size);
-    if (r == 0) {
-      std::string out{buf2, size};
-      std::free(buf2);
-      return out;
-    }
-    std::free(buf2);
-  }
-  ReportError(r);
-  return std::string{};
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Poll.cpp b/wpiutil/src/main/native/cpp/uv/Poll.cpp
deleted file mode 100644
index 090a40b..0000000
--- a/wpiutil/src/main/native/cpp/uv/Poll.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Poll.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Poll> Poll::Create(Loop& loop, int fd) {
-  auto h = std::make_shared<Poll>(private_init{});
-  int err = uv_poll_init(loop.GetRaw(), h->GetRaw(), fd);
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-std::shared_ptr<Poll> Poll::CreateSocket(Loop& loop, uv_os_sock_t sock) {
-  auto h = std::make_shared<Poll>(private_init{});
-  int err = uv_poll_init_socket(loop.GetRaw(), h->GetRaw(), sock);
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Poll::Reuse(int fd, std::function<void()> callback) {
-  if (IsClosing()) {
-    return;
-  }
-  if (!m_reuseData) {
-    m_reuseData = std::make_unique<ReuseData>();
-  }
-  m_reuseData->callback = std::move(callback);
-  m_reuseData->isSocket = false;
-  m_reuseData->fd = fd;
-  uv_close(GetRawHandle(), [](uv_handle_t* handle) {
-    Poll& h = *static_cast<Poll*>(handle->data);
-    if (!h.m_reuseData || h.m_reuseData->isSocket) {
-      return;  // just in case
-    }
-    auto data = std::move(h.m_reuseData);
-    int err = uv_poll_init(h.GetLoopRef().GetRaw(), h.GetRaw(), data->fd);
-    if (err < 0) {
-      h.ReportError(err);
-      return;
-    }
-    data->callback();
-  });
-}
-
-void Poll::ReuseSocket(uv_os_sock_t sock, std::function<void()> callback) {
-  if (IsClosing()) {
-    return;
-  }
-  if (!m_reuseData) {
-    m_reuseData = std::make_unique<ReuseData>();
-  }
-  m_reuseData->callback = std::move(callback);
-  m_reuseData->isSocket = true;
-  m_reuseData->sock = sock;
-  uv_close(GetRawHandle(), [](uv_handle_t* handle) {
-    Poll& h = *static_cast<Poll*>(handle->data);
-    if (!h.m_reuseData || !h.m_reuseData->isSocket) {
-      return;  // just in case
-    }
-    auto data = std::move(h.m_reuseData);
-    int err = uv_poll_init(h.GetLoopRef().GetRaw(), h.GetRaw(), data->sock);
-    if (err < 0) {
-      h.ReportError(err);
-      return;
-    }
-    data->callback();
-  });
-}
-
-void Poll::Start(int events) {
-  Invoke(&uv_poll_start, GetRaw(), events,
-         [](uv_poll_t* handle, int status, int events) {
-           Poll& h = *static_cast<Poll*>(handle->data);
-           if (status < 0) {
-             h.ReportError(status);
-           } else {
-             h.pollEvent(events);
-           }
-         });
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Prepare.cpp b/wpiutil/src/main/native/cpp/uv/Prepare.cpp
deleted file mode 100644
index 048fd08..0000000
--- a/wpiutil/src/main/native/cpp/uv/Prepare.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Prepare.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Prepare> Prepare::Create(Loop& loop) {
-  auto h = std::make_shared<Prepare>(private_init{});
-  int err = uv_prepare_init(loop.GetRaw(), h->GetRaw());
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Prepare::Start() {
-  Invoke(&uv_prepare_start, GetRaw(), [](uv_prepare_t* handle) {
-    Prepare& h = *static_cast<Prepare*>(handle->data);
-    h.prepare();
-  });
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Process.cpp b/wpiutil/src/main/native/cpp/uv/Process.cpp
deleted file mode 100644
index c8d5229..0000000
--- a/wpiutil/src/main/native/cpp/uv/Process.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Process.h"
-
-#include "wpi/SmallString.h"
-#include "wpi/uv/Loop.h"
-#include "wpi/uv/Pipe.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Process> Process::SpawnArray(Loop& loop, std::string_view file,
-                                             span<const Option> options) {
-  // convert Option array to libuv structure
-  uv_process_options_t coptions;
-
-  coptions.exit_cb = [](uv_process_t* handle, int64_t status, int signal) {
-    auto& h = *static_cast<Process*>(handle->data);
-    h.exited(status, signal);
-  };
-
-  SmallString<128> fileBuf{file};
-  coptions.file = fileBuf.c_str();
-  coptions.cwd = nullptr;
-  coptions.flags = 0;
-  coptions.uid = 0;
-  coptions.gid = 0;
-
-  SmallVector<char*, 4> argsBuf;
-  SmallVector<char*, 4> envBuf;
-  struct StdioContainer : public uv_stdio_container_t {
-    StdioContainer() {
-      flags = UV_IGNORE;
-      data.fd = 0;
-    }
-  };
-  SmallVector<StdioContainer, 4> stdioBuf;
-
-  for (auto&& o : options) {
-    switch (o.m_type) {
-      case Option::kArg:
-        argsBuf.push_back(const_cast<char*>(o.m_data.str));
-        break;
-      case Option::kEnv:
-        envBuf.push_back(const_cast<char*>(o.m_data.str));
-        break;
-      case Option::kCwd:
-        coptions.cwd = o.m_data.str[0] == '\0' ? nullptr : o.m_data.str;
-        break;
-      case Option::kUid:
-        coptions.uid = o.m_data.uid;
-        coptions.flags |= UV_PROCESS_SETUID;
-        break;
-      case Option::kGid:
-        coptions.gid = o.m_data.gid;
-        coptions.flags |= UV_PROCESS_SETGID;
-        break;
-      case Option::kSetFlags:
-        coptions.flags |= o.m_data.flags;
-        break;
-      case Option::kClearFlags:
-        coptions.flags &= ~o.m_data.flags;
-        break;
-      case Option::kStdioIgnore: {
-        size_t index = o.m_data.stdio.index;
-        if (index >= stdioBuf.size()) {
-          stdioBuf.resize(index + 1);
-        }
-        stdioBuf[index].flags = UV_IGNORE;
-        stdioBuf[index].data.fd = 0;
-        break;
-      }
-      case Option::kStdioInheritFd: {
-        size_t index = o.m_data.stdio.index;
-        if (index >= stdioBuf.size()) {
-          stdioBuf.resize(index + 1);
-        }
-        stdioBuf[index].flags = UV_INHERIT_FD;
-        stdioBuf[index].data.fd = o.m_data.stdio.fd;
-        break;
-      }
-      case Option::kStdioInheritPipe: {
-        size_t index = o.m_data.stdio.index;
-        if (index >= stdioBuf.size()) {
-          stdioBuf.resize(index + 1);
-        }
-        stdioBuf[index].flags = UV_INHERIT_STREAM;
-        stdioBuf[index].data.stream = o.m_data.stdio.pipe->GetRawStream();
-        break;
-      }
-      case Option::kStdioCreatePipe: {
-        size_t index = o.m_data.stdio.index;
-        if (index >= stdioBuf.size()) {
-          stdioBuf.resize(index + 1);
-        }
-        stdioBuf[index].flags =
-            static_cast<uv_stdio_flags>(UV_CREATE_PIPE | o.m_data.stdio.flags);
-        stdioBuf[index].data.stream = o.m_data.stdio.pipe->GetRawStream();
-        break;
-      }
-      default:
-        break;
-    }
-  }
-
-  if (argsBuf.empty()) {
-    argsBuf.push_back(const_cast<char*>(coptions.file));
-  }
-  argsBuf.push_back(nullptr);
-  coptions.args = argsBuf.data();
-
-  if (envBuf.empty()) {
-    coptions.env = nullptr;
-  } else {
-    envBuf.push_back(nullptr);
-    coptions.env = envBuf.data();
-  }
-
-  coptions.stdio_count = stdioBuf.size();
-  coptions.stdio = static_cast<uv_stdio_container_t*>(stdioBuf.data());
-
-  auto h = std::make_shared<Process>(private_init{});
-  int err = uv_spawn(loop.GetRaw(), h->GetRaw(), &coptions);
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Signal.cpp b/wpiutil/src/main/native/cpp/uv/Signal.cpp
deleted file mode 100644
index 81d7c3e..0000000
--- a/wpiutil/src/main/native/cpp/uv/Signal.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Signal.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Signal> Signal::Create(Loop& loop) {
-  auto h = std::make_shared<Signal>(private_init{});
-  int err = uv_signal_init(loop.GetRaw(), h->GetRaw());
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Signal::Start(int signum) {
-  Invoke(
-      &uv_signal_start, GetRaw(),
-      [](uv_signal_t* handle, int signum) {
-        Signal& h = *static_cast<Signal*>(handle->data);
-        h.signal(signum);
-      },
-      signum);
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Stream.cpp b/wpiutil/src/main/native/cpp/uv/Stream.cpp
deleted file mode 100644
index a37750b..0000000
--- a/wpiutil/src/main/native/cpp/uv/Stream.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Stream.h"
-
-#include "wpi/SmallVector.h"
-
-using namespace wpi;
-using namespace wpi::uv;
-
-namespace {
-class CallbackWriteReq : public WriteReq {
- public:
-  CallbackWriteReq(span<const Buffer> bufs,
-                   std::function<void(span<Buffer>, Error)> callback)
-      : m_bufs{bufs.begin(), bufs.end()} {
-    finish.connect(
-        [this, f = std::move(callback)](Error err) { f(m_bufs, err); });
-  }
-
- private:
-  SmallVector<Buffer, 4> m_bufs;
-};
-}  // namespace
-
-namespace wpi::uv {
-
-ShutdownReq::ShutdownReq() {
-  error = [this](Error err) { GetStream().error(err); };
-}
-
-WriteReq::WriteReq() {
-  error = [this](Error err) { GetStream().error(err); };
-}
-
-void Stream::Shutdown(const std::shared_ptr<ShutdownReq>& req) {
-  if (Invoke(&uv_shutdown, req->GetRaw(), GetRawStream(),
-             [](uv_shutdown_t* req, int status) {
-               auto& h = *static_cast<ShutdownReq*>(req->data);
-               if (status < 0) {
-                 h.ReportError(status);
-               } else {
-                 h.complete();
-               }
-               h.Release();  // this is always a one-shot
-             })) {
-    req->Keep();
-  }
-}
-
-void Stream::Shutdown(std::function<void()> callback) {
-  auto req = std::make_shared<ShutdownReq>();
-  if (callback) {
-    req->complete.connect(std::move(callback));
-  }
-  Shutdown(req);
-}
-
-void Stream::StartRead() {
-  Invoke(&uv_read_start, GetRawStream(), &Handle::AllocBuf,
-         [](uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) {
-           auto& h = *static_cast<Stream*>(stream->data);
-           Buffer data = *buf;
-
-           // nread=0 is simply ignored
-           if (nread == UV_EOF) {
-             h.end();
-           } else if (nread > 0) {
-             h.data(data, static_cast<size_t>(nread));
-           } else if (nread < 0) {
-             h.ReportError(nread);
-           }
-
-           // free the buffer
-           h.FreeBuf(data);
-         });
-}
-
-void Stream::Write(span<const Buffer> bufs,
-                   const std::shared_ptr<WriteReq>& req) {
-  if (Invoke(&uv_write, req->GetRaw(), GetRawStream(), bufs.data(), bufs.size(),
-             [](uv_write_t* r, int status) {
-               auto& h = *static_cast<WriteReq*>(r->data);
-               if (status < 0) {
-                 h.ReportError(status);
-               }
-               h.finish(Error(status));
-               h.Release();  // this is always a one-shot
-             })) {
-    req->Keep();
-  }
-}
-
-void Stream::Write(span<const Buffer> bufs,
-                   std::function<void(span<Buffer>, Error)> callback) {
-  Write(bufs, std::make_shared<CallbackWriteReq>(bufs, std::move(callback)));
-}
-
-int Stream::TryWrite(span<const Buffer> bufs) {
-  int val = uv_try_write(GetRawStream(), bufs.data(), bufs.size());
-  if (val < 0) {
-    this->ReportError(val);
-    return 0;
-  }
-  return val;
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Tcp.cpp b/wpiutil/src/main/native/cpp/uv/Tcp.cpp
deleted file mode 100644
index 6f92557..0000000
--- a/wpiutil/src/main/native/cpp/uv/Tcp.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Tcp.h"
-
-#include <cstring>
-
-#include "wpi/uv/util.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Tcp> Tcp::Create(Loop& loop, unsigned int flags) {
-  auto h = std::make_shared<Tcp>(private_init{});
-  int err = uv_tcp_init_ex(loop.GetRaw(), h->GetRaw(), flags);
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Tcp::Reuse(std::function<void()> callback, unsigned int flags) {
-  if (IsClosing()) {
-    return;
-  }
-  if (!m_reuseData) {
-    m_reuseData = std::make_unique<ReuseData>();
-  }
-  m_reuseData->callback = std::move(callback);
-  m_reuseData->flags = flags;
-  uv_close(GetRawHandle(), [](uv_handle_t* handle) {
-    Tcp& h = *static_cast<Tcp*>(handle->data);
-    if (!h.m_reuseData) {
-      return;  // just in case
-    }
-    auto data = std::move(h.m_reuseData);
-    int err = uv_tcp_init_ex(h.GetLoopRef().GetRaw(), h.GetRaw(), data->flags);
-    if (err < 0) {
-      h.ReportError(err);
-      return;
-    }
-    data->callback();
-  });
-}
-
-std::shared_ptr<Tcp> Tcp::Accept() {
-  auto client = Create(GetLoopRef());
-  if (!client) {
-    return nullptr;
-  }
-  if (!Accept(client)) {
-    client->Release();
-    return nullptr;
-  }
-  return client;
-}
-
-Tcp* Tcp::DoAccept() {
-  return Accept().get();
-}
-
-void Tcp::Bind(std::string_view ip, unsigned int port, unsigned int flags) {
-  sockaddr_in addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Bind(reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-}
-
-void Tcp::Bind6(std::string_view ip, unsigned int port, unsigned int flags) {
-  sockaddr_in6 addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Bind(reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-}
-
-sockaddr_storage Tcp::GetSock() {
-  sockaddr_storage name;
-  int len = sizeof(name);
-  if (!Invoke(&uv_tcp_getsockname, GetRaw(), reinterpret_cast<sockaddr*>(&name),
-              &len)) {
-    std::memset(&name, 0, sizeof(name));
-  }
-  return name;
-}
-
-sockaddr_storage Tcp::GetPeer() {
-  sockaddr_storage name;
-  int len = sizeof(name);
-  if (!Invoke(&uv_tcp_getpeername, GetRaw(), reinterpret_cast<sockaddr*>(&name),
-              &len)) {
-    std::memset(&name, 0, sizeof(name));
-  }
-  return name;
-}
-
-void Tcp::Connect(const sockaddr& addr,
-                  const std::shared_ptr<TcpConnectReq>& req) {
-  if (Invoke(&uv_tcp_connect, req->GetRaw(), GetRaw(), &addr,
-             [](uv_connect_t* req, int status) {
-               auto& h = *static_cast<TcpConnectReq*>(req->data);
-               if (status < 0) {
-                 h.ReportError(status);
-               } else {
-                 h.connected();
-               }
-               h.Release();  // this is always a one-shot
-             })) {
-    req->Keep();
-  }
-}
-
-void Tcp::Connect(const sockaddr& addr, std::function<void()> callback) {
-  auto req = std::make_shared<TcpConnectReq>();
-  req->connected.connect(std::move(callback));
-  Connect(addr, req);
-}
-
-void Tcp::Connect(std::string_view ip, unsigned int port,
-                  const std::shared_ptr<TcpConnectReq>& req) {
-  sockaddr_in addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Connect(reinterpret_cast<const sockaddr&>(addr), req);
-  }
-}
-
-void Tcp::Connect(std::string_view ip, unsigned int port,
-                  std::function<void()> callback) {
-  sockaddr_in addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Connect(reinterpret_cast<const sockaddr&>(addr), std::move(callback));
-  }
-}
-
-void Tcp::Connect6(std::string_view ip, unsigned int port,
-                   const std::shared_ptr<TcpConnectReq>& req) {
-  sockaddr_in6 addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Connect(reinterpret_cast<const sockaddr&>(addr), req);
-  }
-}
-
-void Tcp::Connect6(std::string_view ip, unsigned int port,
-                   std::function<void()> callback) {
-  sockaddr_in6 addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Connect(reinterpret_cast<const sockaddr&>(addr), std::move(callback));
-  }
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Timer.cpp b/wpiutil/src/main/native/cpp/uv/Timer.cpp
deleted file mode 100644
index 33fd851..0000000
--- a/wpiutil/src/main/native/cpp/uv/Timer.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Timer.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Timer> Timer::Create(Loop& loop) {
-  auto h = std::make_shared<Timer>(private_init{});
-  int err = uv_timer_init(loop.GetRaw(), h->GetRaw());
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Timer::SingleShot(Loop& loop, Time timeout, std::function<void()> func) {
-  auto h = Create(loop);
-  if (!h) {
-    return;
-  }
-  h->timeout.connect([theTimer = h.get(), f = std::move(func)]() {
-    f();
-    theTimer->Close();
-  });
-  h->Start(timeout);
-}
-
-void Timer::Start(Time timeout, Time repeat) {
-  Invoke(
-      &uv_timer_start, GetRaw(),
-      [](uv_timer_t* handle) {
-        Timer& h = *static_cast<Timer*>(handle->data);
-        h.timeout();
-      },
-      timeout.count(), repeat.count());
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Tty.cpp b/wpiutil/src/main/native/cpp/uv/Tty.cpp
deleted file mode 100644
index 4531ded..0000000
--- a/wpiutil/src/main/native/cpp/uv/Tty.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Tty.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-std::shared_ptr<Tty> Tty::Create(Loop& loop, uv_file fd, bool readable) {
-  auto h = std::make_shared<Tty>(private_init{});
-  int err = uv_tty_init(loop.GetRaw(), h->GetRaw(), fd, readable ? 1 : 0);
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Udp.cpp b/wpiutil/src/main/native/cpp/uv/Udp.cpp
deleted file mode 100644
index bea2b57..0000000
--- a/wpiutil/src/main/native/cpp/uv/Udp.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Udp.h"
-
-#include <cstring>
-
-#include "wpi/SmallString.h"
-#include "wpi/SmallVector.h"
-#include "wpi/uv/util.h"
-
-namespace {
-
-using namespace wpi;
-using namespace wpi::uv;
-
-class CallbackUdpSendReq : public UdpSendReq {
- public:
-  CallbackUdpSendReq(span<const Buffer> bufs,
-                     std::function<void(span<Buffer>, Error)> callback)
-      : m_bufs{bufs.begin(), bufs.end()} {
-    complete.connect(
-        [this, f = std::move(callback)](Error err) { f(m_bufs, err); });
-  }
-
- private:
-  SmallVector<Buffer, 4> m_bufs;
-};
-
-}  // namespace
-
-namespace wpi::uv {
-
-UdpSendReq::UdpSendReq() {
-  error = [this](Error err) { GetUdp().error(err); };
-}
-
-std::shared_ptr<Udp> Udp::Create(Loop& loop, unsigned int flags) {
-  auto h = std::make_shared<Udp>(private_init{});
-  int err = uv_udp_init_ex(loop.GetRaw(), h->GetRaw(), flags);
-  if (err < 0) {
-    loop.ReportError(err);
-    return nullptr;
-  }
-  h->Keep();
-  return h;
-}
-
-void Udp::Bind(std::string_view ip, unsigned int port, unsigned int flags) {
-  sockaddr_in addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Bind(reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-}
-
-void Udp::Bind6(std::string_view ip, unsigned int port, unsigned int flags) {
-  sockaddr_in6 addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Bind(reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-}
-
-void Udp::Connect(std::string_view ip, unsigned int port) {
-  sockaddr_in addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Connect(reinterpret_cast<const sockaddr&>(addr));
-  }
-}
-
-void Udp::Connect6(std::string_view ip, unsigned int port) {
-  sockaddr_in6 addr;
-  int err = NameToAddr(ip, port, &addr);
-  if (err < 0) {
-    ReportError(err);
-  } else {
-    Connect(reinterpret_cast<const sockaddr&>(addr));
-  }
-}
-
-sockaddr_storage Udp::GetPeer() {
-  sockaddr_storage name;
-  int len = sizeof(name);
-  if (!Invoke(&uv_udp_getpeername, GetRaw(), reinterpret_cast<sockaddr*>(&name),
-              &len)) {
-    std::memset(&name, 0, sizeof(name));
-  }
-  return name;
-}
-
-sockaddr_storage Udp::GetSock() {
-  sockaddr_storage name;
-  int len = sizeof(name);
-  if (!Invoke(&uv_udp_getsockname, GetRaw(), reinterpret_cast<sockaddr*>(&name),
-              &len)) {
-    std::memset(&name, 0, sizeof(name));
-  }
-  return name;
-}
-
-void Udp::SetMembership(std::string_view multicastAddr,
-                        std::string_view interfaceAddr,
-                        uv_membership membership) {
-  SmallString<128> multicastAddrBuf{multicastAddr};
-  SmallString<128> interfaceAddrBuf{interfaceAddr};
-  Invoke(&uv_udp_set_membership, GetRaw(), multicastAddrBuf.c_str(),
-         interfaceAddrBuf.c_str(), membership);
-}
-
-void Udp::SetMulticastInterface(std::string_view interfaceAddr) {
-  SmallString<128> interfaceAddrBuf{interfaceAddr};
-  Invoke(&uv_udp_set_multicast_interface, GetRaw(), interfaceAddrBuf.c_str());
-}
-
-void Udp::Send(const sockaddr& addr, span<const Buffer> bufs,
-               const std::shared_ptr<UdpSendReq>& req) {
-  if (Invoke(&uv_udp_send, req->GetRaw(), GetRaw(), bufs.data(), bufs.size(),
-             &addr, [](uv_udp_send_t* r, int status) {
-               auto& h = *static_cast<UdpSendReq*>(r->data);
-               if (status < 0) {
-                 h.ReportError(status);
-               }
-               h.complete(Error(status));
-               h.Release();  // this is always a one-shot
-             })) {
-    req->Keep();
-  }
-}
-
-void Udp::Send(const sockaddr& addr, span<const Buffer> bufs,
-               std::function<void(span<Buffer>, Error)> callback) {
-  Send(addr, bufs,
-       std::make_shared<CallbackUdpSendReq>(bufs, std::move(callback)));
-}
-
-void Udp::Send(span<const Buffer> bufs,
-               const std::shared_ptr<UdpSendReq>& req) {
-  if (Invoke(&uv_udp_send, req->GetRaw(), GetRaw(), bufs.data(), bufs.size(),
-             nullptr, [](uv_udp_send_t* r, int status) {
-               auto& h = *static_cast<UdpSendReq*>(r->data);
-               if (status < 0) {
-                 h.ReportError(status);
-               }
-               h.complete(Error(status));
-               h.Release();  // this is always a one-shot
-             })) {
-    req->Keep();
-  }
-}
-
-void Udp::Send(span<const Buffer> bufs,
-               std::function<void(span<Buffer>, Error)> callback) {
-  Send(bufs, std::make_shared<CallbackUdpSendReq>(bufs, std::move(callback)));
-}
-
-void Udp::StartRecv() {
-  Invoke(&uv_udp_recv_start, GetRaw(), &AllocBuf,
-         [](uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf,
-            const sockaddr* addr, unsigned flags) {
-           auto& h = *static_cast<Udp*>(handle->data);
-           Buffer data = *buf;
-
-           // nread=0 is simply ignored
-           if (nread > 0) {
-             h.received(data, static_cast<size_t>(nread), *addr, flags);
-           } else if (nread < 0) {
-             h.ReportError(nread);
-           }
-
-           // free the buffer
-           h.FreeBuf(data);
-         });
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/cpp/uv/Work.cpp b/wpiutil/src/main/native/cpp/uv/Work.cpp
deleted file mode 100644
index 0fc254e..0000000
--- a/wpiutil/src/main/native/cpp/uv/Work.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/uv/Work.h"
-
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-WorkReq::WorkReq() {
-  error = [this](Error err) { GetLoop().error(err); };
-}
-
-void QueueWork(Loop& loop, const std::shared_ptr<WorkReq>& req) {
-  int err = uv_queue_work(
-      loop.GetRaw(), req->GetRaw(),
-      [](uv_work_t* req) {
-        auto& h = *static_cast<WorkReq*>(req->data);
-        h.work();
-      },
-      [](uv_work_t* req, int status) {
-        auto& h = *static_cast<WorkReq*>(req->data);
-        if (status < 0) {
-          h.ReportError(status);
-        } else {
-          h.afterWork();
-        }
-        h.Release();  // this is always a one-shot
-      });
-  if (err < 0) {
-    loop.ReportError(err);
-  } else {
-    req->Keep();
-  }
-}
-
-void QueueWork(Loop& loop, std::function<void()> work,
-               std::function<void()> afterWork) {
-  auto req = std::make_shared<WorkReq>();
-  if (work) {
-    req->work.connect(std::move(work));
-  }
-  if (afterWork) {
-    req->afterWork.connect(std::move(afterWork));
-  }
-  QueueWork(loop, req);
-}
-
-}  // namespace wpi::uv
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/format-inl.h b/wpiutil/src/main/native/fmtlib/include/fmt/format-inl.h
deleted file mode 100644
index cc89abd..0000000
--- a/wpiutil/src/main/native/fmtlib/include/fmt/format-inl.h
+++ /dev/null
@@ -1,2642 +0,0 @@
-// Formatting library for C++ - implementation
-//
-// Copyright (c) 2012 - 2016, Victor Zverovich
-// All rights reserved.
-//
-// For the license information refer to format.h.
-
-#ifndef FMT_FORMAT_INL_H_
-#define FMT_FORMAT_INL_H_
-
-#include <algorithm>
-#include <cctype>
-#include <cerrno>  // errno
-#include <climits>
-#include <cmath>
-#include <cstdarg>
-#include <cstring>  // std::memmove
-#include <cwchar>
-#include <exception>
-
-#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
-#  include <locale>
-#endif
-
-#ifdef _WIN32
-#  include <io.h>  // _isatty
-#endif
-
-#include "format.h"
-
-FMT_BEGIN_NAMESPACE
-namespace detail {
-
-FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
-  // Use unchecked std::fprintf to avoid triggering another assertion when
-  // writing to stderr fails
-  std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
-  // Chosen instead of std::abort to satisfy Clang in CUDA mode during device
-  // code pass.
-  std::terminate();
-}
-
-FMT_FUNC void throw_format_error(const char* message) {
-  FMT_THROW(format_error(message));
-}
-
-#ifndef _MSC_VER
-#  define FMT_SNPRINTF snprintf
-#else  // _MSC_VER
-inline int fmt_snprintf(char* buffer, size_t size, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
-  va_end(args);
-  return result;
-}
-#  define FMT_SNPRINTF fmt_snprintf
-#endif  // _MSC_VER
-
-FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
-                                string_view message) FMT_NOEXCEPT {
-  // Report error code making sure that the output fits into
-  // inline_buffer_size to avoid dynamic memory allocation and potential
-  // bad_alloc.
-  out.try_resize(0);
-  static const char SEP[] = ": ";
-  static const char ERROR_STR[] = "error ";
-  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
-  size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
-  auto abs_value = static_cast<uint32_or_64_or_128_t<int>>(error_code);
-  if (detail::is_negative(error_code)) {
-    abs_value = 0 - abs_value;
-    ++error_code_size;
-  }
-  error_code_size += detail::to_unsigned(detail::count_digits(abs_value));
-  auto it = buffer_appender<char>(out);
-  if (message.size() <= inline_buffer_size - error_code_size)
-    format_to(it, FMT_STRING("{}{}"), message, SEP);
-  format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code);
-  FMT_ASSERT(out.size() <= inline_buffer_size, "");
-}
-
-FMT_FUNC void report_error(format_func func, int error_code,
-                           const char* message) FMT_NOEXCEPT {
-  memory_buffer full_message;
-  func(full_message, error_code, message);
-  // Don't use fwrite_fully because the latter may throw.
-  if (std::fwrite(full_message.data(), full_message.size(), 1, stderr) > 0)
-    std::fputc('\n', stderr);
-}
-
-// A wrapper around fwrite that throws on error.
-inline void fwrite_fully(const void* ptr, size_t size, size_t count,
-                         FILE* stream) {
-  std::fwrite(ptr, size, count, stream);
-}
-
-#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
-template <typename Locale>
-locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
-  static_assert(std::is_same<Locale, std::locale>::value, "");
-}
-
-template <typename Locale> Locale locale_ref::get() const {
-  static_assert(std::is_same<Locale, std::locale>::value, "");
-  return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();
-}
-
-template <typename Char>
-FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {
-  auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>());
-  auto grouping = facet.grouping();
-  auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();
-  return {std::move(grouping), thousands_sep};
-}
-template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {
-  return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
-      .decimal_point();
-}
-#else
-template <typename Char>
-FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> {
-  return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR};
-}
-template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
-  return '.';
-}
-#endif
-}  // namespace detail
-
-#if !FMT_MSC_VER
-FMT_API FMT_FUNC format_error::~format_error() FMT_NOEXCEPT = default;
-#endif
-
-FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str,
-                                         format_args args) {
-  auto ec = std::error_code(error_code, std::generic_category());
-  return std::system_error(ec, vformat(format_str, args));
-}
-
-namespace detail {
-
-template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) {
-  // fallback_uintptr is always stored in little endian.
-  int i = static_cast<int>(sizeof(void*)) - 1;
-  while (i > 0 && n.value[i] == 0) --i;
-  auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
-  return i >= 0 ? i * char_digits + count_digits<4, unsigned>(n.value[i]) : 1;
-}
-
-// log10(2) = 0x0.4d104d427de7fbcc...
-static constexpr uint64_t log10_2_significand = 0x4d104d427de7fbcc;
-
-template <typename T = void> struct basic_impl_data {
-  // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
-  // These are generated by support/compute-powers.py.
-  static constexpr uint64_t pow10_significands[87] = {
-      0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
-      0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
-      0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
-      0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
-      0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,
-      0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,
-      0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,
-      0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
-      0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,
-      0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
-      0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,
-      0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
-      0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,
-      0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
-      0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,
-      0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
-      0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,
-      0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
-      0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,
-      0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
-      0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,
-      0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,
-      0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,
-      0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
-      0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,
-      0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,
-      0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,
-      0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
-      0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
-  };
-
-#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wnarrowing"
-#endif
-  // Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
-  // to significands above.
-  static constexpr int16_t pow10_exponents[87] = {
-      -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
-      -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,  -688, -661,
-      -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,  -422,  -396, -369,
-      -343,  -316,  -289,  -263,  -236,  -210,  -183,  -157,  -130,  -103, -77,
-      -50,   -24,   3,     30,    56,    83,    109,   136,   162,   189,  216,
-      242,   269,   295,   322,   348,   375,   402,   428,   455,   481,  508,
-      534,   561,   588,   614,   641,   667,   694,   720,   747,   774,  800,
-      827,   853,   880,   907,   933,   960,   986,   1013,  1039,  1066};
-#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
-#  pragma GCC diagnostic pop
-#endif
-
-  static constexpr uint64_t power_of_10_64[20] = {
-      1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL),
-      10000000000000000000ULL};
-};
-
-// This is a struct rather than an alias to avoid shadowing warnings in gcc.
-struct impl_data : basic_impl_data<> {};
-
-#if __cplusplus < 201703L
-template <typename T>
-constexpr uint64_t basic_impl_data<T>::pow10_significands[];
-template <typename T> constexpr int16_t basic_impl_data<T>::pow10_exponents[];
-template <typename T> constexpr uint64_t basic_impl_data<T>::power_of_10_64[];
-#endif
-
-template <typename T> struct bits {
-  static FMT_CONSTEXPR_DECL const int value =
-      static_cast<int>(sizeof(T) * std::numeric_limits<unsigned char>::digits);
-};
-
-// Returns the number of significand bits in Float excluding the implicit bit.
-template <typename Float> constexpr int num_significand_bits() {
-  // Subtract 1 to account for an implicit most significant bit in the
-  // normalized form.
-  return std::numeric_limits<Float>::digits - 1;
-}
-
-// A floating-point number f * pow(2, e).
-struct fp {
-  uint64_t f;
-  int e;
-
-  static constexpr const int num_significand_bits = bits<decltype(f)>::value;
-
-  constexpr fp() : f(0), e(0) {}
-  constexpr fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
-
-  // Constructs fp from an IEEE754 floating-point number. It is a template to
-  // prevent compile errors on systems where n is not IEEE754.
-  template <typename Float> explicit FMT_CONSTEXPR fp(Float n) { assign(n); }
-
-  template <typename Float>
-  using is_supported = bool_constant<sizeof(Float) == sizeof(uint64_t) ||
-                                     sizeof(Float) == sizeof(uint32_t)>;
-
-  // Assigns d to this and return true iff predecessor is closer than successor.
-  template <typename Float, FMT_ENABLE_IF(is_supported<Float>::value)>
-  FMT_CONSTEXPR bool assign(Float n) {
-    // Assume float is in the format [sign][exponent][significand].
-    const int num_float_significand_bits =
-        detail::num_significand_bits<Float>();
-    const uint64_t implicit_bit = 1ULL << num_float_significand_bits;
-    const uint64_t significand_mask = implicit_bit - 1;
-    constexpr bool is_double = sizeof(Float) == sizeof(uint64_t);
-    auto u = bit_cast<conditional_t<is_double, uint64_t, uint32_t>>(n);
-    f = u & significand_mask;
-    const uint64_t exponent_mask = (~0ULL >> 1) & ~significand_mask;
-    int biased_e =
-        static_cast<int>((u & exponent_mask) >> num_float_significand_bits);
-    // The predecessor is closer if n is a normalized power of 2 (f == 0) other
-    // than the smallest normalized number (biased_e > 1).
-    bool is_predecessor_closer = f == 0 && biased_e > 1;
-    if (biased_e != 0)
-      f += implicit_bit;
-    else
-      biased_e = 1;  // Subnormals use biased exponent 1 (min exponent).
-    const int exponent_bias = std::numeric_limits<Float>::max_exponent - 1;
-    e = biased_e - exponent_bias - num_float_significand_bits;
-    return is_predecessor_closer;
-  }
-
-  template <typename Float, FMT_ENABLE_IF(!is_supported<Float>::value)>
-  bool assign(Float) {
-    FMT_ASSERT(false, "");
-    return false;
-  }
-};
-
-// Normalizes the value converted from double and multiplied by (1 << SHIFT).
-template <int SHIFT = 0> FMT_CONSTEXPR fp normalize(fp value) {
-  // Handle subnormals.
-  const uint64_t implicit_bit = 1ULL << num_significand_bits<double>();
-  const auto shifted_implicit_bit = implicit_bit << SHIFT;
-  while ((value.f & shifted_implicit_bit) == 0) {
-    value.f <<= 1;
-    --value.e;
-  }
-  // Subtract 1 to account for hidden bit.
-  const auto offset =
-      fp::num_significand_bits - num_significand_bits<double>() - SHIFT - 1;
-  value.f <<= offset;
-  value.e -= offset;
-  return value;
-}
-
-inline bool operator==(fp x, fp y) { return x.f == y.f && x.e == y.e; }
-
-// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
-FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
-#if FMT_USE_INT128
-  auto product = static_cast<__uint128_t>(lhs) * rhs;
-  auto f = static_cast<uint64_t>(product >> 64);
-  return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
-#else
-  // Multiply 32-bit parts of significands.
-  uint64_t mask = (1ULL << 32) - 1;
-  uint64_t a = lhs >> 32, b = lhs & mask;
-  uint64_t c = rhs >> 32, d = rhs & mask;
-  uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
-  // Compute mid 64-bit of result and round.
-  uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
-  return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
-#endif
-}
-
-FMT_CONSTEXPR inline fp operator*(fp x, fp y) {
-  return {multiply(x.f, y.f), x.e + y.e + 64};
-}
-
-// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its
-// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.
-FMT_CONSTEXPR inline fp get_cached_power(int min_exponent,
-                                         int& pow10_exponent) {
-  const int shift = 32;
-  const auto significand = static_cast<int64_t>(log10_2_significand);
-  int index = static_cast<int>(
-      ((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) +
-       ((int64_t(1) << shift) - 1))  // ceil
-      >> 32                          // arithmetic shift
-  );
-  // Decimal exponent of the first (smallest) cached power of 10.
-  const int first_dec_exp = -348;
-  // Difference between 2 consecutive decimal exponents in cached powers of 10.
-  const int dec_exp_step = 8;
-  index = (index - first_dec_exp - 1) / dec_exp_step + 1;
-  pow10_exponent = first_dec_exp + index * dec_exp_step;
-  return {impl_data::pow10_significands[index],
-          impl_data::pow10_exponents[index]};
-}
-
-// A simple accumulator to hold the sums of terms in bigint::square if uint128_t
-// is not available.
-struct accumulator {
-  uint64_t lower;
-  uint64_t upper;
-
-  constexpr accumulator() : lower(0), upper(0) {}
-  constexpr explicit operator uint32_t() const {
-    return static_cast<uint32_t>(lower);
-  }
-
-  FMT_CONSTEXPR void operator+=(uint64_t n) {
-    lower += n;
-    if (lower < n) ++upper;
-  }
-  FMT_CONSTEXPR void operator>>=(int shift) {
-    FMT_ASSERT(shift == 32, "");
-    (void)shift;
-    lower = (upper << 32) | (lower >> 32);
-    upper >>= 32;
-  }
-};
-
-class bigint {
- private:
-  // A bigint is stored as an array of bigits (big digits), with bigit at index
-  // 0 being the least significant one.
-  using bigit = uint32_t;
-  using double_bigit = uint64_t;
-  enum { bigits_capacity = 32 };
-  basic_memory_buffer<bigit, bigits_capacity> bigits_;
-  int exp_;
-
-  FMT_CONSTEXPR20 bigit operator[](int index) const {
-    return bigits_[to_unsigned(index)];
-  }
-  FMT_CONSTEXPR20 bigit& operator[](int index) {
-    return bigits_[to_unsigned(index)];
-  }
-
-  static FMT_CONSTEXPR_DECL const int bigit_bits = bits<bigit>::value;
-
-  friend struct formatter<bigint>;
-
-  FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) {
-    auto result = static_cast<double_bigit>((*this)[index]) - other - borrow;
-    (*this)[index] = static_cast<bigit>(result);
-    borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));
-  }
-
-  FMT_CONSTEXPR20 void remove_leading_zeros() {
-    int num_bigits = static_cast<int>(bigits_.size()) - 1;
-    while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits;
-    bigits_.resize(to_unsigned(num_bigits + 1));
-  }
-
-  // Computes *this -= other assuming aligned bigints and *this >= other.
-  FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) {
-    FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints");
-    FMT_ASSERT(compare(*this, other) >= 0, "");
-    bigit borrow = 0;
-    int i = other.exp_ - exp_;
-    for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)
-      subtract_bigits(i, other.bigits_[j], borrow);
-    while (borrow > 0) subtract_bigits(i, 0, borrow);
-    remove_leading_zeros();
-  }
-
-  FMT_CONSTEXPR20 void multiply(uint32_t value) {
-    const double_bigit wide_value = value;
-    bigit carry = 0;
-    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
-      double_bigit result = bigits_[i] * wide_value + carry;
-      bigits_[i] = static_cast<bigit>(result);
-      carry = static_cast<bigit>(result >> bigit_bits);
-    }
-    if (carry != 0) bigits_.push_back(carry);
-  }
-
-  FMT_CONSTEXPR20 void multiply(uint64_t value) {
-    const bigit mask = ~bigit(0);
-    const double_bigit lower = value & mask;
-    const double_bigit upper = value >> bigit_bits;
-    double_bigit carry = 0;
-    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
-      double_bigit result = bigits_[i] * lower + (carry & mask);
-      carry =
-          bigits_[i] * upper + (result >> bigit_bits) + (carry >> bigit_bits);
-      bigits_[i] = static_cast<bigit>(result);
-    }
-    while (carry != 0) {
-      bigits_.push_back(carry & mask);
-      carry >>= bigit_bits;
-    }
-  }
-
- public:
-  FMT_CONSTEXPR20 bigint() : exp_(0) {}
-  explicit bigint(uint64_t n) { assign(n); }
-  FMT_CONSTEXPR20 ~bigint() {
-    FMT_ASSERT(bigits_.capacity() <= bigits_capacity, "");
-  }
-
-  bigint(const bigint&) = delete;
-  void operator=(const bigint&) = delete;
-
-  FMT_CONSTEXPR20 void assign(const bigint& other) {
-    auto size = other.bigits_.size();
-    bigits_.resize(size);
-    auto data = other.bigits_.data();
-    std::copy(data, data + size, make_checked(bigits_.data(), size));
-    exp_ = other.exp_;
-  }
-
-  FMT_CONSTEXPR20 void assign(uint64_t n) {
-    size_t num_bigits = 0;
-    do {
-      bigits_[num_bigits++] = n & ~bigit(0);
-      n >>= bigit_bits;
-    } while (n != 0);
-    bigits_.resize(num_bigits);
-    exp_ = 0;
-  }
-
-  FMT_CONSTEXPR20 int num_bigits() const {
-    return static_cast<int>(bigits_.size()) + exp_;
-  }
-
-  FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) {
-    FMT_ASSERT(shift >= 0, "");
-    exp_ += shift / bigit_bits;
-    shift %= bigit_bits;
-    if (shift == 0) return *this;
-    bigit carry = 0;
-    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
-      bigit c = bigits_[i] >> (bigit_bits - shift);
-      bigits_[i] = (bigits_[i] << shift) + carry;
-      carry = c;
-    }
-    if (carry != 0) bigits_.push_back(carry);
-    return *this;
-  }
-
-  template <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) {
-    FMT_ASSERT(value > 0, "");
-    multiply(uint32_or_64_or_128_t<Int>(value));
-    return *this;
-  }
-
-  friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) {
-    int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
-    if (num_lhs_bigits != num_rhs_bigits)
-      return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
-    int i = static_cast<int>(lhs.bigits_.size()) - 1;
-    int j = static_cast<int>(rhs.bigits_.size()) - 1;
-    int end = i - j;
-    if (end < 0) end = 0;
-    for (; i >= end; --i, --j) {
-      bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];
-      if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1;
-    }
-    if (i != j) return i > j ? 1 : -1;
-    return 0;
-  }
-
-  // Returns compare(lhs1 + lhs2, rhs).
-  friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2,
-                                         const bigint& rhs) {
-    int max_lhs_bigits = (std::max)(lhs1.num_bigits(), lhs2.num_bigits());
-    int num_rhs_bigits = rhs.num_bigits();
-    if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;
-    if (max_lhs_bigits > num_rhs_bigits) return 1;
-    auto get_bigit = [](const bigint& n, int i) -> bigit {
-      return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0;
-    };
-    double_bigit borrow = 0;
-    int min_exp = (std::min)((std::min)(lhs1.exp_, lhs2.exp_), rhs.exp_);
-    for (int i = num_rhs_bigits - 1; i >= min_exp; --i) {
-      double_bigit sum =
-          static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);
-      bigit rhs_bigit = get_bigit(rhs, i);
-      if (sum > rhs_bigit + borrow) return 1;
-      borrow = rhs_bigit + borrow - sum;
-      if (borrow > 1) return -1;
-      borrow <<= bigit_bits;
-    }
-    return borrow != 0 ? -1 : 0;
-  }
-
-  // Assigns pow(10, exp) to this bigint.
-  FMT_CONSTEXPR20 void assign_pow10(int exp) {
-    FMT_ASSERT(exp >= 0, "");
-    if (exp == 0) return assign(1);
-    // Find the top bit.
-    int bitmask = 1;
-    while (exp >= bitmask) bitmask <<= 1;
-    bitmask >>= 1;
-    // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
-    // repeated squaring and multiplication.
-    assign(5);
-    bitmask >>= 1;
-    while (bitmask != 0) {
-      square();
-      if ((exp & bitmask) != 0) *this *= 5;
-      bitmask >>= 1;
-    }
-    *this <<= exp;  // Multiply by pow(2, exp) by shifting.
-  }
-
-  FMT_CONSTEXPR20 void square() {
-    int num_bigits = static_cast<int>(bigits_.size());
-    int num_result_bigits = 2 * num_bigits;
-    basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));
-    bigits_.resize(to_unsigned(num_result_bigits));
-    using accumulator_t = conditional_t<FMT_USE_INT128, uint128_t, accumulator>;
-    auto sum = accumulator_t();
-    for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {
-      // Compute bigit at position bigit_index of the result by adding
-      // cross-product terms n[i] * n[j] such that i + j == bigit_index.
-      for (int i = 0, j = bigit_index; j >= 0; ++i, --j) {
-        // Most terms are multiplied twice which can be optimized in the future.
-        sum += static_cast<double_bigit>(n[i]) * n[j];
-      }
-      (*this)[bigit_index] = static_cast<bigit>(sum);
-      sum >>= bits<bigit>::value;  // Compute the carry.
-    }
-    // Do the same for the top half.
-    for (int bigit_index = num_bigits; bigit_index < num_result_bigits;
-         ++bigit_index) {
-      for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)
-        sum += static_cast<double_bigit>(n[i++]) * n[j--];
-      (*this)[bigit_index] = static_cast<bigit>(sum);
-      sum >>= bits<bigit>::value;
-    }
-    remove_leading_zeros();
-    exp_ *= 2;
-  }
-
-  // If this bigint has a bigger exponent than other, adds trailing zero to make
-  // exponents equal. This simplifies some operations such as subtraction.
-  FMT_CONSTEXPR20 void align(const bigint& other) {
-    int exp_difference = exp_ - other.exp_;
-    if (exp_difference <= 0) return;
-    int num_bigits = static_cast<int>(bigits_.size());
-    bigits_.resize(to_unsigned(num_bigits + exp_difference));
-    for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
-      bigits_[j] = bigits_[i];
-    std::uninitialized_fill_n(bigits_.data(), exp_difference, 0);
-    exp_ -= exp_difference;
-  }
-
-  // Divides this bignum by divisor, assigning the remainder to this and
-  // returning the quotient.
-  FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) {
-    FMT_ASSERT(this != &divisor, "");
-    if (compare(*this, divisor) < 0) return 0;
-    FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, "");
-    align(divisor);
-    int quotient = 0;
-    do {
-      subtract_aligned(divisor);
-      ++quotient;
-    } while (compare(*this, divisor) >= 0);
-    return quotient;
-  }
-};
-
-enum class round_direction { unknown, up, down };
-
-// Given the divisor (normally a power of 10), the remainder = v % divisor for
-// some number v and the error, returns whether v should be rounded up, down, or
-// whether the rounding direction can't be determined due to error.
-// error should be less than divisor / 2.
-FMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor,
-                                                         uint64_t remainder,
-                                                         uint64_t error) {
-  FMT_ASSERT(remainder < divisor, "");  // divisor - remainder won't overflow.
-  FMT_ASSERT(error < divisor, "");      // divisor - error won't overflow.
-  FMT_ASSERT(error < divisor - error, "");  // error * 2 won't overflow.
-  // Round down if (remainder + error) * 2 <= divisor.
-  if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2)
-    return round_direction::down;
-  // Round up if (remainder - error) * 2 >= divisor.
-  if (remainder >= error &&
-      remainder - error >= divisor - (remainder - error)) {
-    return round_direction::up;
-  }
-  return round_direction::unknown;
-}
-
-namespace digits {
-enum result {
-  more,  // Generate more digits.
-  done,  // Done generating digits.
-  error  // Digit generation cancelled due to an error.
-};
-}
-
-struct gen_digits_handler {
-  char* buf;
-  int size;
-  int precision;
-  int exp10;
-  bool fixed;
-
-  FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor,
-                                        uint64_t remainder, uint64_t error,
-                                        bool integral) {
-    FMT_ASSERT(remainder < divisor, "");
-    buf[size++] = digit;
-    if (!integral && error >= remainder) return digits::error;
-    if (size < precision) return digits::more;
-    if (!integral) {
-      // Check if error * 2 < divisor with overflow prevention.
-      // The check is not needed for the integral part because error = 1
-      // and divisor > (1 << 32) there.
-      if (error >= divisor || error >= divisor - error) return digits::error;
-    } else {
-      FMT_ASSERT(error == 1 && divisor > 2, "");
-    }
-    auto dir = get_round_direction(divisor, remainder, error);
-    if (dir != round_direction::up)
-      return dir == round_direction::down ? digits::done : digits::error;
-    ++buf[size - 1];
-    for (int i = size - 1; i > 0 && buf[i] > '9'; --i) {
-      buf[i] = '0';
-      ++buf[i - 1];
-    }
-    if (buf[0] > '9') {
-      buf[0] = '1';
-      if (fixed)
-        buf[size++] = '0';
-      else
-        ++exp10;
-    }
-    return digits::done;
-  }
-};
-
-// Generates output using the Grisu digit-gen algorithm.
-// error: the size of the region (lower, upper) outside of which numbers
-// definitely do not round to value (Delta in Grisu3).
-FMT_INLINE FMT_CONSTEXPR20 digits::result grisu_gen_digits(
-    fp value, uint64_t error, int& exp, gen_digits_handler& handler) {
-  const fp one(1ULL << -value.e, value.e);
-  // The integral part of scaled value (p1 in Grisu) = value / one. It cannot be
-  // zero because it contains a product of two 64-bit numbers with MSB set (due
-  // to normalization) - 1, shifted right by at most 60 bits.
-  auto integral = static_cast<uint32_t>(value.f >> -one.e);
-  FMT_ASSERT(integral != 0, "");
-  FMT_ASSERT(integral == value.f >> -one.e, "");
-  // The fractional part of scaled value (p2 in Grisu) c = value % one.
-  uint64_t fractional = value.f & (one.f - 1);
-  exp = count_digits(integral);  // kappa in Grisu.
-  // Non-fixed formats require at least one digit and no precision adjustment.
-  if (handler.fixed) {
-    // Adjust fixed precision by exponent because it is relative to decimal
-    // point.
-    int precision_offset = exp + handler.exp10;
-    if (precision_offset > 0 &&
-        handler.precision > max_value<int>() - precision_offset) {
-      FMT_THROW(format_error("number is too big"));
-    }
-    handler.precision += precision_offset;
-    // Check if precision is satisfied just by leading zeros, e.g.
-    // format("{:.2f}", 0.001) gives "0.00" without generating any digits.
-    if (handler.precision <= 0) {
-      if (handler.precision < 0) return digits::done;
-      // Divide by 10 to prevent overflow.
-      uint64_t divisor = impl_data::power_of_10_64[exp - 1] << -one.e;
-      auto dir = get_round_direction(divisor, value.f / 10, error * 10);
-      if (dir == round_direction::unknown) return digits::error;
-      handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0';
-      return digits::done;
-    }
-  }
-  // Generate digits for the integral part. This can produce up to 10 digits.
-  do {
-    uint32_t digit = 0;
-    auto divmod_integral = [&](uint32_t divisor) {
-      digit = integral / divisor;
-      integral %= divisor;
-    };
-    // This optimization by Milo Yip reduces the number of integer divisions by
-    // one per iteration.
-    switch (exp) {
-    case 10:
-      divmod_integral(1000000000);
-      break;
-    case 9:
-      divmod_integral(100000000);
-      break;
-    case 8:
-      divmod_integral(10000000);
-      break;
-    case 7:
-      divmod_integral(1000000);
-      break;
-    case 6:
-      divmod_integral(100000);
-      break;
-    case 5:
-      divmod_integral(10000);
-      break;
-    case 4:
-      divmod_integral(1000);
-      break;
-    case 3:
-      divmod_integral(100);
-      break;
-    case 2:
-      divmod_integral(10);
-      break;
-    case 1:
-      digit = integral;
-      integral = 0;
-      break;
-    default:
-      FMT_ASSERT(false, "invalid number of digits");
-    }
-    --exp;
-    auto remainder = (static_cast<uint64_t>(integral) << -one.e) + fractional;
-    auto result = handler.on_digit(static_cast<char>('0' + digit),
-                                   impl_data::power_of_10_64[exp] << -one.e,
-                                   remainder, error, true);
-    if (result != digits::more) return result;
-  } while (exp > 0);
-  // Generate digits for the fractional part.
-  for (;;) {
-    fractional *= 10;
-    error *= 10;
-    char digit = static_cast<char>('0' + (fractional >> -one.e));
-    fractional &= one.f - 1;
-    --exp;
-    auto result = handler.on_digit(digit, one.f, fractional, error, false);
-    if (result != digits::more) return result;
-  }
-}
-
-// A 128-bit integer type used internally,
-struct uint128_wrapper {
-  uint128_wrapper() = default;
-
-#if FMT_USE_INT128
-  uint128_t internal_;
-
-  constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT
-      : internal_{static_cast<uint128_t>(low) |
-                  (static_cast<uint128_t>(high) << 64)} {}
-
-  constexpr uint128_wrapper(uint128_t u) : internal_{u} {}
-
-  constexpr uint64_t high() const FMT_NOEXCEPT {
-    return uint64_t(internal_ >> 64);
-  }
-  constexpr uint64_t low() const FMT_NOEXCEPT { return uint64_t(internal_); }
-
-  uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT {
-    internal_ += n;
-    return *this;
-  }
-#else
-  uint64_t high_;
-  uint64_t low_;
-
-  constexpr uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT
-      : high_{high},
-        low_{low} {}
-
-  constexpr uint64_t high() const FMT_NOEXCEPT { return high_; }
-  constexpr uint64_t low() const FMT_NOEXCEPT { return low_; }
-
-  uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT {
-#  if defined(_MSC_VER) && defined(_M_X64)
-    unsigned char carry = _addcarry_u64(0, low_, n, &low_);
-    _addcarry_u64(carry, high_, 0, &high_);
-    return *this;
-#  else
-    uint64_t sum = low_ + n;
-    high_ += (sum < low_ ? 1 : 0);
-    low_ = sum;
-    return *this;
-#  endif
-  }
-#endif
-};
-
-// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox.
-namespace dragonbox {
-// Computes 128-bit result of multiplication of two 64-bit unsigned integers.
-inline uint128_wrapper umul128(uint64_t x, uint64_t y) FMT_NOEXCEPT {
-#if FMT_USE_INT128
-  return static_cast<uint128_t>(x) * static_cast<uint128_t>(y);
-#elif defined(_MSC_VER) && defined(_M_X64)
-  uint128_wrapper result;
-  result.low_ = _umul128(x, y, &result.high_);
-  return result;
-#else
-  const uint64_t mask = (uint64_t(1) << 32) - uint64_t(1);
-
-  uint64_t a = x >> 32;
-  uint64_t b = x & mask;
-  uint64_t c = y >> 32;
-  uint64_t d = y & mask;
-
-  uint64_t ac = a * c;
-  uint64_t bc = b * c;
-  uint64_t ad = a * d;
-  uint64_t bd = b * d;
-
-  uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
-
-  return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
-          (intermediate << 32) + (bd & mask)};
-#endif
-}
-
-// Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
-inline uint64_t umul128_upper64(uint64_t x, uint64_t y) FMT_NOEXCEPT {
-#if FMT_USE_INT128
-  auto p = static_cast<uint128_t>(x) * static_cast<uint128_t>(y);
-  return static_cast<uint64_t>(p >> 64);
-#elif defined(_MSC_VER) && defined(_M_X64)
-  return __umulh(x, y);
-#else
-  return umul128(x, y).high();
-#endif
-}
-
-// Computes upper 64 bits of multiplication of a 64-bit unsigned integer and a
-// 128-bit unsigned integer.
-inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT {
-  uint128_wrapper g0 = umul128(x, y.high());
-  g0 += umul128_upper64(x, y.low());
-  return g0.high();
-}
-
-// Computes upper 32 bits of multiplication of a 32-bit unsigned integer and a
-// 64-bit unsigned integer.
-inline uint32_t umul96_upper32(uint32_t x, uint64_t y) FMT_NOEXCEPT {
-  return static_cast<uint32_t>(umul128_upper64(x, y));
-}
-
-// Computes middle 64 bits of multiplication of a 64-bit unsigned integer and a
-// 128-bit unsigned integer.
-inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT {
-  uint64_t g01 = x * y.high();
-  uint64_t g10 = umul128_upper64(x, y.low());
-  return g01 + g10;
-}
-
-// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a
-// 64-bit unsigned integer.
-inline uint64_t umul96_lower64(uint32_t x, uint64_t y) FMT_NOEXCEPT {
-  return x * y;
-}
-
-// Computes floor(log10(pow(2, e))) for e in [-1700, 1700] using the method from
-// https://fmt.dev/papers/Grisu-Exact.pdf#page=5, section 3.4.
-inline int floor_log10_pow2(int e) FMT_NOEXCEPT {
-  FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
-  const int shift = 22;
-  return (e * static_cast<int>(log10_2_significand >> (64 - shift))) >> shift;
-}
-
-// Various fast log computations.
-inline int floor_log2_pow10(int e) FMT_NOEXCEPT {
-  FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent");
-  const uint64_t log2_10_integer_part = 3;
-  const uint64_t log2_10_fractional_digits = 0x5269e12f346e2bf9;
-  const int shift_amount = 19;
-  return (e * static_cast<int>(
-                  (log2_10_integer_part << shift_amount) |
-                  (log2_10_fractional_digits >> (64 - shift_amount)))) >>
-         shift_amount;
-}
-inline int floor_log10_pow2_minus_log10_4_over_3(int e) FMT_NOEXCEPT {
-  FMT_ASSERT(e <= 1700 && e >= -1700, "too large exponent");
-  const uint64_t log10_4_over_3_fractional_digits = 0x1ffbfc2bbc780375;
-  const int shift_amount = 22;
-  return (e * static_cast<int>(log10_2_significand >> (64 - shift_amount)) -
-          static_cast<int>(log10_4_over_3_fractional_digits >>
-                           (64 - shift_amount))) >>
-         shift_amount;
-}
-
-// Returns true iff x is divisible by pow(2, exp).
-inline bool divisible_by_power_of_2(uint32_t x, int exp) FMT_NOEXCEPT {
-  FMT_ASSERT(exp >= 1, "");
-  FMT_ASSERT(x != 0, "");
-#ifdef FMT_BUILTIN_CTZ
-  return FMT_BUILTIN_CTZ(x) >= exp;
-#else
-  return exp < num_bits<uint32_t>() && x == ((x >> exp) << exp);
-#endif
-}
-inline bool divisible_by_power_of_2(uint64_t x, int exp) FMT_NOEXCEPT {
-  FMT_ASSERT(exp >= 1, "");
-  FMT_ASSERT(x != 0, "");
-#ifdef FMT_BUILTIN_CTZLL
-  return FMT_BUILTIN_CTZLL(x) >= exp;
-#else
-  return exp < num_bits<uint64_t>() && x == ((x >> exp) << exp);
-#endif
-}
-
-// Table entry type for divisibility test.
-template <typename T> struct divtest_table_entry {
-  T mod_inv;
-  T max_quotient;
-};
-
-// Returns true iff x is divisible by pow(5, exp).
-inline bool divisible_by_power_of_5(uint32_t x, int exp) FMT_NOEXCEPT {
-  FMT_ASSERT(exp <= 10, "too large exponent");
-  static constexpr const divtest_table_entry<uint32_t> divtest_table[] = {
-      {0x00000001, 0xffffffff}, {0xcccccccd, 0x33333333},
-      {0xc28f5c29, 0x0a3d70a3}, {0x26e978d5, 0x020c49ba},
-      {0x3afb7e91, 0x0068db8b}, {0x0bcbe61d, 0x0014f8b5},
-      {0x68c26139, 0x000431bd}, {0xae8d46a5, 0x0000d6bf},
-      {0x22e90e21, 0x00002af3}, {0x3a2e9c6d, 0x00000897},
-      {0x3ed61f49, 0x000001b7}};
-  return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient;
-}
-inline bool divisible_by_power_of_5(uint64_t x, int exp) FMT_NOEXCEPT {
-  FMT_ASSERT(exp <= 23, "too large exponent");
-  static constexpr const divtest_table_entry<uint64_t> divtest_table[] = {
-      {0x0000000000000001, 0xffffffffffffffff},
-      {0xcccccccccccccccd, 0x3333333333333333},
-      {0x8f5c28f5c28f5c29, 0x0a3d70a3d70a3d70},
-      {0x1cac083126e978d5, 0x020c49ba5e353f7c},
-      {0xd288ce703afb7e91, 0x0068db8bac710cb2},
-      {0x5d4e8fb00bcbe61d, 0x0014f8b588e368f0},
-      {0x790fb65668c26139, 0x000431bde82d7b63},
-      {0xe5032477ae8d46a5, 0x0000d6bf94d5e57a},
-      {0xc767074b22e90e21, 0x00002af31dc46118},
-      {0x8e47ce423a2e9c6d, 0x0000089705f4136b},
-      {0x4fa7f60d3ed61f49, 0x000001b7cdfd9d7b},
-      {0x0fee64690c913975, 0x00000057f5ff85e5},
-      {0x3662e0e1cf503eb1, 0x000000119799812d},
-      {0xa47a2cf9f6433fbd, 0x0000000384b84d09},
-      {0x54186f653140a659, 0x00000000b424dc35},
-      {0x7738164770402145, 0x0000000024075f3d},
-      {0xe4a4d1417cd9a041, 0x000000000734aca5},
-      {0xc75429d9e5c5200d, 0x000000000170ef54},
-      {0xc1773b91fac10669, 0x000000000049c977},
-      {0x26b172506559ce15, 0x00000000000ec1e4},
-      {0xd489e3a9addec2d1, 0x000000000002f394},
-      {0x90e860bb892c8d5d, 0x000000000000971d},
-      {0x502e79bf1b6f4f79, 0x0000000000001e39},
-      {0xdcd618596be30fe5, 0x000000000000060b}};
-  return x * divtest_table[exp].mod_inv <= divtest_table[exp].max_quotient;
-}
-
-// Replaces n by floor(n / pow(5, N)) returning true if and only if n is
-// divisible by pow(5, N).
-// Precondition: n <= 2 * pow(5, N + 1).
-template <int N>
-bool check_divisibility_and_divide_by_pow5(uint32_t& n) FMT_NOEXCEPT {
-  static constexpr struct {
-    uint32_t magic_number;
-    int bits_for_comparison;
-    uint32_t threshold;
-    int shift_amount;
-  } infos[] = {{0xcccd, 16, 0x3333, 18}, {0xa429, 8, 0x0a, 20}};
-  constexpr auto info = infos[N - 1];
-  n *= info.magic_number;
-  const uint32_t comparison_mask = (1u << info.bits_for_comparison) - 1;
-  bool result = (n & comparison_mask) <= info.threshold;
-  n >>= info.shift_amount;
-  return result;
-}
-
-// Computes floor(n / pow(10, N)) for small n and N.
-// Precondition: n <= pow(10, N + 1).
-template <int N> uint32_t small_division_by_pow10(uint32_t n) FMT_NOEXCEPT {
-  static constexpr struct {
-    uint32_t magic_number;
-    int shift_amount;
-    uint32_t divisor_times_10;
-  } infos[] = {{0xcccd, 19, 100}, {0xa3d8, 22, 1000}};
-  constexpr auto info = infos[N - 1];
-  FMT_ASSERT(n <= info.divisor_times_10, "n is too large");
-  return n * info.magic_number >> info.shift_amount;
-}
-
-// Computes floor(n / 10^(kappa + 1)) (float)
-inline uint32_t divide_by_10_to_kappa_plus_1(uint32_t n) FMT_NOEXCEPT {
-  return n / float_info<float>::big_divisor;
-}
-// Computes floor(n / 10^(kappa + 1)) (double)
-inline uint64_t divide_by_10_to_kappa_plus_1(uint64_t n) FMT_NOEXCEPT {
-  return umul128_upper64(n, 0x83126e978d4fdf3c) >> 9;
-}
-
-// Various subroutines using pow10 cache
-template <class T> struct cache_accessor;
-
-template <> struct cache_accessor<float> {
-  using carrier_uint = float_info<float>::carrier_uint;
-  using cache_entry_type = uint64_t;
-
-  static uint64_t get_cached_power(int k) FMT_NOEXCEPT {
-    FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k,
-               "k is out of range");
-    static constexpr const uint64_t pow10_significands[] = {
-        0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f,
-        0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb,
-        0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28,
-        0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb,
-        0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a,
-        0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810,
-        0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff,
-        0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd,
-        0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424,
-        0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b,
-        0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000,
-        0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000,
-        0xc350000000000000, 0xf424000000000000, 0x9896800000000000,
-        0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000,
-        0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000,
-        0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000,
-        0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000,
-        0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000,
-        0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0,
-        0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940984,
-        0xa18f07d736b90be5, 0xc9f2c9cd04674ede, 0xfc6f7c4045812296,
-        0x9dc5ada82b70b59d, 0xc5371912364ce305, 0xf684df56c3e01bc6,
-        0x9a130b963a6c115c, 0xc097ce7bc90715b3, 0xf0bdc21abb48db20,
-        0x96769950b50d88f4, 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd,
-        0x92efd1b8d0cf37be, 0xb7abc627050305ad, 0xe596b7b0c643c719,
-        0x8f7e32ce7bea5c6f, 0xb35dbf821ae4f38b, 0xe0352f62a19e306e};
-    return pow10_significands[k - float_info<float>::min_k];
-  }
-
-  static carrier_uint compute_mul(carrier_uint u,
-                                  const cache_entry_type& cache) FMT_NOEXCEPT {
-    return umul96_upper32(u, cache);
-  }
-
-  static uint32_t compute_delta(const cache_entry_type& cache,
-                                int beta_minus_1) FMT_NOEXCEPT {
-    return static_cast<uint32_t>(cache >> (64 - 1 - beta_minus_1));
-  }
-
-  static bool compute_mul_parity(carrier_uint two_f,
-                                 const cache_entry_type& cache,
-                                 int beta_minus_1) FMT_NOEXCEPT {
-    FMT_ASSERT(beta_minus_1 >= 1, "");
-    FMT_ASSERT(beta_minus_1 < 64, "");
-
-    return ((umul96_lower64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0;
-  }
-
-  static carrier_uint compute_left_endpoint_for_shorter_interval_case(
-      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
-    return static_cast<carrier_uint>(
-        (cache - (cache >> (float_info<float>::significand_bits + 2))) >>
-        (64 - float_info<float>::significand_bits - 1 - beta_minus_1));
-  }
-
-  static carrier_uint compute_right_endpoint_for_shorter_interval_case(
-      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
-    return static_cast<carrier_uint>(
-        (cache + (cache >> (float_info<float>::significand_bits + 1))) >>
-        (64 - float_info<float>::significand_bits - 1 - beta_minus_1));
-  }
-
-  static carrier_uint compute_round_up_for_shorter_interval_case(
-      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
-    return (static_cast<carrier_uint>(
-                cache >>
-                (64 - float_info<float>::significand_bits - 2 - beta_minus_1)) +
-            1) /
-           2;
-  }
-};
-
-template <> struct cache_accessor<double> {
-  using carrier_uint = float_info<double>::carrier_uint;
-  using cache_entry_type = uint128_wrapper;
-
-  static uint128_wrapper get_cached_power(int k) FMT_NOEXCEPT {
-    FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k,
-               "k is out of range");
-
-    static constexpr const uint128_wrapper pow10_significands[] = {
-#if FMT_USE_FULL_CACHE_DRAGONBOX
-      {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},
-      {0x9faacf3df73609b1, 0x77b191618c54e9ad},
-      {0xc795830d75038c1d, 0xd59df5b9ef6a2418},
-      {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e},
-      {0x9becce62836ac577, 0x4ee367f9430aec33},
-      {0xc2e801fb244576d5, 0x229c41f793cda740},
-      {0xf3a20279ed56d48a, 0x6b43527578c11110},
-      {0x9845418c345644d6, 0x830a13896b78aaaa},
-      {0xbe5691ef416bd60c, 0x23cc986bc656d554},
-      {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9},
-      {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa},
-      {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54},
-      {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69},
-      {0x91376c36d99995be, 0x23100809b9c21fa2},
-      {0xb58547448ffffb2d, 0xabd40a0c2832a78b},
-      {0xe2e69915b3fff9f9, 0x16c90c8f323f516d},
-      {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4},
-      {0xb1442798f49ffb4a, 0x99cd11cfdf41779d},
-      {0xdd95317f31c7fa1d, 0x40405643d711d584},
-      {0x8a7d3eef7f1cfc52, 0x482835ea666b2573},
-      {0xad1c8eab5ee43b66, 0xda3243650005eed0},
-      {0xd863b256369d4a40, 0x90bed43e40076a83},
-      {0x873e4f75e2224e68, 0x5a7744a6e804a292},
-      {0xa90de3535aaae202, 0x711515d0a205cb37},
-      {0xd3515c2831559a83, 0x0d5a5b44ca873e04},
-      {0x8412d9991ed58091, 0xe858790afe9486c3},
-      {0xa5178fff668ae0b6, 0x626e974dbe39a873},
-      {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
-      {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a},
-      {0xa139029f6a239f72, 0x1c1fffc1ebc44e81},
-      {0xc987434744ac874e, 0xa327ffb266b56221},
-      {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9},
-      {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa},
-      {0xc4ce17b399107c22, 0xcb550fb4384d21d4},
-      {0xf6019da07f549b2b, 0x7e2a53a146606a49},
-      {0x99c102844f94e0fb, 0x2eda7444cbfc426e},
-      {0xc0314325637a1939, 0xfa911155fefb5309},
-      {0xf03d93eebc589f88, 0x793555ab7eba27cb},
-      {0x96267c7535b763b5, 0x4bc1558b2f3458df},
-      {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17},
-      {0xea9c227723ee8bcb, 0x465e15a979c1cadd},
-      {0x92a1958a7675175f, 0x0bfacd89ec191eca},
-      {0xb749faed14125d36, 0xcef980ec671f667c},
-      {0xe51c79a85916f484, 0x82b7e12780e7401b},
-      {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811},
-      {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16},
-      {0xdfbdcece67006ac9, 0x67a791e093e1d49b},
-      {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1},
-      {0xaecc49914078536d, 0x58fae9f773886e19},
-      {0xda7f5bf590966848, 0xaf39a475506a899f},
-      {0x888f99797a5e012d, 0x6d8406c952429604},
-      {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84},
-      {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65},
-      {0x855c3be0a17fcd26, 0x5cf2eea09a550680},
-      {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f},
-      {0xd0601d8efc57b08b, 0xf13b94daf124da27},
-      {0x823c12795db6ce57, 0x76c53d08d6b70859},
-      {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f},
-      {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a},
-      {0xfe5d54150b090b02, 0xd3f93b35435d7c4d},
-      {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0},
-      {0xc6b8e9b0709f109a, 0x359ab6419ca1091c},
-      {0xf867241c8cc6d4c0, 0xc30163d203c94b63},
-      {0x9b407691d7fc44f8, 0x79e0de63425dcf1e},
-      {0xc21094364dfb5636, 0x985915fc12f542e5},
-      {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e},
-      {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43},
-      {0xbd8430bd08277231, 0x50c6ff782a838354},
-      {0xece53cec4a314ebd, 0xa4f8bf5635246429},
-      {0x940f4613ae5ed136, 0x871b7795e136be9a},
-      {0xb913179899f68584, 0x28e2557b59846e40},
-      {0xe757dd7ec07426e5, 0x331aeada2fe589d0},
-      {0x9096ea6f3848984f, 0x3ff0d2c85def7622},
-      {0xb4bca50b065abe63, 0x0fed077a756b53aa},
-      {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895},
-      {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d},
-      {0xb080392cc4349dec, 0xbd8d794d96aacfb4},
-      {0xdca04777f541c567, 0xecf0d7a0fc5583a1},
-      {0x89e42caaf9491b60, 0xf41686c49db57245},
-      {0xac5d37d5b79b6239, 0x311c2875c522ced6},
-      {0xd77485cb25823ac7, 0x7d633293366b828c},
-      {0x86a8d39ef77164bc, 0xae5dff9c02033198},
-      {0xa8530886b54dbdeb, 0xd9f57f830283fdfd},
-      {0xd267caa862a12d66, 0xd072df63c324fd7c},
-      {0x8380dea93da4bc60, 0x4247cb9e59f71e6e},
-      {0xa46116538d0deb78, 0x52d9be85f074e609},
-      {0xcd795be870516656, 0x67902e276c921f8c},
-      {0x806bd9714632dff6, 0x00ba1cd8a3db53b7},
-      {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5},
-      {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce},
-      {0xfad2a4b13d1b5d6c, 0x796b805720085f82},
-      {0x9cc3a6eec6311a63, 0xcbe3303674053bb1},
-      {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d},
-      {0xf4f1b4d515acb93b, 0xee92fb5515482d45},
-      {0x991711052d8bf3c5, 0x751bdd152d4d1c4b},
-      {0xbf5cd54678eef0b6, 0xd262d45a78a0635e},
-      {0xef340a98172aace4, 0x86fb897116c87c35},
-      {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1},
-      {0xbae0a846d2195712, 0x8974836059cca10a},
-      {0xe998d258869facd7, 0x2bd1a438703fc94c},
-      {0x91ff83775423cc06, 0x7b6306a34627ddd0},
-      {0xb67f6455292cbf08, 0x1a3bc84c17b1d543},
-      {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94},
-      {0x8e938662882af53e, 0x547eb47b7282ee9d},
-      {0xb23867fb2a35b28d, 0xe99e619a4f23aa44},
-      {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5},
-      {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05},
-      {0xae0b158b4738705e, 0x9624ab50b148d446},
-      {0xd98ddaee19068c76, 0x3badd624dd9b0958},
-      {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7},
-      {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d},
-      {0xd47487cc8470652b, 0x7647c32000696720},
-      {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074},
-      {0xa5fb0a17c777cf09, 0xf468107100525891},
-      {0xcf79cc9db955c2cc, 0x7182148d4066eeb5},
-      {0x81ac1fe293d599bf, 0xc6f14cd848405531},
-      {0xa21727db38cb002f, 0xb8ada00e5a506a7d},
-      {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d},
-      {0xfd442e4688bd304a, 0x908f4a166d1da664},
-      {0x9e4a9cec15763e2e, 0x9a598e4e043287ff},
-      {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe},
-      {0xf7549530e188c128, 0xd12bee59e68ef47d},
-      {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf},
-      {0xc13a148e3032d6e7, 0xe36a52363c1faf02},
-      {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2},
-      {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba},
-      {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8},
-      {0xebdf661791d60f56, 0x111b495b3464ad22},
-      {0x936b9fcebb25c995, 0xcab10dd900beec35},
-      {0xb84687c269ef3bfb, 0x3d5d514f40eea743},
-      {0xe65829b3046b0afa, 0x0cb4a5a3112a5113},
-      {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac},
-      {0xb3f4e093db73a093, 0x59ed216765690f57},
-      {0xe0f218b8d25088b8, 0x306869c13ec3532d},
-      {0x8c974f7383725573, 0x1e414218c73a13fc},
-      {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
-      {0xdbac6c247d62a583, 0xdf45f746b74abf3a},
-      {0x894bc396ce5da772, 0x6b8bba8c328eb784},
-      {0xab9eb47c81f5114f, 0x066ea92f3f326565},
-      {0xd686619ba27255a2, 0xc80a537b0efefebe},
-      {0x8613fd0145877585, 0xbd06742ce95f5f37},
-      {0xa798fc4196e952e7, 0x2c48113823b73705},
-      {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6},
-      {0x82ef85133de648c4, 0x9a984d73dbe722fc},
-      {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb},
-      {0xcc963fee10b7d1b3, 0x318df905079926a9},
-      {0xffbbcfe994e5c61f, 0xfdf17746497f7053},
-      {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634},
-      {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1},
-      {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1},
-      {0x9c1661a651213e2d, 0x06bea10ca65c084f},
-      {0xc31bfa0fe5698db8, 0x486e494fcff30a63},
-      {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb},
-      {0x986ddb5c6b3a76b7, 0xf89629465a75e01d},
-      {0xbe89523386091465, 0xf6bbb397f1135824},
-      {0xee2ba6c0678b597f, 0x746aa07ded582e2d},
-      {0x94db483840b717ef, 0xa8c2a44eb4571cdd},
-      {0xba121a4650e4ddeb, 0x92f34d62616ce414},
-      {0xe896a0d7e51e1566, 0x77b020baf9c81d18},
-      {0x915e2486ef32cd60, 0x0ace1474dc1d122f},
-      {0xb5b5ada8aaff80b8, 0x0d819992132456bb},
-      {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a},
-      {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2},
-      {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3},
-      {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf},
-      {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c},
-      {0xad4ab7112eb3929d, 0x86c16c98d2c953c7},
-      {0xd89d64d57a607744, 0xe871c7bf077ba8b8},
-      {0x87625f056c7c4a8b, 0x11471cd764ad4973},
-      {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0},
-      {0xd389b47879823479, 0x4aff1d108d4ec2c4},
-      {0x843610cb4bf160cb, 0xcedf722a585139bb},
-      {0xa54394fe1eedb8fe, 0xc2974eb4ee658829},
-      {0xce947a3da6a9273e, 0x733d226229feea33},
-      {0x811ccc668829b887, 0x0806357d5a3f5260},
-      {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8},
-      {0xc9bcff6034c13052, 0xfc89b393dd02f0b6},
-      {0xfc2c3f3841f17c67, 0xbbac2078d443ace3},
-      {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e},
-      {0xc5029163f384a931, 0x0a9e795e65d4df12},
-      {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6},
-      {0x99ea0196163fa42e, 0x504bced1bf8e4e46},
-      {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7},
-      {0xf07da27a82c37088, 0x5d767327bb4e5a4d},
-      {0x964e858c91ba2655, 0x3a6a07f8d510f870},
-      {0xbbe226efb628afea, 0x890489f70a55368c},
-      {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f},
-      {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e},
-      {0xb77ada0617e3bbcb, 0x09ce6ebb40173745},
-      {0xe55990879ddcaabd, 0xcc420a6a101d0516},
-      {0x8f57fa54c2a9eab6, 0x9fa946824a12232e},
-      {0xb32df8e9f3546564, 0x47939822dc96abfa},
-      {0xdff9772470297ebd, 0x59787e2b93bc56f8},
-      {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b},
-      {0xaefae51477a06b03, 0xede622920b6b23f2},
-      {0xdab99e59958885c4, 0xe95fab368e45ecee},
-      {0x88b402f7fd75539b, 0x11dbcb0218ebb415},
-      {0xaae103b5fcd2a881, 0xd652bdc29f26a11a},
-      {0xd59944a37c0752a2, 0x4be76d3346f04960},
-      {0x857fcae62d8493a5, 0x6f70a4400c562ddc},
-      {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953},
-      {0xd097ad07a71f26b2, 0x7e2000a41346a7a8},
-      {0x825ecc24c873782f, 0x8ed400668c0c28c9},
-      {0xa2f67f2dfa90563b, 0x728900802f0f32fb},
-      {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba},
-      {0xfea126b7d78186bc, 0xe2f610c84987bfa9},
-      {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca},
-      {0xc6ede63fa05d3143, 0x91503d1c79720dbc},
-      {0xf8a95fcf88747d94, 0x75a44c6397ce912b},
-      {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb},
-      {0xc24452da229b021b, 0xfbe85badce996169},
-      {0xf2d56790ab41c2a2, 0xfae27299423fb9c4},
-      {0x97c560ba6b0919a5, 0xdccd879fc967d41b},
-      {0xbdb6b8e905cb600f, 0x5400e987bbc1c921},
-      {0xed246723473e3813, 0x290123e9aab23b69},
-      {0x9436c0760c86e30b, 0xf9a0b6720aaf6522},
-      {0xb94470938fa89bce, 0xf808e40e8d5b3e6a},
-      {0xe7958cb87392c2c2, 0xb60b1d1230b20e05},
-      {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3},
-      {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4},
-      {0xe2280b6c20dd5232, 0x25c6da63c38de1b1},
-      {0x8d590723948a535f, 0x579c487e5a38ad0f},
-      {0xb0af48ec79ace837, 0x2d835a9df0c6d852},
-      {0xdcdb1b2798182244, 0xf8e431456cf88e66},
-      {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900},
-      {0xac8b2d36eed2dac5, 0xe272467e3d222f40},
-      {0xd7adf884aa879177, 0x5b0ed81dcc6abb10},
-      {0x86ccbb52ea94baea, 0x98e947129fc2b4ea},
-      {0xa87fea27a539e9a5, 0x3f2398d747b36225},
-      {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae},
-      {0x83a3eeeef9153e89, 0x1953cf68300424ad},
-      {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8},
-      {0xcdb02555653131b6, 0x3792f412cb06794e},
-      {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1},
-      {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5},
-      {0xc8de047564d20a8b, 0xf245825a5a445276},
-      {0xfb158592be068d2e, 0xeed6e2f0f0d56713},
-      {0x9ced737bb6c4183d, 0x55464dd69685606c},
-      {0xc428d05aa4751e4c, 0xaa97e14c3c26b887},
-      {0xf53304714d9265df, 0xd53dd99f4b3066a9},
-      {0x993fe2c6d07b7fab, 0xe546a8038efe402a},
-      {0xbf8fdb78849a5f96, 0xde98520472bdd034},
-      {0xef73d256a5c0f77c, 0x963e66858f6d4441},
-      {0x95a8637627989aad, 0xdde7001379a44aa9},
-      {0xbb127c53b17ec159, 0x5560c018580d5d53},
-      {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7},
-      {0x9226712162ab070d, 0xcab3961304ca70e9},
-      {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23},
-      {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b},
-      {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243},
-      {0xb267ed1940f1c61c, 0x55f038b237591ed4},
-      {0xdf01e85f912e37a3, 0x6b6c46dec52f6689},
-      {0x8b61313bbabce2c6, 0x2323ac4b3b3da016},
-      {0xae397d8aa96c1b77, 0xabec975e0a0d081b},
-      {0xd9c7dced53c72255, 0x96e7bd358c904a22},
-      {0x881cea14545c7575, 0x7e50d64177da2e55},
-      {0xaa242499697392d2, 0xdde50bd1d5d0b9ea},
-      {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865},
-      {0x84ec3c97da624ab4, 0xbd5af13bef0b113f},
-      {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f},
-      {0xcfb11ead453994ba, 0x67de18eda5814af3},
-      {0x81ceb32c4b43fcf4, 0x80eacf948770ced8},
-      {0xa2425ff75e14fc31, 0xa1258379a94d028e},
-      {0xcad2f7f5359a3b3e, 0x096ee45813a04331},
-      {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd},
-      {0x9e74d1b791e07e48, 0x775ea264cf55347e},
-      {0xc612062576589dda, 0x95364afe032a819e},
-      {0xf79687aed3eec551, 0x3a83ddbd83f52205},
-      {0x9abe14cd44753b52, 0xc4926a9672793543},
-      {0xc16d9a0095928a27, 0x75b7053c0f178294},
-      {0xf1c90080baf72cb1, 0x5324c68b12dd6339},
-      {0x971da05074da7bee, 0xd3f6fc16ebca5e04},
-      {0xbce5086492111aea, 0x88f4bb1ca6bcf585},
-      {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6},
-      {0x9392ee8e921d5d07, 0x3aff322e62439fd0},
-      {0xb877aa3236a4b449, 0x09befeb9fad487c3},
-      {0xe69594bec44de15b, 0x4c2ebe687989a9b4},
-      {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11},
-      {0xb424dc35095cd80f, 0x538484c19ef38c95},
-      {0xe12e13424bb40e13, 0x2865a5f206b06fba},
-      {0x8cbccc096f5088cb, 0xf93f87b7442e45d4},
-      {0xafebff0bcb24aafe, 0xf78f69a51539d749},
-      {0xdbe6fecebdedd5be, 0xb573440e5a884d1c},
-      {0x89705f4136b4a597, 0x31680a88f8953031},
-      {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e},
-      {0xd6bf94d5e57a42bc, 0x3d32907604691b4d},
-      {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110},
-      {0xa7c5ac471b478423, 0x0fcf80dc33721d54},
-      {0xd1b71758e219652b, 0xd3c36113404ea4a9},
-      {0x83126e978d4fdf3b, 0x645a1cac083126ea},
-      {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4},
-      {0xcccccccccccccccc, 0xcccccccccccccccd},
-      {0x8000000000000000, 0x0000000000000000},
-      {0xa000000000000000, 0x0000000000000000},
-      {0xc800000000000000, 0x0000000000000000},
-      {0xfa00000000000000, 0x0000000000000000},
-      {0x9c40000000000000, 0x0000000000000000},
-      {0xc350000000000000, 0x0000000000000000},
-      {0xf424000000000000, 0x0000000000000000},
-      {0x9896800000000000, 0x0000000000000000},
-      {0xbebc200000000000, 0x0000000000000000},
-      {0xee6b280000000000, 0x0000000000000000},
-      {0x9502f90000000000, 0x0000000000000000},
-      {0xba43b74000000000, 0x0000000000000000},
-      {0xe8d4a51000000000, 0x0000000000000000},
-      {0x9184e72a00000000, 0x0000000000000000},
-      {0xb5e620f480000000, 0x0000000000000000},
-      {0xe35fa931a0000000, 0x0000000000000000},
-      {0x8e1bc9bf04000000, 0x0000000000000000},
-      {0xb1a2bc2ec5000000, 0x0000000000000000},
-      {0xde0b6b3a76400000, 0x0000000000000000},
-      {0x8ac7230489e80000, 0x0000000000000000},
-      {0xad78ebc5ac620000, 0x0000000000000000},
-      {0xd8d726b7177a8000, 0x0000000000000000},
-      {0x878678326eac9000, 0x0000000000000000},
-      {0xa968163f0a57b400, 0x0000000000000000},
-      {0xd3c21bcecceda100, 0x0000000000000000},
-      {0x84595161401484a0, 0x0000000000000000},
-      {0xa56fa5b99019a5c8, 0x0000000000000000},
-      {0xcecb8f27f4200f3a, 0x0000000000000000},
-      {0x813f3978f8940984, 0x4000000000000000},
-      {0xa18f07d736b90be5, 0x5000000000000000},
-      {0xc9f2c9cd04674ede, 0xa400000000000000},
-      {0xfc6f7c4045812296, 0x4d00000000000000},
-      {0x9dc5ada82b70b59d, 0xf020000000000000},
-      {0xc5371912364ce305, 0x6c28000000000000},
-      {0xf684df56c3e01bc6, 0xc732000000000000},
-      {0x9a130b963a6c115c, 0x3c7f400000000000},
-      {0xc097ce7bc90715b3, 0x4b9f100000000000},
-      {0xf0bdc21abb48db20, 0x1e86d40000000000},
-      {0x96769950b50d88f4, 0x1314448000000000},
-      {0xbc143fa4e250eb31, 0x17d955a000000000},
-      {0xeb194f8e1ae525fd, 0x5dcfab0800000000},
-      {0x92efd1b8d0cf37be, 0x5aa1cae500000000},
-      {0xb7abc627050305ad, 0xf14a3d9e40000000},
-      {0xe596b7b0c643c719, 0x6d9ccd05d0000000},
-      {0x8f7e32ce7bea5c6f, 0xe4820023a2000000},
-      {0xb35dbf821ae4f38b, 0xdda2802c8a800000},
-      {0xe0352f62a19e306e, 0xd50b2037ad200000},
-      {0x8c213d9da502de45, 0x4526f422cc340000},
-      {0xaf298d050e4395d6, 0x9670b12b7f410000},
-      {0xdaf3f04651d47b4c, 0x3c0cdd765f114000},
-      {0x88d8762bf324cd0f, 0xa5880a69fb6ac800},
-      {0xab0e93b6efee0053, 0x8eea0d047a457a00},
-      {0xd5d238a4abe98068, 0x72a4904598d6d880},
-      {0x85a36366eb71f041, 0x47a6da2b7f864750},
-      {0xa70c3c40a64e6c51, 0x999090b65f67d924},
-      {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d},
-      {0x82818f1281ed449f, 0xbff8f10e7a8921a4},
-      {0xa321f2d7226895c7, 0xaff72d52192b6a0d},
-      {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490},
-      {0xfee50b7025c36a08, 0x02f236d04753d5b4},
-      {0x9f4f2726179a2245, 0x01d762422c946590},
-      {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5},
-      {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2},
-      {0x9b934c3b330c8577, 0x63cc55f49f88eb2f},
-      {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb},
-      {0xf316271c7fc3908a, 0x8bef464e3945ef7a},
-      {0x97edd871cfda3a56, 0x97758bf0e3cbb5ac},
-      {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317},
-      {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd},
-      {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a},
-      {0xb975d6b6ee39e436, 0xb3e2fd538e122b44},
-      {0xe7d34c64a9c85d44, 0x60dbbca87196b616},
-      {0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd},
-      {0xb51d13aea4a488dd, 0x6babab6398bdbe41},
-      {0xe264589a4dcdab14, 0xc696963c7eed2dd1},
-      {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2},
-      {0xb0de65388cc8ada8, 0x3b25a55f43294bcb},
-      {0xdd15fe86affad912, 0x49ef0eb713f39ebe},
-      {0x8a2dbf142dfcc7ab, 0x6e3569326c784337},
-      {0xacb92ed9397bf996, 0x49c2c37f07965404},
-      {0xd7e77a8f87daf7fb, 0xdc33745ec97be906},
-      {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3},
-      {0xa8acd7c0222311bc, 0xc40832ea0d68ce0c},
-      {0xd2d80db02aabd62b, 0xf50a3fa490c30190},
-      {0x83c7088e1aab65db, 0x792667c6da79e0fa},
-      {0xa4b8cab1a1563f52, 0x577001b891185938},
-      {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86},
-      {0x80b05e5ac60b6178, 0x544f8158315b05b4},
-      {0xa0dc75f1778e39d6, 0x696361ae3db1c721},
-      {0xc913936dd571c84c, 0x03bc3a19cd1e38e9},
-      {0xfb5878494ace3a5f, 0x04ab48a04065c723},
-      {0x9d174b2dcec0e47b, 0x62eb0d64283f9c76},
-      {0xc45d1df942711d9a, 0x3ba5d0bd324f8394},
-      {0xf5746577930d6500, 0xca8f44ec7ee36479},
-      {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb},
-      {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e},
-      {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e},
-      {0x95d04aee3b80ece5, 0xbba1f1d158724a12},
-      {0xbb445da9ca61281f, 0x2a8a6e45ae8edc97},
-      {0xea1575143cf97226, 0xf52d09d71a3293bd},
-      {0x924d692ca61be758, 0x593c2626705f9c56},
-      {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c},
-      {0xe498f455c38b997a, 0x0b6dfb9c0f956447},
-      {0x8edf98b59a373fec, 0x4724bd4189bd5eac},
-      {0xb2977ee300c50fe7, 0x58edec91ec2cb657},
-      {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed},
-      {0x8b865b215899f46c, 0xbd79e0d20082ee74},
-      {0xae67f1e9aec07187, 0xecd8590680a3aa11},
-      {0xda01ee641a708de9, 0xe80e6f4820cc9495},
-      {0x884134fe908658b2, 0x3109058d147fdcdd},
-      {0xaa51823e34a7eede, 0xbd4b46f0599fd415},
-      {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a},
-      {0x850fadc09923329e, 0x03e2cf6bc604ddb0},
-      {0xa6539930bf6bff45, 0x84db8346b786151c},
-      {0xcfe87f7cef46ff16, 0xe612641865679a63},
-      {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e},
-      {0xa26da3999aef7749, 0xe3be5e330f38f09d},
-      {0xcb090c8001ab551c, 0x5cadf5bfd3072cc5},
-      {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6},
-      {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa},
-      {0xc646d63501a1511d, 0xb281e1fd541501b8},
-      {0xf7d88bc24209a565, 0x1f225a7ca91a4226},
-      {0x9ae757596946075f, 0x3375788de9b06958},
-      {0xc1a12d2fc3978937, 0x0052d6b1641c83ae},
-      {0xf209787bb47d6b84, 0xc0678c5dbd23a49a},
-      {0x9745eb4d50ce6332, 0xf840b7ba963646e0},
-      {0xbd176620a501fbff, 0xb650e5a93bc3d898},
-      {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe},
-      {0x93ba47c980e98cdf, 0xc66f336c36b10137},
-      {0xb8a8d9bbe123f017, 0xb80b0047445d4184},
-      {0xe6d3102ad96cec1d, 0xa60dc059157491e5},
-      {0x9043ea1ac7e41392, 0x87c89837ad68db2f},
-      {0xb454e4a179dd1877, 0x29babe4598c311fb},
-      {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a},
-      {0x8ce2529e2734bb1d, 0x1899e4a65f58660c},
-      {0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f},
-      {0xdc21a1171d42645d, 0x76707543f4fa1f73},
-      {0x899504ae72497eba, 0x6a06494a791c53a8},
-      {0xabfa45da0edbde69, 0x0487db9d17636892},
-      {0xd6f8d7509292d603, 0x45a9d2845d3c42b6},
-      {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2},
-      {0xa7f26836f282b732, 0x8e6cac7768d7141e},
-      {0xd1ef0244af2364ff, 0x3207d795430cd926},
-      {0x8335616aed761f1f, 0x7f44e6bd49e807b8},
-      {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6},
-      {0xcd036837130890a1, 0x36dba887c37a8c0f},
-      {0x802221226be55a64, 0xc2494954da2c9789},
-      {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c},
-      {0xc83553c5c8965d3d, 0x6f92829494e5acc7},
-      {0xfa42a8b73abbf48c, 0xcb772339ba1f17f9},
-      {0x9c69a97284b578d7, 0xff2a760414536efb},
-      {0xc38413cf25e2d70d, 0xfef5138519684aba},
-      {0xf46518c2ef5b8cd1, 0x7eb258665fc25d69},
-      {0x98bf2f79d5993802, 0xef2f773ffbd97a61},
-      {0xbeeefb584aff8603, 0xaafb550ffacfd8fa},
-      {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38},
-      {0x952ab45cfa97a0b2, 0xdd945a747bf26183},
-      {0xba756174393d88df, 0x94f971119aeef9e4},
-      {0xe912b9d1478ceb17, 0x7a37cd5601aab85d},
-      {0x91abb422ccb812ee, 0xac62e055c10ab33a},
-      {0xb616a12b7fe617aa, 0x577b986b314d6009},
-      {0xe39c49765fdf9d94, 0xed5a7e85fda0b80b},
-      {0x8e41ade9fbebc27d, 0x14588f13be847307},
-      {0xb1d219647ae6b31c, 0x596eb2d8ae258fc8},
-      {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb},
-      {0x8aec23d680043bee, 0x25de7bb9480d5854},
-      {0xada72ccc20054ae9, 0xaf561aa79a10ae6a},
-      {0xd910f7ff28069da4, 0x1b2ba1518094da04},
-      {0x87aa9aff79042286, 0x90fb44d2f05d0842},
-      {0xa99541bf57452b28, 0x353a1607ac744a53},
-      {0xd3fa922f2d1675f2, 0x42889b8997915ce8},
-      {0x847c9b5d7c2e09b7, 0x69956135febada11},
-      {0xa59bc234db398c25, 0x43fab9837e699095},
-      {0xcf02b2c21207ef2e, 0x94f967e45e03f4bb},
-      {0x8161afb94b44f57d, 0x1d1be0eebac278f5},
-      {0xa1ba1ba79e1632dc, 0x6462d92a69731732},
-      {0xca28a291859bbf93, 0x7d7b8f7503cfdcfe},
-      {0xfcb2cb35e702af78, 0x5cda735244c3d43e},
-      {0x9defbf01b061adab, 0x3a0888136afa64a7},
-      {0xc56baec21c7a1916, 0x088aaa1845b8fdd0},
-      {0xf6c69a72a3989f5b, 0x8aad549e57273d45},
-      {0x9a3c2087a63f6399, 0x36ac54e2f678864b},
-      {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd},
-      {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5},
-      {0x969eb7c47859e743, 0x9f644ae5a4b1b325},
-      {0xbc4665b596706114, 0x873d5d9f0dde1fee},
-      {0xeb57ff22fc0c7959, 0xa90cb506d155a7ea},
-      {0x9316ff75dd87cbd8, 0x09a7f12442d588f2},
-      {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb2f},
-      {0xe5d3ef282a242e81, 0x8f1668c8a86da5fa},
-      {0x8fa475791a569d10, 0xf96e017d694487bc},
-      {0xb38d92d760ec4455, 0x37c981dcc395a9ac},
-      {0xe070f78d3927556a, 0x85bbe253f47b1417},
-      {0x8c469ab843b89562, 0x93956d7478ccec8e},
-      {0xaf58416654a6babb, 0x387ac8d1970027b2},
-      {0xdb2e51bfe9d0696a, 0x06997b05fcc0319e},
-      {0x88fcf317f22241e2, 0x441fece3bdf81f03},
-      {0xab3c2fddeeaad25a, 0xd527e81cad7626c3},
-      {0xd60b3bd56a5586f1, 0x8a71e223d8d3b074},
-      {0x85c7056562757456, 0xf6872d5667844e49},
-      {0xa738c6bebb12d16c, 0xb428f8ac016561db},
-      {0xd106f86e69d785c7, 0xe13336d701beba52},
-      {0x82a45b450226b39c, 0xecc0024661173473},
-      {0xa34d721642b06084, 0x27f002d7f95d0190},
-      {0xcc20ce9bd35c78a5, 0x31ec038df7b441f4},
-      {0xff290242c83396ce, 0x7e67047175a15271},
-      {0x9f79a169bd203e41, 0x0f0062c6e984d386},
-      {0xc75809c42c684dd1, 0x52c07b78a3e60868},
-      {0xf92e0c3537826145, 0xa7709a56ccdf8a82},
-      {0x9bbcc7a142b17ccb, 0x88a66076400bb691},
-      {0xc2abf989935ddbfe, 0x6acff893d00ea435},
-      {0xf356f7ebf83552fe, 0x0583f6b8c4124d43},
-      {0x98165af37b2153de, 0xc3727a337a8b704a},
-      {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c},
-      {0xeda2ee1c7064130c, 0x1162def06f79df73},
-      {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8},
-      {0xb9a74a0637ce2ee1, 0x6d953e2bd7173692},
-      {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437},
-      {0x910ab1d4db9914a0, 0x1d9c9892400a22a2},
-      {0xb54d5e4a127f59c8, 0x2503beb6d00cab4b},
-      {0xe2a0b5dc971f303a, 0x2e44ae64840fd61d},
-      {0x8da471a9de737e24, 0x5ceaecfed289e5d2},
-      {0xb10d8e1456105dad, 0x7425a83e872c5f47},
-      {0xdd50f1996b947518, 0xd12f124e28f77719},
-      {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f},
-      {0xace73cbfdc0bfb7b, 0x636cc64d1001550b},
-      {0xd8210befd30efa5a, 0x3c47f7e05401aa4e},
-      {0x8714a775e3e95c78, 0x65acfaec34810a71},
-      {0xa8d9d1535ce3b396, 0x7f1839a741a14d0d},
-      {0xd31045a8341ca07c, 0x1ede48111209a050},
-      {0x83ea2b892091e44d, 0x934aed0aab460432},
-      {0xa4e4b66b68b65d60, 0xf81da84d5617853f},
-      {0xce1de40642e3f4b9, 0x36251260ab9d668e},
-      {0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019},
-      {0xa1075a24e4421730, 0xb24cf65b8612f81f},
-      {0xc94930ae1d529cfc, 0xdee033f26797b627},
-      {0xfb9b7cd9a4a7443c, 0x169840ef017da3b1},
-      {0x9d412e0806e88aa5, 0x8e1f289560ee864e},
-      {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2},
-      {0xf5b5d7ec8acb58a2, 0xae10af696774b1db},
-      {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29},
-      {0xbff610b0cc6edd3f, 0x17fd090a58d32af3},
-      {0xeff394dcff8a948e, 0xddfc4b4cef07f5b0},
-      {0x95f83d0a1fb69cd9, 0x4abdaf101564f98e},
-      {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1},
-      {0xea53df5fd18d5513, 0x84c86189216dc5ed},
-      {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4},
-      {0xb7118682dbb66a77, 0x3fbc8c33221dc2a1},
-      {0xe4d5e82392a40515, 0x0fabaf3feaa5334a},
-      {0x8f05b1163ba6832d, 0x29cb4d87f2a7400e},
-      {0xb2c71d5bca9023f8, 0x743e20e9ef511012},
-      {0xdf78e4b2bd342cf6, 0x914da9246b255416},
-      {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e},
-      {0xae9672aba3d0c320, 0xa184ac2473b529b1},
-      {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e},
-      {0x8865899617fb1871, 0x7e2fa67c7a658892},
-      {0xaa7eebfb9df9de8d, 0xddbb901b98feeab7},
-      {0xd51ea6fa85785631, 0x552a74227f3ea565},
-      {0x8533285c936b35de, 0xd53a88958f87275f},
-      {0xa67ff273b8460356, 0x8a892abaf368f137},
-      {0xd01fef10a657842c, 0x2d2b7569b0432d85},
-      {0x8213f56a67f6b29b, 0x9c3b29620e29fc73},
-      {0xa298f2c501f45f42, 0x8349f3ba91b47b8f},
-      {0xcb3f2f7642717713, 0x241c70a936219a73},
-      {0xfe0efb53d30dd4d7, 0xed238cd383aa0110},
-      {0x9ec95d1463e8a506, 0xf4363804324a40aa},
-      {0xc67bb4597ce2ce48, 0xb143c6053edcd0d5},
-      {0xf81aa16fdc1b81da, 0xdd94b7868e94050a},
-      {0x9b10a4e5e9913128, 0xca7cf2b4191c8326},
-      {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0},
-      {0xf24a01a73cf2dccf, 0xbc633b39673c8cec},
-      {0x976e41088617ca01, 0xd5be0503e085d813},
-      {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18},
-      {0xec9c459d51852ba2, 0xddf8e7d60ed1219e},
-      {0x93e1ab8252f33b45, 0xcabb90e5c942b503},
-      {0xb8da1662e7b00a17, 0x3d6a751f3b936243},
-      {0xe7109bfba19c0c9d, 0x0cc512670a783ad4},
-      {0x906a617d450187e2, 0x27fb2b80668b24c5},
-      {0xb484f9dc9641e9da, 0xb1f9f660802dedf6},
-      {0xe1a63853bbd26451, 0x5e7873f8a0396973},
-      {0x8d07e33455637eb2, 0xdb0b487b6423e1e8},
-      {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62},
-      {0xdc5c5301c56b75f7, 0x7641a140cc7810fb},
-      {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d},
-      {0xac2820d9623bf429, 0x546345fa9fbdcd44},
-      {0xd732290fbacaf133, 0xa97c177947ad4095},
-      {0x867f59a9d4bed6c0, 0x49ed8eabcccc485d},
-      {0xa81f301449ee8c70, 0x5c68f256bfff5a74},
-      {0xd226fc195c6a2f8c, 0x73832eec6fff3111},
-      {0x83585d8fd9c25db7, 0xc831fd53c5ff7eab},
-      {0xa42e74f3d032f525, 0xba3e7ca8b77f5e55},
-      {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb},
-      {0x80444b5e7aa7cf85, 0x7980d163cf5b81b3},
-      {0xa0555e361951c366, 0xd7e105bcc332621f},
-      {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7},
-      {0xfa856334878fc150, 0xb14f98f6f0feb951},
-      {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3},
-      {0xc3b8358109e84f07, 0x0a862f80ec4700c8},
-      {0xf4a642e14c6262c8, 0xcd27bb612758c0fa},
-      {0x98e7e9cccfbd7dbd, 0x8038d51cb897789c},
-      {0xbf21e44003acdd2c, 0xe0470a63e6bd56c3},
-      {0xeeea5d5004981478, 0x1858ccfce06cac74},
-      {0x95527a5202df0ccb, 0x0f37801e0c43ebc8},
-      {0xbaa718e68396cffd, 0xd30560258f54e6ba},
-      {0xe950df20247c83fd, 0x47c6b82ef32a2069},
-      {0x91d28b7416cdd27e, 0x4cdc331d57fa5441},
-      {0xb6472e511c81471d, 0xe0133fe4adf8e952},
-      {0xe3d8f9e563a198e5, 0x58180fddd97723a6},
-      {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648},
-      {0xb201833b35d63f73, 0x2cd2cc6551e513da},
-      {0xde81e40a034bcf4f, 0xf8077f7ea65e58d1},
-      {0x8b112e86420f6191, 0xfb04afaf27faf782},
-      {0xadd57a27d29339f6, 0x79c5db9af1f9b563},
-      {0xd94ad8b1c7380874, 0x18375281ae7822bc},
-      {0x87cec76f1c830548, 0x8f2293910d0b15b5},
-      {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb22},
-      {0xd433179d9c8cb841, 0x5fa60692a46151eb},
-      {0x849feec281d7f328, 0xdbc7c41ba6bcd333},
-      {0xa5c7ea73224deff3, 0x12b9b522906c0800},
-      {0xcf39e50feae16bef, 0xd768226b34870a00},
-      {0x81842f29f2cce375, 0xe6a1158300d46640},
-      {0xa1e53af46f801c53, 0x60495ae3c1097fd0},
-      {0xca5e89b18b602368, 0x385bb19cb14bdfc4},
-      {0xfcf62c1dee382c42, 0x46729e03dd9ed7b5},
-      {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d1},
-      {0xc5a05277621be293, 0xc7098b7305241885},
-      { 0xf70867153aa2db38,
-        0xb8cbee4fc66d1ea7 }
-#else
-      {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},
-      {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
-      {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f},
-      {0x86a8d39ef77164bc, 0xae5dff9c02033198},
-      {0xd98ddaee19068c76, 0x3badd624dd9b0958},
-      {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
-      {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2},
-      {0xe55990879ddcaabd, 0xcc420a6a101d0516},
-      {0xb94470938fa89bce, 0xf808e40e8d5b3e6a},
-      {0x95a8637627989aad, 0xdde7001379a44aa9},
-      {0xf1c90080baf72cb1, 0x5324c68b12dd6339},
-      {0xc350000000000000, 0x0000000000000000},
-      {0x9dc5ada82b70b59d, 0xf020000000000000},
-      {0xfee50b7025c36a08, 0x02f236d04753d5b4},
-      {0xcde6fd5e09abcf26, 0xed4c0226b55e6f86},
-      {0xa6539930bf6bff45, 0x84db8346b786151c},
-      {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b2},
-      {0xd910f7ff28069da4, 0x1b2ba1518094da04},
-      {0xaf58416654a6babb, 0x387ac8d1970027b2},
-      {0x8da471a9de737e24, 0x5ceaecfed289e5d2},
-      {0xe4d5e82392a40515, 0x0fabaf3feaa5334a},
-      {0xb8da1662e7b00a17, 0x3d6a751f3b936243},
-      { 0x95527a5202df0ccb,
-        0x0f37801e0c43ebc8 }
-#endif
-    };
-
-#if FMT_USE_FULL_CACHE_DRAGONBOX
-    return pow10_significands[k - float_info<double>::min_k];
-#else
-    static constexpr const uint64_t powers_of_5_64[] = {
-        0x0000000000000001, 0x0000000000000005, 0x0000000000000019,
-        0x000000000000007d, 0x0000000000000271, 0x0000000000000c35,
-        0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1,
-        0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd,
-        0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9,
-        0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5,
-        0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631,
-        0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed,
-        0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9};
-
-    static constexpr const uint32_t pow10_recovery_errors[] = {
-        0x50001400, 0x54044100, 0x54014555, 0x55954415, 0x54115555, 0x00000001,
-        0x50000000, 0x00104000, 0x54010004, 0x05004001, 0x55555544, 0x41545555,
-        0x54040551, 0x15445545, 0x51555514, 0x10000015, 0x00101100, 0x01100015,
-        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04450514, 0x45414110,
-        0x55555145, 0x50544050, 0x15040155, 0x11054140, 0x50111514, 0x11451454,
-        0x00400541, 0x00000000, 0x55555450, 0x10056551, 0x10054011, 0x55551014,
-        0x69514555, 0x05151109, 0x00155555};
-
-    static const int compression_ratio = 27;
-
-    // Compute base index.
-    int cache_index = (k - float_info<double>::min_k) / compression_ratio;
-    int kb = cache_index * compression_ratio + float_info<double>::min_k;
-    int offset = k - kb;
-
-    // Get base cache.
-    uint128_wrapper base_cache = pow10_significands[cache_index];
-    if (offset == 0) return base_cache;
-
-    // Compute the required amount of bit-shift.
-    int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset;
-    FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected");
-
-    // Try to recover the real cache.
-    uint64_t pow5 = powers_of_5_64[offset];
-    uint128_wrapper recovered_cache = umul128(base_cache.high(), pow5);
-    uint128_wrapper middle_low =
-        umul128(base_cache.low() - (kb < 0 ? 1u : 0u), pow5);
-
-    recovered_cache += middle_low.high();
-
-    uint64_t high_to_middle = recovered_cache.high() << (64 - alpha);
-    uint64_t middle_to_low = recovered_cache.low() << (64 - alpha);
-
-    recovered_cache =
-        uint128_wrapper{(recovered_cache.low() >> alpha) | high_to_middle,
-                        ((middle_low.low() >> alpha) | middle_to_low)};
-
-    if (kb < 0) recovered_cache += 1;
-
-    // Get error.
-    int error_idx = (k - float_info<double>::min_k) / 16;
-    uint32_t error = (pow10_recovery_errors[error_idx] >>
-                      ((k - float_info<double>::min_k) % 16) * 2) &
-                     0x3;
-
-    // Add the error back.
-    FMT_ASSERT(recovered_cache.low() + error >= recovered_cache.low(), "");
-    return {recovered_cache.high(), recovered_cache.low() + error};
-#endif
-  }
-
-  static carrier_uint compute_mul(carrier_uint u,
-                                  const cache_entry_type& cache) FMT_NOEXCEPT {
-    return umul192_upper64(u, cache);
-  }
-
-  static uint32_t compute_delta(cache_entry_type const& cache,
-                                int beta_minus_1) FMT_NOEXCEPT {
-    return static_cast<uint32_t>(cache.high() >> (64 - 1 - beta_minus_1));
-  }
-
-  static bool compute_mul_parity(carrier_uint two_f,
-                                 const cache_entry_type& cache,
-                                 int beta_minus_1) FMT_NOEXCEPT {
-    FMT_ASSERT(beta_minus_1 >= 1, "");
-    FMT_ASSERT(beta_minus_1 < 64, "");
-
-    return ((umul192_middle64(two_f, cache) >> (64 - beta_minus_1)) & 1) != 0;
-  }
-
-  static carrier_uint compute_left_endpoint_for_shorter_interval_case(
-      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
-    return (cache.high() -
-            (cache.high() >> (float_info<double>::significand_bits + 2))) >>
-           (64 - float_info<double>::significand_bits - 1 - beta_minus_1);
-  }
-
-  static carrier_uint compute_right_endpoint_for_shorter_interval_case(
-      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
-    return (cache.high() +
-            (cache.high() >> (float_info<double>::significand_bits + 1))) >>
-           (64 - float_info<double>::significand_bits - 1 - beta_minus_1);
-  }
-
-  static carrier_uint compute_round_up_for_shorter_interval_case(
-      const cache_entry_type& cache, int beta_minus_1) FMT_NOEXCEPT {
-    return ((cache.high() >>
-             (64 - float_info<double>::significand_bits - 2 - beta_minus_1)) +
-            1) /
-           2;
-  }
-};
-
-// Various integer checks
-template <class T>
-bool is_left_endpoint_integer_shorter_interval(int exponent) FMT_NOEXCEPT {
-  return exponent >=
-             float_info<
-                 T>::case_shorter_interval_left_endpoint_lower_threshold &&
-         exponent <=
-             float_info<T>::case_shorter_interval_left_endpoint_upper_threshold;
-}
-template <class T>
-bool is_endpoint_integer(typename float_info<T>::carrier_uint two_f,
-                         int exponent, int minus_k) FMT_NOEXCEPT {
-  if (exponent < float_info<T>::case_fc_pm_half_lower_threshold) return false;
-  // For k >= 0.
-  if (exponent <= float_info<T>::case_fc_pm_half_upper_threshold) return true;
-  // For k < 0.
-  if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false;
-  return divisible_by_power_of_5(two_f, minus_k);
-}
-
-template <class T>
-bool is_center_integer(typename float_info<T>::carrier_uint two_f, int exponent,
-                       int minus_k) FMT_NOEXCEPT {
-  // Exponent for 5 is negative.
-  if (exponent > float_info<T>::divisibility_check_by_5_threshold) return false;
-  if (exponent > float_info<T>::case_fc_upper_threshold)
-    return divisible_by_power_of_5(two_f, minus_k);
-  // Both exponents are nonnegative.
-  if (exponent >= float_info<T>::case_fc_lower_threshold) return true;
-  // Exponent for 2 is negative.
-  return divisible_by_power_of_2(two_f, minus_k - exponent + 1);
-}
-
-// Remove trailing zeros from n and return the number of zeros removed (float)
-FMT_INLINE int remove_trailing_zeros(uint32_t& n) FMT_NOEXCEPT {
-#ifdef FMT_BUILTIN_CTZ
-  int t = FMT_BUILTIN_CTZ(n);
-#else
-  int t = ctz(n);
-#endif
-  if (t > float_info<float>::max_trailing_zeros)
-    t = float_info<float>::max_trailing_zeros;
-
-  const uint32_t mod_inv1 = 0xcccccccd;
-  const uint32_t max_quotient1 = 0x33333333;
-  const uint32_t mod_inv2 = 0xc28f5c29;
-  const uint32_t max_quotient2 = 0x0a3d70a3;
-
-  int s = 0;
-  for (; s < t - 1; s += 2) {
-    if (n * mod_inv2 > max_quotient2) break;
-    n *= mod_inv2;
-  }
-  if (s < t && n * mod_inv1 <= max_quotient1) {
-    n *= mod_inv1;
-    ++s;
-  }
-  n >>= s;
-  return s;
-}
-
-// Removes trailing zeros and returns the number of zeros removed (double)
-FMT_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT {
-#ifdef FMT_BUILTIN_CTZLL
-  int t = FMT_BUILTIN_CTZLL(n);
-#else
-  int t = ctzll(n);
-#endif
-  if (t > float_info<double>::max_trailing_zeros)
-    t = float_info<double>::max_trailing_zeros;
-  // Divide by 10^8 and reduce to 32-bits
-  // Since ret_value.significand <= (2^64 - 1) / 1000 < 10^17,
-  // both of the quotient and the r should fit in 32-bits
-
-  const uint32_t mod_inv1 = 0xcccccccd;
-  const uint32_t max_quotient1 = 0x33333333;
-  const uint64_t mod_inv8 = 0xc767074b22e90e21;
-  const uint64_t max_quotient8 = 0x00002af31dc46118;
-
-  // If the number is divisible by 1'0000'0000, work with the quotient
-  if (t >= 8) {
-    auto quotient_candidate = n * mod_inv8;
-
-    if (quotient_candidate <= max_quotient8) {
-      auto quotient = static_cast<uint32_t>(quotient_candidate >> 8);
-
-      int s = 8;
-      for (; s < t; ++s) {
-        if (quotient * mod_inv1 > max_quotient1) break;
-        quotient *= mod_inv1;
-      }
-      quotient >>= (s - 8);
-      n = quotient;
-      return s;
-    }
-  }
-
-  // Otherwise, work with the remainder
-  auto quotient = static_cast<uint32_t>(n / 100000000);
-  auto remainder = static_cast<uint32_t>(n - 100000000 * quotient);
-
-  if (t == 0 || remainder * mod_inv1 > max_quotient1) {
-    return 0;
-  }
-  remainder *= mod_inv1;
-
-  if (t == 1 || remainder * mod_inv1 > max_quotient1) {
-    n = (remainder >> 1) + quotient * 10000000ull;
-    return 1;
-  }
-  remainder *= mod_inv1;
-
-  if (t == 2 || remainder * mod_inv1 > max_quotient1) {
-    n = (remainder >> 2) + quotient * 1000000ull;
-    return 2;
-  }
-  remainder *= mod_inv1;
-
-  if (t == 3 || remainder * mod_inv1 > max_quotient1) {
-    n = (remainder >> 3) + quotient * 100000ull;
-    return 3;
-  }
-  remainder *= mod_inv1;
-
-  if (t == 4 || remainder * mod_inv1 > max_quotient1) {
-    n = (remainder >> 4) + quotient * 10000ull;
-    return 4;
-  }
-  remainder *= mod_inv1;
-
-  if (t == 5 || remainder * mod_inv1 > max_quotient1) {
-    n = (remainder >> 5) + quotient * 1000ull;
-    return 5;
-  }
-  remainder *= mod_inv1;
-
-  if (t == 6 || remainder * mod_inv1 > max_quotient1) {
-    n = (remainder >> 6) + quotient * 100ull;
-    return 6;
-  }
-  remainder *= mod_inv1;
-
-  n = (remainder >> 7) + quotient * 10ull;
-  return 7;
-}
-
-// The main algorithm for shorter interval case
-template <class T>
-FMT_INLINE decimal_fp<T> shorter_interval_case(int exponent) FMT_NOEXCEPT {
-  decimal_fp<T> ret_value;
-  // Compute k and beta
-  const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent);
-  const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k);
-
-  // Compute xi and zi
-  using cache_entry_type = typename cache_accessor<T>::cache_entry_type;
-  const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k);
-
-  auto xi = cache_accessor<T>::compute_left_endpoint_for_shorter_interval_case(
-      cache, beta_minus_1);
-  auto zi = cache_accessor<T>::compute_right_endpoint_for_shorter_interval_case(
-      cache, beta_minus_1);
-
-  // If the left endpoint is not an integer, increase it
-  if (!is_left_endpoint_integer_shorter_interval<T>(exponent)) ++xi;
-
-  // Try bigger divisor
-  ret_value.significand = zi / 10;
-
-  // If succeed, remove trailing zeros if necessary and return
-  if (ret_value.significand * 10 >= xi) {
-    ret_value.exponent = minus_k + 1;
-    ret_value.exponent += remove_trailing_zeros(ret_value.significand);
-    return ret_value;
-  }
-
-  // Otherwise, compute the round-up of y
-  ret_value.significand =
-      cache_accessor<T>::compute_round_up_for_shorter_interval_case(
-          cache, beta_minus_1);
-  ret_value.exponent = minus_k;
-
-  // When tie occurs, choose one of them according to the rule
-  if (exponent >= float_info<T>::shorter_interval_tie_lower_threshold &&
-      exponent <= float_info<T>::shorter_interval_tie_upper_threshold) {
-    ret_value.significand = ret_value.significand % 2 == 0
-                                ? ret_value.significand
-                                : ret_value.significand - 1;
-  } else if (ret_value.significand < xi) {
-    ++ret_value.significand;
-  }
-  return ret_value;
-}
-
-template <typename T> decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT {
-  // Step 1: integer promotion & Schubfach multiplier calculation.
-
-  using carrier_uint = typename float_info<T>::carrier_uint;
-  using cache_entry_type = typename cache_accessor<T>::cache_entry_type;
-  auto br = bit_cast<carrier_uint>(x);
-
-  // Extract significand bits and exponent bits.
-  const carrier_uint significand_mask =
-      (static_cast<carrier_uint>(1) << float_info<T>::significand_bits) - 1;
-  carrier_uint significand = (br & significand_mask);
-  int exponent = static_cast<int>((br & exponent_mask<T>()) >>
-                                  float_info<T>::significand_bits);
-
-  if (exponent != 0) {  // Check if normal.
-    exponent += float_info<T>::exponent_bias - float_info<T>::significand_bits;
-
-    // Shorter interval case; proceed like Schubfach.
-    if (significand == 0) return shorter_interval_case<T>(exponent);
-
-    significand |=
-        (static_cast<carrier_uint>(1) << float_info<T>::significand_bits);
-  } else {
-    // Subnormal case; the interval is always regular.
-    if (significand == 0) return {0, 0};
-    exponent = float_info<T>::min_exponent - float_info<T>::significand_bits;
-  }
-
-  const bool include_left_endpoint = (significand % 2 == 0);
-  const bool include_right_endpoint = include_left_endpoint;
-
-  // Compute k and beta.
-  const int minus_k = floor_log10_pow2(exponent) - float_info<T>::kappa;
-  const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k);
-  const int beta_minus_1 = exponent + floor_log2_pow10(-minus_k);
-
-  // Compute zi and deltai
-  // 10^kappa <= deltai < 10^(kappa + 1)
-  const uint32_t deltai = cache_accessor<T>::compute_delta(cache, beta_minus_1);
-  const carrier_uint two_fc = significand << 1;
-  const carrier_uint two_fr = two_fc | 1;
-  const carrier_uint zi =
-      cache_accessor<T>::compute_mul(two_fr << beta_minus_1, cache);
-
-  // Step 2: Try larger divisor; remove trailing zeros if necessary
-
-  // Using an upper bound on zi, we might be able to optimize the division
-  // better than the compiler; we are computing zi / big_divisor here
-  decimal_fp<T> ret_value;
-  ret_value.significand = divide_by_10_to_kappa_plus_1(zi);
-  uint32_t r = static_cast<uint32_t>(zi - float_info<T>::big_divisor *
-                                              ret_value.significand);
-
-  if (r > deltai) {
-    goto small_divisor_case_label;
-  } else if (r < deltai) {
-    // Exclude the right endpoint if necessary
-    if (r == 0 && !include_right_endpoint &&
-        is_endpoint_integer<T>(two_fr, exponent, minus_k)) {
-      --ret_value.significand;
-      r = float_info<T>::big_divisor;
-      goto small_divisor_case_label;
-    }
-  } else {
-    // r == deltai; compare fractional parts
-    // Check conditions in the order different from the paper
-    // to take advantage of short-circuiting
-    const carrier_uint two_fl = two_fc - 1;
-    if ((!include_left_endpoint ||
-         !is_endpoint_integer<T>(two_fl, exponent, minus_k)) &&
-        !cache_accessor<T>::compute_mul_parity(two_fl, cache, beta_minus_1)) {
-      goto small_divisor_case_label;
-    }
-  }
-  ret_value.exponent = minus_k + float_info<T>::kappa + 1;
-
-  // We may need to remove trailing zeros
-  ret_value.exponent += remove_trailing_zeros(ret_value.significand);
-  return ret_value;
-
-  // Step 3: Find the significand with the smaller divisor
-
-small_divisor_case_label:
-  ret_value.significand *= 10;
-  ret_value.exponent = minus_k + float_info<T>::kappa;
-
-  const uint32_t mask = (1u << float_info<T>::kappa) - 1;
-  auto dist = r - (deltai / 2) + (float_info<T>::small_divisor / 2);
-
-  // Is dist divisible by 2^kappa?
-  if ((dist & mask) == 0) {
-    const bool approx_y_parity =
-        ((dist ^ (float_info<T>::small_divisor / 2)) & 1) != 0;
-    dist >>= float_info<T>::kappa;
-
-    // Is dist divisible by 5^kappa?
-    if (check_divisibility_and_divide_by_pow5<float_info<T>::kappa>(dist)) {
-      ret_value.significand += dist;
-
-      // Check z^(f) >= epsilon^(f)
-      // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
-      // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f)
-      // Since there are only 2 possibilities, we only need to care about the
-      // parity. Also, zi and r should have the same parity since the divisor
-      // is an even number
-      if (cache_accessor<T>::compute_mul_parity(two_fc, cache, beta_minus_1) !=
-          approx_y_parity) {
-        --ret_value.significand;
-      } else {
-        // If z^(f) >= epsilon^(f), we might have a tie
-        // when z^(f) == epsilon^(f), or equivalently, when y is an integer
-        if (is_center_integer<T>(two_fc, exponent, minus_k)) {
-          ret_value.significand = ret_value.significand % 2 == 0
-                                      ? ret_value.significand
-                                      : ret_value.significand - 1;
-        }
-      }
-    }
-    // Is dist not divisible by 5^kappa?
-    else {
-      ret_value.significand += dist;
-    }
-  }
-  // Is dist not divisible by 2^kappa?
-  else {
-    // Since we know dist is small, we might be able to optimize the division
-    // better than the compiler; we are computing dist / small_divisor here
-    ret_value.significand +=
-        small_division_by_pow10<float_info<T>::kappa>(dist);
-  }
-  return ret_value;
-}
-}  // namespace dragonbox
-
-// Formats a floating-point number using a variation of the Fixed-Precision
-// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
-// https://fmt.dev/papers/p372-steele.pdf.
-FMT_CONSTEXPR20 inline void format_dragon(fp value, bool is_predecessor_closer,
-                                          int num_digits, buffer<char>& buf,
-                                          int& exp10) {
-  bigint numerator;    // 2 * R in (FPP)^2.
-  bigint denominator;  // 2 * S in (FPP)^2.
-  // lower and upper are differences between value and corresponding boundaries.
-  bigint lower;             // (M^- in (FPP)^2).
-  bigint upper_store;       // upper's value if different from lower.
-  bigint* upper = nullptr;  // (M^+ in (FPP)^2).
-  // Shift numerator and denominator by an extra bit or two (if lower boundary
-  // is closer) to make lower and upper integers. This eliminates multiplication
-  // by 2 during later computations.
-  int shift = is_predecessor_closer ? 2 : 1;
-  uint64_t significand = value.f << shift;
-  if (value.e >= 0) {
-    numerator.assign(significand);
-    numerator <<= value.e;
-    lower.assign(1);
-    lower <<= value.e;
-    if (shift != 1) {
-      upper_store.assign(1);
-      upper_store <<= value.e + 1;
-      upper = &upper_store;
-    }
-    denominator.assign_pow10(exp10);
-    denominator <<= shift;
-  } else if (exp10 < 0) {
-    numerator.assign_pow10(-exp10);
-    lower.assign(numerator);
-    if (shift != 1) {
-      upper_store.assign(numerator);
-      upper_store <<= 1;
-      upper = &upper_store;
-    }
-    numerator *= significand;
-    denominator.assign(1);
-    denominator <<= shift - value.e;
-  } else {
-    numerator.assign(significand);
-    denominator.assign_pow10(exp10);
-    denominator <<= shift - value.e;
-    lower.assign(1);
-    if (shift != 1) {
-      upper_store.assign(1ULL << 1);
-      upper = &upper_store;
-    }
-  }
-  // Invariant: value == (numerator / denominator) * pow(10, exp10).
-  if (num_digits < 0) {
-    // Generate the shortest representation.
-    if (!upper) upper = &lower;
-    bool even = (value.f & 1) == 0;
-    num_digits = 0;
-    char* data = buf.data();
-    for (;;) {
-      int digit = numerator.divmod_assign(denominator);
-      bool low = compare(numerator, lower) - even < 0;  // numerator <[=] lower.
-      // numerator + upper >[=] pow10:
-      bool high = add_compare(numerator, *upper, denominator) + even > 0;
-      data[num_digits++] = static_cast<char>('0' + digit);
-      if (low || high) {
-        if (!low) {
-          ++data[num_digits - 1];
-        } else if (high) {
-          int result = add_compare(numerator, numerator, denominator);
-          // Round half to even.
-          if (result > 0 || (result == 0 && (digit % 2) != 0))
-            ++data[num_digits - 1];
-        }
-        buf.try_resize(to_unsigned(num_digits));
-        exp10 -= num_digits - 1;
-        return;
-      }
-      numerator *= 10;
-      lower *= 10;
-      if (upper != &lower) *upper *= 10;
-    }
-  }
-  // Generate the given number of digits.
-  exp10 -= num_digits - 1;
-  if (num_digits == 0) {
-    denominator *= 10;
-    auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
-    buf.push_back(digit);
-    return;
-  }
-  buf.try_resize(to_unsigned(num_digits));
-  for (int i = 0; i < num_digits - 1; ++i) {
-    int digit = numerator.divmod_assign(denominator);
-    buf[i] = static_cast<char>('0' + digit);
-    numerator *= 10;
-  }
-  int digit = numerator.divmod_assign(denominator);
-  auto result = add_compare(numerator, numerator, denominator);
-  if (result > 0 || (result == 0 && (digit % 2) != 0)) {
-    if (digit == 9) {
-      const auto overflow = '0' + 10;
-      buf[num_digits - 1] = overflow;
-      // Propagate the carry.
-      for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
-        buf[i] = '0';
-        ++buf[i - 1];
-      }
-      if (buf[0] == overflow) {
-        buf[0] = '1';
-        ++exp10;
-      }
-      return;
-    }
-    ++digit;
-  }
-  buf[num_digits - 1] = static_cast<char>('0' + digit);
-}
-
-template <typename Float>
-FMT_HEADER_ONLY_CONSTEXPR20 int format_float(Float value, int precision,
-                                             float_specs specs,
-                                             buffer<char>& buf) {
-  // float is passed as double to reduce the number of instantiations.
-  static_assert(!std::is_same<Float, float>::value, "");
-  FMT_ASSERT(value >= 0, "value is negative");
-
-  const bool fixed = specs.format == float_format::fixed;
-  if (value <= 0) {  // <= instead of == to silence a warning.
-    if (precision <= 0 || !fixed) {
-      buf.push_back('0');
-      return 0;
-    }
-    buf.try_resize(to_unsigned(precision));
-    fill_n(buf.data(), precision, '0');
-    return -precision;
-  }
-
-  if (specs.fallback) return snprintf_float(value, precision, specs, buf);
-
-  if (!is_constant_evaluated() && precision < 0) {
-    // Use Dragonbox for the shortest format.
-    if (specs.binary32) {
-      auto dec = dragonbox::to_decimal(static_cast<float>(value));
-      write<char>(buffer_appender<char>(buf), dec.significand);
-      return dec.exponent;
-    }
-    auto dec = dragonbox::to_decimal(static_cast<double>(value));
-    write<char>(buffer_appender<char>(buf), dec.significand);
-    return dec.exponent;
-  }
-
-  int exp = 0;
-  bool use_dragon = true;
-  if (is_fast_float<Float>()) {
-    // Use Grisu + Dragon4 for the given precision:
-    // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf.
-    const int min_exp = -60;  // alpha in Grisu.
-    int cached_exp10 = 0;     // K in Grisu.
-    fp normalized = normalize(fp(value));
-    const auto cached_pow = get_cached_power(
-        min_exp - (normalized.e + fp::num_significand_bits), cached_exp10);
-    normalized = normalized * cached_pow;
-    gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed};
-    if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error &&
-        !is_constant_evaluated()) {
-      exp += handler.exp10;
-      buf.try_resize(to_unsigned(handler.size));
-      use_dragon = false;
-    } else {
-      exp += handler.size - cached_exp10 - 1;
-      precision = handler.precision;
-    }
-  }
-  if (use_dragon) {
-    auto f = fp();
-    bool is_predecessor_closer =
-        specs.binary32 ? f.assign(static_cast<float>(value)) : f.assign(value);
-    // Limit precision to the maximum possible number of significant digits in
-    // an IEEE754 double because we don't need to generate zeros.
-    const int max_double_digits = 767;
-    if (precision > max_double_digits) precision = max_double_digits;
-    format_dragon(f, is_predecessor_closer, precision, buf, exp);
-  }
-  if (!fixed && !specs.showpoint) {
-    // Remove trailing zeros.
-    auto num_digits = buf.size();
-    while (num_digits > 0 && buf[num_digits - 1] == '0') {
-      --num_digits;
-      ++exp;
-    }
-    buf.try_resize(num_digits);
-  }
-  return exp;
-}
-
-template <typename T>
-int snprintf_float(T value, int precision, float_specs specs,
-                   buffer<char>& buf) {
-  // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
-  FMT_ASSERT(buf.capacity() > buf.size(), "empty buffer");
-  static_assert(!std::is_same<T, float>::value, "");
-
-  // Subtract 1 to account for the difference in precision since we use %e for
-  // both general and exponent format.
-  if (specs.format == float_format::general ||
-      specs.format == float_format::exp)
-    precision = (precision >= 0 ? precision : 6) - 1;
-
-  // Build the format string.
-  enum { max_format_size = 7 };  // The longest format is "%#.*Le".
-  char format[max_format_size];
-  char* format_ptr = format;
-  *format_ptr++ = '%';
-  if (specs.showpoint && specs.format == float_format::hex) *format_ptr++ = '#';
-  if (precision >= 0) {
-    *format_ptr++ = '.';
-    *format_ptr++ = '*';
-  }
-  if (std::is_same<T, long double>()) *format_ptr++ = 'L';
-  *format_ptr++ = specs.format != float_format::hex
-                      ? (specs.format == float_format::fixed ? 'f' : 'e')
-                      : (specs.upper ? 'A' : 'a');
-  *format_ptr = '\0';
-
-  // Format using snprintf.
-  auto offset = buf.size();
-  for (;;) {
-    auto begin = buf.data() + offset;
-    auto capacity = buf.capacity() - offset;
-#ifdef FMT_FUZZ
-    if (precision > 100000)
-      throw std::runtime_error(
-          "fuzz mode - avoid large allocation inside snprintf");
-#endif
-    // Suppress the warning about a nonliteral format string.
-    // Cannot use auto because of a bug in MinGW (#1532).
-    int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
-    int result = precision >= 0
-                     ? snprintf_ptr(begin, capacity, format, precision, value)
-                     : snprintf_ptr(begin, capacity, format, value);
-    if (result < 0) {
-      // The buffer will grow exponentially.
-      buf.try_reserve(buf.capacity() + 1);
-      continue;
-    }
-    auto size = to_unsigned(result);
-    // Size equal to capacity means that the last character was truncated.
-    if (size >= capacity) {
-      buf.try_reserve(size + offset + 1);  // Add 1 for the terminating '\0'.
-      continue;
-    }
-    auto is_digit = [](char c) { return c >= '0' && c <= '9'; };
-    if (specs.format == float_format::fixed) {
-      if (precision == 0) {
-        buf.try_resize(size);
-        return 0;
-      }
-      // Find and remove the decimal point.
-      auto end = begin + size, p = end;
-      do {
-        --p;
-      } while (is_digit(*p));
-      int fraction_size = static_cast<int>(end - p - 1);
-      std::memmove(p, p + 1, to_unsigned(fraction_size));
-      buf.try_resize(size - 1);
-      return -fraction_size;
-    }
-    if (specs.format == float_format::hex) {
-      buf.try_resize(size + offset);
-      return 0;
-    }
-    // Find and parse the exponent.
-    auto end = begin + size, exp_pos = end;
-    do {
-      --exp_pos;
-    } while (*exp_pos != 'e');
-    char sign = exp_pos[1];
-    FMT_ASSERT(sign == '+' || sign == '-', "");
-    int exp = 0;
-    auto p = exp_pos + 2;  // Skip 'e' and sign.
-    do {
-      FMT_ASSERT(is_digit(*p), "");
-      exp = exp * 10 + (*p++ - '0');
-    } while (p != end);
-    if (sign == '-') exp = -exp;
-    int fraction_size = 0;
-    if (exp_pos != begin + 1) {
-      // Remove trailing zeros.
-      auto fraction_end = exp_pos - 1;
-      while (*fraction_end == '0') --fraction_end;
-      // Move the fractional part left to get rid of the decimal point.
-      fraction_size = static_cast<int>(fraction_end - begin - 1);
-      std::memmove(begin + 1, begin + 2, to_unsigned(fraction_size));
-    }
-    buf.try_resize(to_unsigned(fraction_size) + offset + 1);
-    return exp - fraction_size;
-  }
-}
-}  // namespace detail
-
-template <> struct formatter<detail::bigint> {
-  FMT_CONSTEXPR format_parse_context::iterator parse(
-      format_parse_context& ctx) {
-    return ctx.begin();
-  }
-
-  format_context::iterator format(const detail::bigint& n,
-                                  format_context& ctx) {
-    auto out = ctx.out();
-    bool first = true;
-    for (auto i = n.bigits_.size(); i > 0; --i) {
-      auto value = n.bigits_[i - 1u];
-      if (first) {
-        out = format_to(out, FMT_STRING("{:x}"), value);
-        first = false;
-        continue;
-      }
-      out = format_to(out, FMT_STRING("{:08x}"), value);
-    }
-    if (n.exp_ > 0)
-      out = format_to(out, FMT_STRING("p{}"),
-                      n.exp_ * detail::bigint::bigit_bits);
-    return out;
-  }
-};
-
-FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
-  for_each_codepoint(s, [this](uint32_t cp, string_view) {
-    if (cp == invalid_code_point) FMT_THROW(std::runtime_error("invalid utf8"));
-    if (cp <= 0xFFFF) {
-      buffer_.push_back(static_cast<wchar_t>(cp));
-    } else {
-      cp -= 0x10000;
-      buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10)));
-      buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF)));
-    }
-    return true;
-  });
-  buffer_.push_back(0);
-}
-
-FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
-                                  const char* message) FMT_NOEXCEPT {
-  FMT_TRY {
-    auto ec = std::error_code(error_code, std::generic_category());
-    write(std::back_inserter(out), std::system_error(ec, message).what());
-    return;
-  }
-  FMT_CATCH(...) {}
-  format_error_code(out, error_code, message);
-}
-
-FMT_FUNC void report_system_error(int error_code,
-                                  const char* message) FMT_NOEXCEPT {
-  report_error(format_system_error, error_code, message);
-}
-
-// DEPRECATED!
-// This function is defined here and not inline for ABI compatiblity.
-FMT_FUNC void detail::error_handler::on_error(const char* message) {
-  throw_format_error(message);
-}
-
-FMT_FUNC std::string vformat(string_view fmt, format_args args) {
-  // Don't optimize the "{}" case to keep the binary size small and because it
-  // can be better optimized in fmt::format anyway.
-  auto buffer = memory_buffer();
-  detail::vformat_to(buffer, fmt, args);
-  return to_string(buffer);
-}
-
-#ifdef _WIN32
-namespace detail {
-using dword = conditional_t<sizeof(long) == 4, unsigned long, unsigned>;
-extern "C" __declspec(dllimport) int __stdcall WriteConsoleW(  //
-    void*, const void*, dword, dword*, void*);
-}  // namespace detail
-#endif
-
-namespace detail {
-FMT_FUNC void print(std::FILE* f, string_view text) {
-#ifdef _WIN32
-  auto fd = _fileno(f);
-  if (_isatty(fd)) {
-    detail::utf8_to_utf16 u16(string_view(text.data(), text.size()));
-    auto written = detail::dword();
-    if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)),
-                              u16.c_str(), static_cast<uint32_t>(u16.size()),
-                              &written, nullptr)) {
-      return;
-    }
-    // Fallback to fwrite on failure. It can happen if the output has been
-    // redirected to NUL.
-  }
-#endif
-  detail::fwrite_fully(text.data(), 1, text.size(), f);
-}
-}  // namespace detail
-
-FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
-  memory_buffer buffer;
-  detail::vformat_to(buffer, format_str, args);
-  detail::print(f, {buffer.data(), buffer.size()});
-}
-
-#ifdef _WIN32
-// Print assuming legacy (non-Unicode) encoding.
-FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str,
-                                      format_args args) {
-  memory_buffer buffer;
-  detail::vformat_to(buffer, format_str,
-                     basic_format_args<buffer_context<char>>(args));
-  fwrite_fully(buffer.data(), 1, buffer.size(), f);
-}
-#endif
-
-FMT_FUNC void vprint(string_view format_str, format_args args) {
-  vprint(stdout, format_str, args);
-}
-
-FMT_END_NAMESPACE
-
-#endif  // FMT_FORMAT_INL_H_
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/locale.h b/wpiutil/src/main/native/fmtlib/include/fmt/locale.h
deleted file mode 100644
index 7571b52..0000000
--- a/wpiutil/src/main/native/fmtlib/include/fmt/locale.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "xchar.h"
-#warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/ostream.h b/wpiutil/src/main/native/fmtlib/include/fmt/ostream.h
deleted file mode 100644
index 3d716ec..0000000
--- a/wpiutil/src/main/native/fmtlib/include/fmt/ostream.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Formatting library for C++ - std::ostream support
-//
-// Copyright (c) 2012 - present, Victor Zverovich
-// All rights reserved.
-//
-// For the license information refer to format.h.
-
-#ifndef FMT_OSTREAM_H_
-#define FMT_OSTREAM_H_
-
-#include <ostream>
-
-#include "format.h"
-
-FMT_BEGIN_NAMESPACE
-
-template <typename OutputIt, typename Char> class basic_printf_context;
-
-namespace detail {
-
-// Checks if T has a user-defined operator<<.
-template <typename T, typename Char, typename Enable = void>
-class is_streamable {
- private:
-  template <typename U>
-  static auto test(int)
-      -> bool_constant<sizeof(std::declval<std::basic_ostream<Char>&>()
-                              << std::declval<U>()) != 0>;
-
-  template <typename> static auto test(...) -> std::false_type;
-
-  using result = decltype(test<T>(0));
-
- public:
-  is_streamable() = default;
-
-  static const bool value = result::value;
-};
-
-// Formatting of built-in types and arrays is intentionally disabled because
-// it's handled by standard (non-ostream) formatters.
-template <typename T, typename Char>
-struct is_streamable<
-    T, Char,
-    enable_if_t<
-        std::is_arithmetic<T>::value || std::is_array<T>::value ||
-        std::is_pointer<T>::value || std::is_same<T, char8_type>::value ||
-        std::is_same<T, std::basic_string<Char>>::value ||
-        std::is_same<T, std_string_view<Char>>::value ||
-        (std::is_convertible<T, int>::value && !std::is_enum<T>::value)>>
-    : std::false_type {};
-
-// Write the content of buf to os.
-// It is a separate function rather than a part of vprint to simplify testing.
-template <typename Char>
-void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
-  const Char* buf_data = buf.data();
-  using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
-  unsigned_streamsize size = buf.size();
-  unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
-  do {
-    unsigned_streamsize n = size <= max_size ? size : max_size;
-    os.write(buf_data, static_cast<std::streamsize>(n));
-    buf_data += n;
-    size -= n;
-  } while (size != 0);
-}
-
-template <typename Char, typename T>
-void format_value(buffer<Char>& buf, const T& value,
-                  locale_ref loc = locale_ref()) {
-  auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
-  auto&& output = std::basic_ostream<Char>(&format_buf);
-#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
-  if (loc) output.imbue(loc.get<std::locale>());
-#endif
-  output << value;
-  output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
-  buf.try_resize(buf.size());
-}
-
-// Formats an object of type T that has an overloaded ostream operator<<.
-template <typename T, typename Char>
-struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
-    : private formatter<basic_string_view<Char>, Char> {
-  using formatter<basic_string_view<Char>, Char>::parse;
-
-  template <typename OutputIt>
-  auto format(const T& value, basic_format_context<OutputIt, Char>& ctx)
-      -> OutputIt {
-    auto buffer = basic_memory_buffer<Char>();
-    format_value(buffer, value, ctx.locale());
-    return formatter<basic_string_view<Char>, Char>::format(
-        {buffer.data(), buffer.size()}, ctx);
-  }
-
-  // DEPRECATED!
-  template <typename OutputIt>
-  auto format(const T& value, basic_printf_context<OutputIt, Char>& ctx)
-      -> OutputIt {
-    auto buffer = basic_memory_buffer<Char>();
-    format_value(buffer, value, ctx.locale());
-    return std::copy(buffer.begin(), buffer.end(), ctx.out());
-  }
-};
-}  // namespace detail
-
-FMT_MODULE_EXPORT
-template <typename Char>
-void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
-            basic_format_args<buffer_context<type_identity_t<Char>>> args) {
-  auto buffer = basic_memory_buffer<Char>();
-  detail::vformat_to(buffer, format_str, args);
-  detail::write_buffer(os, buffer);
-}
-
-/**
-  \rst
-  Prints formatted data to the stream *os*.
-
-  **Example**::
-
-    fmt::print(cerr, "Don't {}!", "panic");
-  \endrst
- */
-FMT_MODULE_EXPORT
-template <typename S, typename... Args,
-          typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
-void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
-  vprint(os, to_string_view(format_str),
-         fmt::make_args_checked<Args...>(format_str, args...));
-}
-FMT_END_NAMESPACE
-
-#endif  // FMT_OSTREAM_H_
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/ranges.h b/wpiutil/src/main/native/fmtlib/include/fmt/ranges.h
deleted file mode 100644
index eb9fb8a..0000000
--- a/wpiutil/src/main/native/fmtlib/include/fmt/ranges.h
+++ /dev/null
@@ -1,793 +0,0 @@
-// Formatting library for C++ - experimental range support
-//
-// Copyright (c) 2012 - present, Victor Zverovich
-// All rights reserved.
-//
-// For the license information refer to format.h.
-//
-// Copyright (c) 2018 - present, Remotion (Igor Schulz)
-// All Rights Reserved
-// {fmt} support for ranges, containers and types tuple interface.
-
-#ifndef FMT_RANGES_H_
-#define FMT_RANGES_H_
-
-#include <initializer_list>
-#include <tuple>
-#include <type_traits>
-
-#include "format.h"
-
-FMT_BEGIN_NAMESPACE
-
-namespace detail {
-
-template <typename RangeT, typename OutputIterator>
-OutputIterator copy(const RangeT& range, OutputIterator out) {
-  for (auto it = range.begin(), end = range.end(); it != end; ++it)
-    *out++ = *it;
-  return out;
-}
-
-template <typename OutputIterator>
-OutputIterator copy(const char* str, OutputIterator out) {
-  while (*str) *out++ = *str++;
-  return out;
-}
-
-template <typename OutputIterator>
-OutputIterator copy(char ch, OutputIterator out) {
-  *out++ = ch;
-  return out;
-}
-
-template <typename OutputIterator>
-OutputIterator copy(wchar_t ch, OutputIterator out) {
-  *out++ = ch;
-  return out;
-}
-
-// Returns true if T has a std::string-like interface, like std::string_view.
-template <typename T> class is_std_string_like {
-  template <typename U>
-  static auto check(U* p)
-      -> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
-  template <typename> static void check(...);
-
- public:
-  static FMT_CONSTEXPR_DECL const bool value =
-      is_string<T>::value ||
-      std::is_convertible<T, std_string_view<char>>::value ||
-      !std::is_void<decltype(check<T>(nullptr))>::value;
-};
-
-template <typename Char>
-struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};
-
-template <typename T> class is_map {
-  template <typename U> static auto check(U*) -> typename U::mapped_type;
-  template <typename> static void check(...);
-
- public:
-#ifdef FMT_FORMAT_MAP_AS_LIST
-  static FMT_CONSTEXPR_DECL const bool value = false;
-#else
-  static FMT_CONSTEXPR_DECL const bool value =
-      !std::is_void<decltype(check<T>(nullptr))>::value;
-#endif
-};
-
-template <typename T> class is_set {
-  template <typename U> static auto check(U*) -> typename U::key_type;
-  template <typename> static void check(...);
-
- public:
-#ifdef FMT_FORMAT_SET_AS_LIST
-  static FMT_CONSTEXPR_DECL const bool value = false;
-#else
-  static FMT_CONSTEXPR_DECL const bool value =
-      !std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
-#endif
-};
-
-template <typename... Ts> struct conditional_helper {};
-
-template <typename T, typename _ = void> struct is_range_ : std::false_type {};
-
-#if !FMT_MSC_VER || FMT_MSC_VER > 1800
-
-#  define FMT_DECLTYPE_RETURN(val)  \
-    ->decltype(val) { return val; } \
-    static_assert(                  \
-        true, "")  // This makes it so that a semicolon is required after the
-                   // macro, which helps clang-format handle the formatting.
-
-// C array overload
-template <typename T, std::size_t N>
-auto range_begin(const T (&arr)[N]) -> const T* {
-  return arr;
-}
-template <typename T, std::size_t N>
-auto range_end(const T (&arr)[N]) -> const T* {
-  return arr + N;
-}
-
-template <typename T, typename Enable = void>
-struct has_member_fn_begin_end_t : std::false_type {};
-
-template <typename T>
-struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
-                                           decltype(std::declval<T>().end())>>
-    : std::true_type {};
-
-// Member function overload
-template <typename T>
-auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
-template <typename T>
-auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
-
-// ADL overload. Only participates in overload resolution if member functions
-// are not found.
-template <typename T>
-auto range_begin(T&& rng)
-    -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
-                   decltype(begin(static_cast<T&&>(rng)))> {
-  return begin(static_cast<T&&>(rng));
-}
-template <typename T>
-auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
-                                       decltype(end(static_cast<T&&>(rng)))> {
-  return end(static_cast<T&&>(rng));
-}
-
-template <typename T, typename Enable = void>
-struct has_const_begin_end : std::false_type {};
-template <typename T, typename Enable = void>
-struct has_mutable_begin_end : std::false_type {};
-
-template <typename T>
-struct has_const_begin_end<
-    T,
-    void_t<
-        decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
-        decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
-    : std::true_type {};
-
-template <typename T>
-struct has_mutable_begin_end<
-    T, void_t<decltype(detail::range_begin(std::declval<T>())),
-              decltype(detail::range_end(std::declval<T>())),
-              enable_if_t<std::is_copy_constructible<T>::value>>>
-    : std::true_type {};
-
-template <typename T>
-struct is_range_<T, void>
-    : std::integral_constant<bool, (has_const_begin_end<T>::value ||
-                                    has_mutable_begin_end<T>::value)> {};
-#  undef FMT_DECLTYPE_RETURN
-#endif
-
-// tuple_size and tuple_element check.
-template <typename T> class is_tuple_like_ {
-  template <typename U>
-  static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
-  template <typename> static void check(...);
-
- public:
-  static FMT_CONSTEXPR_DECL const bool value =
-      !std::is_void<decltype(check<T>(nullptr))>::value;
-};
-
-// Check for integer_sequence
-#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
-template <typename T, T... N>
-using integer_sequence = std::integer_sequence<T, N...>;
-template <size_t... N> using index_sequence = std::index_sequence<N...>;
-template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
-#else
-template <typename T, T... N> struct integer_sequence {
-  using value_type = T;
-
-  static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
-};
-
-template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
-
-template <typename T, size_t N, T... Ns>
-struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
-template <typename T, T... Ns>
-struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
-
-template <size_t N>
-using make_index_sequence = make_integer_sequence<size_t, N>;
-#endif
-
-template <class Tuple, class F, size_t... Is>
-void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT {
-  using std::get;
-  // using free function get<I>(T) now.
-  const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
-  (void)_;  // blocks warnings
-}
-
-template <class T>
-FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(
-    T const&) {
-  return {};
-}
-
-template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
-  const auto indexes = get_indexes(tup);
-  for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
-}
-
-template <typename Range>
-using value_type =
-    remove_cvref_t<decltype(*detail::range_begin(std::declval<Range>()))>;
-
-template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
-  *out++ = ',';
-  *out++ = ' ';
-  return out;
-}
-
-struct singleton {
-  unsigned char upper;
-  unsigned char lower_count;
-};
-
-inline auto is_printable(uint16_t x, const singleton* singletons,
-                         size_t singletons_size,
-                         const unsigned char* singleton_lowers,
-                         const unsigned char* normal, size_t normal_size)
-    -> bool {
-  auto upper = x >> 8;
-  auto lower_start = 0;
-  for (size_t i = 0; i < singletons_size; ++i) {
-    auto s = singletons[i];
-    auto lower_end = lower_start + s.lower_count;
-    if (upper < s.upper) break;
-    if (upper == s.upper) {
-      for (auto j = lower_start; j < lower_end; ++j) {
-        if (singleton_lowers[j] == (x & 0xff)) return false;
-      }
-    }
-    lower_start = lower_end;
-  }
-
-  auto xsigned = static_cast<int>(x);
-  auto current = true;
-  for (size_t i = 0; i < normal_size; ++i) {
-    auto v = static_cast<int>(normal[i]);
-    auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v;
-    xsigned -= len;
-    if (xsigned < 0) break;
-    current = !current;
-  }
-  return current;
-}
-
-// Returns true iff the code point cp is printable.
-// This code is generated by support/printable.py.
-inline auto is_printable(uint32_t cp) -> bool {
-  static constexpr singleton singletons0[] = {
-      {0x00, 1},  {0x03, 5},  {0x05, 6},  {0x06, 3},  {0x07, 6},  {0x08, 8},
-      {0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13},
-      {0x0f, 4},  {0x10, 3},  {0x12, 18}, {0x13, 9},  {0x16, 1},  {0x17, 5},
-      {0x18, 2},  {0x19, 3},  {0x1a, 7},  {0x1c, 2},  {0x1d, 1},  {0x1f, 22},
-      {0x20, 3},  {0x2b, 3},  {0x2c, 2},  {0x2d, 11}, {0x2e, 1},  {0x30, 3},
-      {0x31, 2},  {0x32, 1},  {0xa7, 2},  {0xa9, 2},  {0xaa, 4},  {0xab, 8},
-      {0xfa, 2},  {0xfb, 5},  {0xfd, 4},  {0xfe, 3},  {0xff, 9},
-  };
-  static constexpr unsigned char singletons0_lower[] = {
-      0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90,
-      0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f,
-      0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1,
-      0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04,
-      0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d,
-      0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf,
-      0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
-      0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d,
-      0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d,
-      0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d,
-      0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5,
-      0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7,
-      0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49,
-      0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7,
-      0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7,
-      0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e,
-      0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16,
-      0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e,
-      0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f,
-      0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,
-      0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0,
-      0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,
-      0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91,
-      0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7,
-      0xfe, 0xff,
-  };
-  static constexpr singleton singletons1[] = {
-      {0x00, 6},  {0x01, 1}, {0x03, 1},  {0x04, 2}, {0x08, 8},  {0x09, 2},
-      {0x0a, 5},  {0x0b, 2}, {0x0e, 4},  {0x10, 1}, {0x11, 2},  {0x12, 5},
-      {0x13, 17}, {0x14, 1}, {0x15, 2},  {0x17, 2}, {0x19, 13}, {0x1c, 5},
-      {0x1d, 8},  {0x24, 1}, {0x6a, 3},  {0x6b, 2}, {0xbc, 2},  {0xd1, 2},
-      {0xd4, 12}, {0xd5, 9}, {0xd6, 2},  {0xd7, 2}, {0xda, 1},  {0xe0, 5},
-      {0xe1, 2},  {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2},  {0xf9, 2},
-      {0xfa, 2},  {0xfb, 1},
-  };
-  static constexpr unsigned char singletons1_lower[] = {
-      0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07,
-      0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36,
-      0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87,
-      0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
-      0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b,
-      0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9,
-      0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66,
-      0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27,
-      0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc,
-      0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7,
-      0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6,
-      0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c,
-      0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66,
-      0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0,
-      0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93,
-  };
-  static constexpr unsigned char normal0[] = {
-      0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04,
-      0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0,
-      0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01,
-      0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03,
-      0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03,
-      0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a,
-      0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15,
-      0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f,
-      0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80,
-      0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07,
-      0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06,
-      0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04,
-      0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac,
-      0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c,
-      0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11,
-      0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c,
-      0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b,
-      0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6,
-      0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03,
-      0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80,
-      0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06,
-      0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c,
-      0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17,
-      0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80,
-      0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80,
-      0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d,
-  };
-  static constexpr unsigned char normal1[] = {
-      0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f,
-      0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e,
-      0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04,
-      0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09,
-      0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16,
-      0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f,
-      0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36,
-      0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33,
-      0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08,
-      0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e,
-      0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41,
-      0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03,
-      0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22,
-      0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04,
-      0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45,
-      0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03,
-      0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81,
-      0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75,
-      0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1,
-      0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a,
-      0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11,
-      0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09,
-      0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89,
-      0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6,
-      0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09,
-      0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50,
-      0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05,
-      0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83,
-      0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05,
-      0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80,
-      0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80,
-      0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07,
-      0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e,
-      0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07,
-      0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06,
-  };
-  auto lower = static_cast<uint16_t>(cp);
-  if (cp < 0x10000) {
-    return is_printable(lower, singletons0,
-                        sizeof(singletons0) / sizeof(*singletons0),
-                        singletons0_lower, normal0, sizeof(normal0));
-  }
-  if (cp < 0x20000) {
-    return is_printable(lower, singletons1,
-                        sizeof(singletons1) / sizeof(*singletons1),
-                        singletons1_lower, normal1, sizeof(normal1));
-  }
-  if (0x2a6de <= cp && cp < 0x2a700) return false;
-  if (0x2b735 <= cp && cp < 0x2b740) return false;
-  if (0x2b81e <= cp && cp < 0x2b820) return false;
-  if (0x2cea2 <= cp && cp < 0x2ceb0) return false;
-  if (0x2ebe1 <= cp && cp < 0x2f800) return false;
-  if (0x2fa1e <= cp && cp < 0x30000) return false;
-  if (0x3134b <= cp && cp < 0xe0100) return false;
-  if (0xe01f0 <= cp && cp < 0x110000) return false;
-  return cp < 0x110000;
-}
-
-inline auto needs_escape(uint32_t cp) -> bool {
-  return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' ||
-         !is_printable(cp);
-}
-
-template <typename Char> struct find_escape_result {
-  const Char* begin;
-  const Char* end;
-  uint32_t cp;
-};
-
-template <typename Char>
-auto find_escape(const Char* begin, const Char* end)
-    -> find_escape_result<Char> {
-  for (; begin != end; ++begin) {
-    auto cp = static_cast<typename std::make_unsigned<Char>::type>(*begin);
-    if (sizeof(Char) == 1 && cp >= 0x80) continue;
-    if (needs_escape(cp)) return {begin, begin + 1, cp};
-  }
-  return {begin, nullptr, 0};
-}
-
-inline auto find_escape(const char* begin, const char* end)
-    -> find_escape_result<char> {
-  if (!is_utf8()) return find_escape<char>(begin, end);
-  auto result = find_escape_result<char>{end, nullptr, 0};
-  for_each_codepoint(string_view(begin, to_unsigned(end - begin)),
-                     [&](uint32_t cp, string_view sv) {
-                       if (needs_escape(cp)) {
-                         result = {sv.begin(), sv.end(), cp};
-                         return false;
-                       }
-                       return true;
-                     });
-  return result;
-}
-
-template <typename Char, typename OutputIt>
-auto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt {
-  *out++ = '"';
-  auto begin = str.begin(), end = str.end();
-  do {
-    auto escape = find_escape(begin, end);
-    out = copy_str<Char>(begin, escape.begin, out);
-    begin = escape.end;
-    if (!begin) break;
-    auto c = static_cast<Char>(escape.cp);
-    switch (escape.cp) {
-    case '\n':
-      *out++ = '\\';
-      c = 'n';
-      break;
-    case '\r':
-      *out++ = '\\';
-      c = 'r';
-      break;
-    case '\t':
-      *out++ = '\\';
-      c = 't';
-      break;
-    case '"':
-      FMT_FALLTHROUGH;
-    case '\\':
-      *out++ = '\\';
-      break;
-    default:
-      if (is_utf8()) {
-        if (escape.cp < 0x100) {
-          out = format_to(out, "\\x{:02x}", escape.cp);
-          continue;
-        }
-        if (escape.cp < 0x10000) {
-          out = format_to(out, "\\u{:04x}", escape.cp);
-          continue;
-        }
-        if (escape.cp < 0x110000) {
-          out = format_to(out, "\\U{:08x}", escape.cp);
-          continue;
-        }
-      }
-      for (Char escape_char : basic_string_view<Char>(
-               escape.begin, to_unsigned(escape.end - escape.begin))) {
-        out = format_to(
-            out, "\\x{:02x}",
-            static_cast<typename std::make_unsigned<Char>::type>(escape_char));
-      }
-      continue;
-    }
-    *out++ = c;
-  } while (begin != end);
-  *out++ = '"';
-  return out;
-}
-
-template <typename Char, typename OutputIt, typename T,
-          FMT_ENABLE_IF(std::is_convertible<T, std_string_view<char>>::value)>
-inline auto write_range_entry(OutputIt out, const T& str) -> OutputIt {
-  auto sv = std_string_view<Char>(str);
-  return write_range_entry<Char>(out, basic_string_view<Char>(sv));
-}
-
-template <typename Char, typename OutputIt, typename Arg,
-          FMT_ENABLE_IF(std::is_same<Arg, Char>::value)>
-OutputIt write_range_entry(OutputIt out, const Arg v) {
-  *out++ = '\'';
-  *out++ = v;
-  *out++ = '\'';
-  return out;
-}
-
-template <
-    typename Char, typename OutputIt, typename Arg,
-    FMT_ENABLE_IF(!is_std_string_like<typename std::decay<Arg>::type>::value &&
-                  !std::is_same<Arg, Char>::value)>
-OutputIt write_range_entry(OutputIt out, const Arg& v) {
-  return write<Char>(out, v);
-}
-
-}  // namespace detail
-
-template <typename T> struct is_tuple_like {
-  static FMT_CONSTEXPR_DECL const bool value =
-      detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
-};
-
-template <typename TupleT, typename Char>
-struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
- private:
-  // C++11 generic lambda for format().
-  template <typename FormatContext> struct format_each {
-    template <typename T> void operator()(const T& v) {
-      if (i > 0) out = detail::write_delimiter(out);
-      out = detail::write_range_entry<Char>(out, v);
-      ++i;
-    }
-    int i;
-    typename FormatContext::iterator& out;
-  };
-
- public:
-  template <typename ParseContext>
-  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
-    return ctx.begin();
-  }
-
-  template <typename FormatContext = format_context>
-  auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
-    auto out = ctx.out();
-    *out++ = '(';
-    detail::for_each(values, format_each<FormatContext>{0, out});
-    *out++ = ')';
-    return out;
-  }
-};
-
-template <typename T, typename Char> struct is_range {
-  static FMT_CONSTEXPR_DECL const bool value =
-      detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
-      !detail::is_map<T>::value &&
-      !std::is_convertible<T, std::basic_string<Char>>::value &&
-      !std::is_constructible<detail::std_string_view<Char>, T>::value;
-};
-
-template <typename T, typename Char>
-struct formatter<
-    T, Char,
-    enable_if_t<
-        fmt::is_range<T, Char>::value
-// Workaround a bug in MSVC 2019 and earlier.
-#if !FMT_MSC_VER
-        && (is_formattable<detail::value_type<T>, Char>::value ||
-            detail::has_fallback_formatter<detail::value_type<T>, Char>::value)
-#endif
-        >> {
-  template <typename ParseContext>
-  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
-    return ctx.begin();
-  }
-
-  template <
-      typename FormatContext, typename U,
-      FMT_ENABLE_IF(
-          std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
-                                        const T, T>>::value)>
-  auto format(U& range, FormatContext& ctx) -> decltype(ctx.out()) {
-#ifdef FMT_DEPRECATED_BRACED_RANGES
-    Char prefix = '{';
-    Char postfix = '}';
-#else
-    Char prefix = detail::is_set<T>::value ? '{' : '[';
-    Char postfix = detail::is_set<T>::value ? '}' : ']';
-#endif
-    auto out = ctx.out();
-    *out++ = prefix;
-    int i = 0;
-    auto it = std::begin(range);
-    auto end = std::end(range);
-    for (; it != end; ++it) {
-      if (i > 0) out = detail::write_delimiter(out);
-      out = detail::write_range_entry<Char>(out, *it);
-      ++i;
-    }
-    *out++ = postfix;
-    return out;
-  }
-};
-
-template <typename T, typename Char>
-struct formatter<
-    T, Char,
-    enable_if_t<
-        detail::is_map<T>::value
-// Workaround a bug in MSVC 2019 and earlier.
-#if !FMT_MSC_VER
-        && (is_formattable<detail::value_type<T>, Char>::value ||
-            detail::has_fallback_formatter<detail::value_type<T>, Char>::value)
-#endif
-        >> {
-  template <typename ParseContext>
-  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
-    return ctx.begin();
-  }
-
-  template <
-      typename FormatContext, typename U,
-      FMT_ENABLE_IF(
-          std::is_same<U, conditional_t<detail::has_const_begin_end<T>::value,
-                                        const T, T>>::value)>
-  auto format(U& map, FormatContext& ctx) -> decltype(ctx.out()) {
-    auto out = ctx.out();
-    *out++ = '{';
-    int i = 0;
-    for (const auto& item : map) {
-      if (i > 0) out = detail::write_delimiter(out);
-      out = detail::write_range_entry<Char>(out, item.first);
-      *out++ = ':';
-      *out++ = ' ';
-      out = detail::write_range_entry<Char>(out, item.second);
-      ++i;
-    }
-    *out++ = '}';
-    return out;
-  }
-};
-
-template <typename Char, typename... T> struct tuple_join_view : detail::view {
-  const std::tuple<T...>& tuple;
-  basic_string_view<Char> sep;
-
-  tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
-      : tuple(t), sep{s} {}
-};
-
-template <typename Char, typename... T>
-using tuple_arg_join = tuple_join_view<Char, T...>;
-
-// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
-// support in tuple_join. It is disabled by default because of issues with
-// the dynamic width and precision.
-#ifndef FMT_TUPLE_JOIN_SPECIFIERS
-#  define FMT_TUPLE_JOIN_SPECIFIERS 0
-#endif
-
-template <typename Char, typename... T>
-struct formatter<tuple_join_view<Char, T...>, Char> {
-  template <typename ParseContext>
-  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
-    return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
-  }
-
-  template <typename FormatContext>
-  auto format(const tuple_join_view<Char, T...>& value,
-              FormatContext& ctx) const -> typename FormatContext::iterator {
-    return do_format(value, ctx,
-                     std::integral_constant<size_t, sizeof...(T)>());
-  }
-
- private:
-  std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
-
-  template <typename ParseContext>
-  FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
-                              std::integral_constant<size_t, 0>)
-      -> decltype(ctx.begin()) {
-    return ctx.begin();
-  }
-
-  template <typename ParseContext, size_t N>
-  FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
-                              std::integral_constant<size_t, N>)
-      -> decltype(ctx.begin()) {
-    auto end = ctx.begin();
-#if FMT_TUPLE_JOIN_SPECIFIERS
-    end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
-    if (N > 1) {
-      auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
-      if (end != end1)
-        FMT_THROW(format_error("incompatible format specs for tuple elements"));
-    }
-#endif
-    return end;
-  }
-
-  template <typename FormatContext>
-  auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
-                 std::integral_constant<size_t, 0>) const ->
-      typename FormatContext::iterator {
-    return ctx.out();
-  }
-
-  template <typename FormatContext, size_t N>
-  auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
-                 std::integral_constant<size_t, N>) const ->
-      typename FormatContext::iterator {
-    auto out = std::get<sizeof...(T) - N>(formatters_)
-                   .format(std::get<sizeof...(T) - N>(value.tuple), ctx);
-    if (N > 1) {
-      out = std::copy(value.sep.begin(), value.sep.end(), out);
-      ctx.advance_to(out);
-      return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
-    }
-    return out;
-  }
-};
-
-FMT_MODULE_EXPORT_BEGIN
-
-/**
-  \rst
-  Returns an object that formats `tuple` with elements separated by `sep`.
-
-  **Example**::
-
-    std::tuple<int, char> t = {1, 'a'};
-    fmt::print("{}", fmt::join(t, ", "));
-    // Output: "1, a"
-  \endrst
- */
-template <typename... T>
-FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
-    -> tuple_join_view<char, T...> {
-  return {tuple, sep};
-}
-
-template <typename... T>
-FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,
-                        basic_string_view<wchar_t> sep)
-    -> tuple_join_view<wchar_t, T...> {
-  return {tuple, sep};
-}
-
-/**
-  \rst
-  Returns an object that formats `initializer_list` with elements separated by
-  `sep`.
-
-  **Example**::
-
-    fmt::print("{}", fmt::join({1, 2, 3}, ", "));
-    // Output: "1, 2, 3"
-  \endrst
- */
-template <typename T>
-auto join(std::initializer_list<T> list, string_view sep)
-    -> join_view<const T*, const T*> {
-  return join(std::begin(list), std::end(list), sep);
-}
-
-FMT_MODULE_EXPORT_END
-FMT_END_NAMESPACE
-
-#endif  // FMT_RANGES_H_
diff --git a/wpiutil/src/main/native/fmtlib/src/format.cpp b/wpiutil/src/main/native/fmtlib/src/format.cpp
deleted file mode 100644
index ecb8cc7..0000000
--- a/wpiutil/src/main/native/fmtlib/src/format.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-// Formatting library for C++
-//
-// Copyright (c) 2012 - 2016, Victor Zverovich
-// All rights reserved.
-//
-// For the license information refer to format.h.
-
-#include "fmt/format-inl.h"
-
-FMT_BEGIN_NAMESPACE
-namespace detail {
-
-// DEPRECATED!
-template <typename T = void> struct basic_data {
-  FMT_API static constexpr const char digits[100][2] = {
-      {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
-      {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
-      {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
-      {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
-      {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
-      {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
-      {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
-      {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
-      {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
-      {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
-      {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
-      {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
-      {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
-      {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
-      {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
-      {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
-      {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
-  FMT_API static constexpr const char hex_digits[] = "0123456789abcdef";
-  FMT_API static constexpr const char signs[4] = {0, '-', '+', ' '};
-  FMT_API static constexpr const char left_padding_shifts[5] = {31, 31, 0, 1,
-                                                                0};
-  FMT_API static constexpr const char right_padding_shifts[5] = {0, 31, 0, 1,
-                                                                 0};
-  FMT_API static constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
-                                                         0x1000000u | ' '};
-};
-
-#ifdef FMT_SHARED
-// Required for -flto, -fivisibility=hidden and -shared to work
-extern template struct basic_data<void>;
-#endif
-
-#if __cplusplus < 201703L
-// DEPRECATED! These are here only for ABI compatiblity.
-template <typename T> constexpr const char basic_data<T>::digits[][2];
-template <typename T> constexpr const char basic_data<T>::hex_digits[];
-template <typename T> constexpr const char basic_data<T>::signs[];
-template <typename T> constexpr const char basic_data<T>::left_padding_shifts[];
-template <typename T>
-constexpr const char basic_data<T>::right_padding_shifts[];
-template <typename T> constexpr const unsigned basic_data<T>::prefixes[];
-#endif
-
-template <typename T>
-int format_float(char* buf, std::size_t size, const char* format, int precision,
-                 T value) {
-#ifdef FMT_FUZZ
-  if (precision > 100000)
-    throw std::runtime_error(
-        "fuzz mode - avoid large allocation inside snprintf");
-#endif
-  // Suppress the warning about nonliteral format string.
-  int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
-  return precision < 0 ? snprintf_ptr(buf, size, format, value)
-                       : snprintf_ptr(buf, size, format, precision, value);
-}
-
-template FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(float x)
-    FMT_NOEXCEPT;
-template FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(double x)
-    FMT_NOEXCEPT;
-}  // namespace detail
-
-// Workaround a bug in MSVC2013 that prevents instantiation of format_float.
-int (*instantiate_format_float)(double, int, detail::float_specs,
-                                detail::buffer<char>&) = detail::format_float;
-
-#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
-template FMT_API detail::locale_ref::locale_ref(const std::locale& loc);
-template FMT_API std::locale detail::locale_ref::get<std::locale>() const;
-#endif
-
-// Explicit instantiations for char.
-
-template FMT_API auto detail::thousands_sep_impl(locale_ref)
-    -> thousands_sep_result<char>;
-template FMT_API char detail::decimal_point_impl(locale_ref);
-
-template FMT_API void detail::buffer<char>::append(const char*, const char*);
-
-// DEPRECATED!
-// There is no correspondent extern template in format.h because of
-// incompatibility between clang and gcc (#2377).
-template FMT_API void detail::vformat_to(
-    detail::buffer<char>&, string_view,
-    basic_format_args<FMT_BUFFER_CONTEXT(char)>, detail::locale_ref);
-
-template FMT_API int detail::snprintf_float(double, int, detail::float_specs,
-                                            detail::buffer<char>&);
-template FMT_API int detail::snprintf_float(long double, int,
-                                            detail::float_specs,
-                                            detail::buffer<char>&);
-template FMT_API int detail::format_float(double, int, detail::float_specs,
-                                          detail::buffer<char>&);
-template FMT_API int detail::format_float(long double, int, detail::float_specs,
-                                          detail::buffer<char>&);
-
-// Explicit instantiations for wchar_t.
-
-template FMT_API auto detail::thousands_sep_impl(locale_ref)
-    -> thousands_sep_result<wchar_t>;
-template FMT_API wchar_t detail::decimal_point_impl(locale_ref);
-
-template FMT_API void detail::buffer<wchar_t>::append(const wchar_t*,
-                                                      const wchar_t*);
-
-template struct detail::basic_data<void>;
-
-FMT_END_NAMESPACE
diff --git a/wpiutil/src/main/native/include/wpi/Algorithm.h b/wpiutil/src/main/native/include/wpi/Algorithm.h
index d0744dc..1fd2502 100644
--- a/wpiutil/src/main/native/include/wpi/Algorithm.h
+++ b/wpiutil/src/main/native/include/wpi/Algorithm.h
@@ -9,7 +9,7 @@
 
 namespace wpi {
 
-// Binary insortion into vector; std::log(n) efficiency.
+// Binary insertion into vector; std::log(n) efficiency.
 template <typename T>
 typename std::vector<T>::iterator insert_sorted(std::vector<T>& vec,
                                                 T const& item) {
diff --git a/wpiutil/src/main/native/include/wpi/AlignOf.h b/wpiutil/src/main/native/include/wpi/AlignOf.h
deleted file mode 100644
index adddd13..0000000
--- a/wpiutil/src/main/native/include/wpi/AlignOf.h
+++ /dev/null
@@ -1,146 +0,0 @@
-//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the AlignedCharArray and AlignedCharArrayUnion classes.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_ALIGNOF_H
-#define WPIUTIL_WPI_ALIGNOF_H
-
-#include "wpi/Compiler.h"
-#include <cstddef>
-
-namespace wpi {
-
-/// \struct AlignedCharArray
-/// Helper for building an aligned character array type.
-///
-/// This template is used to explicitly build up a collection of aligned
-/// character array types. We have to build these up using a macro and explicit
-/// specialization to cope with MSVC (at least till 2015) where only an
-/// integer literal can be used to specify an alignment constraint. Once built
-/// up here, we can then begin to indirect between these using normal C++
-/// template parameters.
-
-// MSVC requires special handling here.
-#ifndef _MSC_VER
-
-template<std::size_t Alignment, std::size_t Size>
-struct AlignedCharArray {
-  alignas(Alignment) char buffer[Size];
-};
-
-#else // _MSC_VER
-
-/// Create a type with an aligned char buffer.
-template<std::size_t Alignment, std::size_t Size>
-struct AlignedCharArray;
-
-// We provide special variations of this template for the most common
-// alignments because __declspec(align(...)) doesn't actually work when it is
-// a member of a by-value function argument in MSVC, even if the alignment
-// request is something reasonably like 8-byte or 16-byte. Note that we can't
-// even include the declspec with the union that forces the alignment because
-// MSVC warns on the existence of the declspec despite the union member forcing
-// proper alignment.
-
-template<std::size_t Size>
-struct AlignedCharArray<1, Size> {
-  union {
-    char aligned;
-    char buffer[Size];
-  };
-};
-
-template<std::size_t Size>
-struct AlignedCharArray<2, Size> {
-  union {
-    short aligned;
-    char buffer[Size];
-  };
-};
-
-template<std::size_t Size>
-struct AlignedCharArray<4, Size> {
-  union {
-    int aligned;
-    char buffer[Size];
-  };
-};
-
-template<std::size_t Size>
-struct AlignedCharArray<8, Size> {
-  union {
-    double aligned;
-    char buffer[Size];
-  };
-};
-
-
-// The rest of these are provided with a __declspec(align(...)) and we simply
-// can't pass them by-value as function arguments on MSVC.
-
-#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
-  template<std::size_t Size> \
-  struct AlignedCharArray<x, Size> { \
-    __declspec(align(x)) char buffer[Size]; \
-  };
-
-LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
-LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
-LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
-LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
-
-#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
-
-#endif // _MSC_VER
-
-namespace detail {
-template <typename T1,
-          typename T2 = char, typename T3 = char, typename T4 = char,
-          typename T5 = char, typename T6 = char, typename T7 = char,
-          typename T8 = char, typename T9 = char, typename T10 = char>
-class AlignerImpl {
-  T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
-
-  AlignerImpl() = delete;
-};
-
-template <typename T1,
-          typename T2 = char, typename T3 = char, typename T4 = char,
-          typename T5 = char, typename T6 = char, typename T7 = char,
-          typename T8 = char, typename T9 = char, typename T10 = char>
-union SizerImpl {
-  char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)],
-       arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)],
-       arr9[sizeof(T9)], arr10[sizeof(T10)];
-};
-} // end namespace detail
-
-/// This union template exposes a suitably aligned and sized character
-/// array member which can hold elements of any of up to ten types.
-///
-/// These types may be arrays, structs, or any other types. The goal is to
-/// expose a char array buffer member which can be used as suitable storage for
-/// a placement new of any of these types. Support for more than ten types can
-/// be added at the cost of more boilerplate.
-template <typename T1,
-          typename T2 = char, typename T3 = char, typename T4 = char,
-          typename T5 = char, typename T6 = char, typename T7 = char,
-          typename T8 = char, typename T9 = char, typename T10 = char>
-struct AlignedCharArrayUnion : wpi::AlignedCharArray<
-    alignof(wpi::detail::AlignerImpl<T1, T2, T3, T4, T5,
-                                      T6, T7, T8, T9, T10>),
-    sizeof(::wpi::detail::SizerImpl<T1, T2, T3, T4, T5,
-                                     T6, T7, T8, T9, T10>)> {
-};
-} // end namespace wpi
-
-#endif // LLVM_SUPPORT_ALIGNOF_H
diff --git a/wpiutil/src/main/native/include/wpi/Base64.h b/wpiutil/src/main/native/include/wpi/Base64.h
index 41b0062..c410bd0 100644
--- a/wpiutil/src/main/native/include/wpi/Base64.h
+++ b/wpiutil/src/main/native/include/wpi/Base64.h
@@ -6,12 +6,11 @@
 #define WPIUTIL_WPI_BASE64_H_
 
 #include <cstddef>
+#include <span>
 #include <string>
 #include <string_view>
 #include <vector>
 
-#include "wpi/span.h"
-
 namespace wpi {
 template <typename T>
 class SmallVectorImpl;
@@ -26,8 +25,8 @@
 
 size_t Base64Decode(std::string_view encoded, std::vector<uint8_t>* plain);
 
-span<uint8_t> Base64Decode(std::string_view encoded, size_t* num_read,
-                           SmallVectorImpl<uint8_t>& buf);
+std::span<uint8_t> Base64Decode(std::string_view encoded, size_t* num_read,
+                                SmallVectorImpl<uint8_t>& buf);
 
 void Base64Encode(raw_ostream& os, std::string_view plain);
 
@@ -36,11 +35,11 @@
 std::string_view Base64Encode(std::string_view plain,
                               SmallVectorImpl<char>& buf);
 
-void Base64Encode(raw_ostream& os, span<const uint8_t> plain);
+void Base64Encode(raw_ostream& os, std::span<const uint8_t> plain);
 
-void Base64Encode(span<const uint8_t> plain, std::string* encoded);
+void Base64Encode(std::span<const uint8_t> plain, std::string* encoded);
 
-std::string_view Base64Encode(span<const uint8_t> plain,
+std::string_view Base64Encode(std::span<const uint8_t> plain,
                               SmallVectorImpl<char>& buf);
 
 }  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/Compiler.h b/wpiutil/src/main/native/include/wpi/Compiler.h
deleted file mode 100644
index 5ceb605..0000000
--- a/wpiutil/src/main/native/include/wpi/Compiler.h
+++ /dev/null
@@ -1,516 +0,0 @@
-//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines several macros, based on the current compiler.  This allows
-// use of compiler-specific features in a way that remains portable.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_COMPILER_H
-#define WPIUTIL_WPI_COMPILER_H
-
-#include <new>
-#include <stddef.h>
-
-#if defined(_MSC_VER)
-#include <sal.h>
-#endif
-
-#ifndef __has_feature
-# define __has_feature(x) 0
-#endif
-
-#ifndef __has_extension
-# define __has_extension(x) 0
-#endif
-
-#ifndef __has_attribute
-# define __has_attribute(x) 0
-#endif
-
-#ifndef __has_cpp_attribute
-# define __has_cpp_attribute(x) 0
-#endif
-
-#ifndef __has_builtin
-# define __has_builtin(x) 0
-#endif
-
-/// \macro LLVM_GNUC_PREREQ
-/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't
-/// available.
-#ifndef LLVM_GNUC_PREREQ
-# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
-#  define LLVM_GNUC_PREREQ(maj, min, patch) \
-    ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
-     ((maj) << 20) + ((min) << 10) + (patch))
-# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
-#  define LLVM_GNUC_PREREQ(maj, min, patch) \
-    ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
-# else
-#  define LLVM_GNUC_PREREQ(maj, min, patch) 0
-# endif
-#endif
-
-/// \macro LLVM_MSC_PREREQ
-/// Is the compiler MSVC of at least the specified version?
-/// The common \param version values to check for are:
-///  * 1900: Microsoft Visual Studio 2015 / 14.0
-#ifndef LLVM_MSC_PREREQ
-#ifdef _MSC_VER
-#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
-
-// We require at least MSVC 2015.
-#if !LLVM_MSC_PREREQ(1900)
-#error wpiutil requires at least MSVC 2015.
-#endif
-
-#else
-#define LLVM_MSC_PREREQ(version) 0
-#endif
-#endif
-
-/// Does the compiler support ref-qualifiers for *this?
-///
-/// Sadly, this is separate from just rvalue reference support because GCC
-/// and MSVC implemented this later than everything else.
-#ifndef LLVM_HAS_RVALUE_REFERENCE_THIS
-#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1)
-#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
-#else
-#define LLVM_HAS_RVALUE_REFERENCE_THIS 0
-#endif
-#endif
-
-/// Expands to '&' if ref-qualifiers for *this are supported.
-///
-/// This can be used to provide lvalue/rvalue overrides of member functions.
-/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
-#ifndef LLVM_LVALUE_FUNCTION
-#if LLVM_HAS_RVALUE_REFERENCE_THIS
-#define LLVM_LVALUE_FUNCTION &
-#else
-#define LLVM_LVALUE_FUNCTION
-#endif
-#endif
-
-#ifndef LLVM_PREFETCH
-#if defined(__GNUC__)
-#define LLVM_PREFETCH(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
-#else
-#define LLVM_PREFETCH(addr, rw, locality)
-#endif
-#endif
-
-#ifndef LLVM_ATTRIBUTE_USED
-#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0)
-#define LLVM_ATTRIBUTE_USED __attribute__((__used__))
-#else
-#define LLVM_ATTRIBUTE_USED
-#endif
-#endif
-
-/// LLVM_NODISCARD - Warn if a type or return value is discarded.
-#ifndef LLVM_NODISCARD
-#if __cplusplus > 201402L && __has_cpp_attribute(nodiscard)
-#define LLVM_NODISCARD [[nodiscard]]
-// Detect MSVC directly, since __cplusplus still defaults to old version
-#elif _MSVC_LANG >= 201703L
-#define LLVM_NODISCARD [[nodiscard]]
-#elif _MSC_VER
-#define LLVM_NODISCARD
-#elif !__cplusplus
-// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
-// error when __has_cpp_attribute is given a scoped attribute in C mode.
-#define LLVM_NODISCARD
-#elif __has_cpp_attribute(clang::warn_unused_result)
-#define LLVM_NODISCARD [[clang::warn_unused_result]]
-#else
-#define LLVM_NODISCARD
-#endif
-#endif
-
-// Some compilers warn about unused functions. When a function is sometimes
-// used or not depending on build settings (e.g. a function only called from
-// within "assert"), this attribute can be used to suppress such warnings.
-//
-// However, it shouldn't be used for unused *variables*, as those have a much
-// more portable solution:
-//   (void)unused_var_name;
-// Prefer cast-to-void wherever it is sufficient.
-#ifndef LLVM_ATTRIBUTE_UNUSED
-#if __has_attribute(unused) || LLVM_GNUC_PREREQ(3, 1, 0)
-#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__))
-#else
-#define LLVM_ATTRIBUTE_UNUSED
-#endif
-#endif
-
-#ifndef LLVM_READNONE
-// Prior to clang 3.2, clang did not accept any spelling of
-// __has_attribute(const), so assume it is supported.
-#if defined(__clang__) || defined(__GNUC__)
-// aka 'CONST' but following LLVM Conventions.
-#define LLVM_READNONE __attribute__((__const__))
-#else
-#define LLVM_READNONE
-#endif
-#endif
-
-#ifndef LLVM_READONLY
-#if __has_attribute(pure) || defined(__GNUC__)
-// aka 'PURE' but following LLVM Conventions.
-#define LLVM_READONLY __attribute__((__pure__))
-#else
-#define LLVM_READONLY
-#endif
-#endif
-
-#ifndef LLVM_LIKELY
-#if __has_builtin(__builtin_expect) || LLVM_GNUC_PREREQ(4, 0, 0)
-#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
-#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
-#else
-#define LLVM_LIKELY(EXPR) (EXPR)
-#define LLVM_UNLIKELY(EXPR) (EXPR)
-#endif
-#endif
-
-/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
-/// mark a method "not for inlining".
-#ifndef LLVM_ATTRIBUTE_NOINLINE
-#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0)
-#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
-#elif defined(_MSC_VER)
-#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
-#else
-#define LLVM_ATTRIBUTE_NOINLINE
-#endif
-#endif
-
-/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do
-/// so, mark a method "always inline" because it is performance sensitive. GCC
-/// 3.4 supported this but is buggy in various cases and produces unimplemented
-/// errors, just use it in GCC 4.0 and later.
-#ifndef LLVM_ATTRIBUTE_ALWAYS_INLINE
-#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0)
-#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) inline
-#elif defined(_MSC_VER)
-#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline
-#else
-#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline
-#endif
-#endif
-
-#ifndef LLVM_ATTRIBUTE_NORETURN
-#ifdef __GNUC__
-#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn))
-#elif defined(_MSC_VER)
-#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn)
-#else
-#define LLVM_ATTRIBUTE_NORETURN
-#endif
-#endif
-
-#ifndef LLVM_ATTRIBUTE_RETURNS_NONNULL
-#if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0)
-#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
-#elif defined(_MSC_VER)
-#define LLVM_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_
-#else
-#define LLVM_ATTRIBUTE_RETURNS_NONNULL
-#endif
-#endif
-
-/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a
-/// pointer that does not alias any other valid pointer.
-#ifndef LLVM_ATTRIBUTE_RETURNS_NOALIAS
-#ifdef __GNUC__
-#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
-#elif defined(_MSC_VER)
-#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
-#else
-#define LLVM_ATTRIBUTE_RETURNS_NOALIAS
-#endif
-#endif
-
-/// LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
-#ifndef LLVM_FALLTHROUGH
-#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
-#define LLVM_FALLTHROUGH [[fallthrough]]
-// Detect MSVC directly, since __cplusplus still defaults to old version
-#elif _MSVC_LANG >= 201703L
-#define LLVM_FALLTHROUGH [[fallthrough]]
-#elif _MSC_VER
-#define LLVM_FALLTHROUGH
-#elif __has_cpp_attribute(gnu::fallthrough)
-#define LLVM_FALLTHROUGH [[gnu::fallthrough]]
-#elif !__cplusplus
-// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
-// error when __has_cpp_attribute is given a scoped attribute in C mode.
-#define LLVM_FALLTHROUGH
-#elif __has_cpp_attribute(clang::fallthrough)
-#define LLVM_FALLTHROUGH [[clang::fallthrough]]
-#else
-#define LLVM_FALLTHROUGH
-#endif
-#endif
-
-/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
-/// pedantic diagnostics.
-#ifndef LLVM_EXTENSION
-#ifdef __GNUC__
-#define LLVM_EXTENSION __extension__
-#else
-#define LLVM_EXTENSION
-#endif
-#endif
-
-// LLVM_ATTRIBUTE_DEPRECATED(decl, "message")
-#ifndef LLVM_ATTRIBUTE_DEPRECATED
-#if __has_feature(attribute_deprecated_with_message)
-# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
-  decl __attribute__((deprecated(message)))
-#elif defined(__GNUC__)
-# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
-  decl __attribute__((deprecated))
-#elif defined(_MSC_VER)
-# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
-  __declspec(deprecated(message)) decl
-#else
-# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
-  decl
-#endif
-#endif
-
-/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
-/// to an expression which states that it is undefined behavior for the
-/// compiler to reach this point.  Otherwise is not defined.
-#ifndef LLVM_BUILTIN_UNREACHABLE
-#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0)
-# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
-#elif defined(_MSC_VER)
-# define LLVM_BUILTIN_UNREACHABLE __assume(false)
-#endif
-#endif
-
-/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression
-/// which causes the program to exit abnormally.
-#ifndef LLVM_BUILTIN_TRAP
-#if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0)
-# define LLVM_BUILTIN_TRAP __builtin_trap()
-#elif defined(_MSC_VER)
-// The __debugbreak intrinsic is supported by MSVC, does not require forward
-// declarations involving platform-specific typedefs (unlike RaiseException),
-// results in a call to vectored exception handlers, and encodes to a short
-// instruction that still causes the trapping behavior we want.
-# define LLVM_BUILTIN_TRAP __debugbreak()
-#else
-# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
-#endif
-#endif
-
-/// LLVM_BUILTIN_DEBUGTRAP - On compilers which support it, expands to
-/// an expression which causes the program to break while running
-/// under a debugger.
-#ifndef LLVM_BUILTIN_DEBUGTRAP
-#if __has_builtin(__builtin_debugtrap)
-# define LLVM_BUILTIN_DEBUGTRAP __builtin_debugtrap()
-#elif defined(_MSC_VER)
-// The __debugbreak intrinsic is supported by MSVC and breaks while
-// running under the debugger, and also supports invoking a debugger
-// when the OS is configured appropriately.
-# define LLVM_BUILTIN_DEBUGTRAP __debugbreak()
-#else
-// Just continue execution when built with compilers that have no
-// support. This is a debugging aid and not intended to force the
-// program to abort if encountered.
-# define LLVM_BUILTIN_DEBUGTRAP
-#endif
-#endif
-
-/// \macro LLVM_ASSUME_ALIGNED
-/// Returns a pointer with an assumed alignment.
-#ifndef LLVM_ASSUME_ALIGNED
-#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0)
-# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
-#elif defined(LLVM_BUILTIN_UNREACHABLE)
-// As of today, clang does not support __builtin_assume_aligned.
-# define LLVM_ASSUME_ALIGNED(p, a) \
-           (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p)))
-#else
-# define LLVM_ASSUME_ALIGNED(p, a) (p)
-#endif
-#endif
-
-/// \macro LLVM_ALIGNAS
-/// Used to specify a minimum alignment for a structure or variable.
-#ifndef LLVM_ALIGNAS
-#if __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 1)
-# define LLVM_ALIGNAS(x) __attribute__((aligned(x)))
-#else
-# define LLVM_ALIGNAS(x) alignas(x)
-#endif
-#endif
-
-/// \macro LLVM_PACKED
-/// Used to specify a packed structure.
-/// LLVM_PACKED(
-///    struct A {
-///      int i;
-///      int j;
-///      int k;
-///      long long l;
-///   });
-///
-/// LLVM_PACKED_START
-/// struct B {
-///   int i;
-///   int j;
-///   int k;
-///   long long l;
-/// };
-/// LLVM_PACKED_END
-#ifndef LLVM_PACKED
-#ifdef _MSC_VER
-# define LLVM_PACKED(d) __pragma(pack(push, 1)) d __pragma(pack(pop))
-# define LLVM_PACKED_START __pragma(pack(push, 1))
-# define LLVM_PACKED_END   __pragma(pack(pop))
-#else
-# define LLVM_PACKED(d) d __attribute__((packed))
-# define LLVM_PACKED_START _Pragma("pack(push, 1)")
-# define LLVM_PACKED_END   _Pragma("pack(pop)")
-#endif
-#endif
-
-/// \macro LLVM_PTR_SIZE
-/// A constant integer equivalent to the value of sizeof(void*).
-/// Generally used in combination with LLVM_ALIGNAS or when doing computation in
-/// the preprocessor.
-#ifndef LLVM_PTR_SIZE
-#ifdef __SIZEOF_POINTER__
-# define LLVM_PTR_SIZE __SIZEOF_POINTER__
-#elif defined(_WIN64)
-# define LLVM_PTR_SIZE 8
-#elif defined(_WIN32)
-# define LLVM_PTR_SIZE 4
-#elif defined(_MSC_VER)
-# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC"
-#else
-# define LLVM_PTR_SIZE sizeof(void *)
-#endif
-#endif
-
-/// \macro LLVM_NO_SANITIZE
-/// Disable a particular sanitizer for a function.
-#ifndef LLVM_NO_SANITIZE
-#if __has_attribute(no_sanitize)
-#define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND)))
-#else
-#define LLVM_NO_SANITIZE(KIND)
-#endif
-#endif
-
-/// Mark debug helper function definitions like dump() that should not be
-/// stripped from debug builds.
-/// Note that you should also surround dump() functions with
-/// `#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)` so they do always
-/// get stripped in release builds.
-// FIXME: Move this to a private config.h as it's not usable in public headers.
-#ifndef LLVM_DUMP_METHOD
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
-#else
-#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
-#endif
-#endif
-
-/// \macro LLVM_PRETTY_FUNCTION
-/// Gets a user-friendly looking function signature for the current scope
-/// using the best available method on each platform.  The exact format of the
-/// resulting string is implementation specific and non-portable, so this should
-/// only be used, for example, for logging or diagnostics.
-#ifndef LLVM_PRETTY_FUNCTION
-#if defined(_MSC_VER)
-#define LLVM_PRETTY_FUNCTION __FUNCSIG__
-#elif defined(__GNUC__) || defined(__clang__)
-#define LLVM_PRETTY_FUNCTION __PRETTY_FUNCTION__
-#else
-#define LLVM_PRETTY_FUNCTION __func__
-#endif
-#endif
-
-/// \macro LLVM_THREAD_LOCAL
-/// A thread-local storage specifier which can be used with globals,
-/// extern globals, and static globals.
-///
-/// This is essentially an extremely restricted analog to C++11's thread_local
-/// support, and uses that when available. However, it falls back on
-/// platform-specific or vendor-provided extensions when necessary. These
-/// extensions don't support many of the C++11 thread_local's features. You
-/// should only use this for PODs that you can statically initialize to
-/// some constant value. In almost all circumstances this is most appropriate
-/// for use with a pointer, integer, or small aggregation of pointers and
-/// integers.
-#ifndef LLVM_THREAD_LOCAL
-#if __has_feature(cxx_thread_local)
-#define LLVM_THREAD_LOCAL thread_local
-#elif defined(_MSC_VER)
-// MSVC supports this with a __declspec.
-#define LLVM_THREAD_LOCAL __declspec(thread)
-#else
-// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
-// we only need the restricted functionality that provides.
-#define LLVM_THREAD_LOCAL __thread
-#endif
-#endif
-
-namespace wpi {
-
-/// Allocate a buffer of memory with the given size and alignment.
-///
-/// When the compiler supports aligned operator new, this will use it to to
-/// handle even over-aligned allocations.
-///
-/// However, this doesn't make any attempt to leverage the fancier techniques
-/// like posix_memalign due to portability. It is mostly intended to allow
-/// compatibility with platforms that, after aligned allocation was added, use
-/// reduced default alignment.
-inline void *allocate_buffer(size_t Size, size_t Alignment) {
-  return ::operator new(Size
-#ifdef __cpp_aligned_new
-                        ,
-                        std::align_val_t(Alignment)
-#endif
-  );
-}
-
-/// Deallocate a buffer of memory with the given size and alignment.
-///
-/// If supported, this will used the sized delete operator. Also if supported,
-/// this will pass the alignment to the delete operator.
-///
-/// The pointer must have been allocated with the corresponding new operator,
-/// most likely using the above helper.
-inline void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
-  ::operator delete(Ptr
-#ifdef __cpp_sized_deallocation
-                    ,
-                    Size
-#endif
-#ifdef __cpp_aligned_new
-                    ,
-                    std::align_val_t(Alignment)
-#endif
-  );
-}
-
-} // End namespace wpi
-
-#endif
diff --git a/wpiutil/src/main/native/include/wpi/DataLog.h b/wpiutil/src/main/native/include/wpi/DataLog.h
new file mode 100644
index 0000000..cac273c
--- /dev/null
+++ b/wpiutil/src/main/native/include/wpi/DataLog.h
@@ -0,0 +1,696 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <stdint.h>
+
+#include <functional>
+#include <initializer_list>
+#include <memory>
+#include <span>
+#include <string>
+#include <string_view>
+#include <thread>
+#include <vector>
+
+#include "wpi/DenseMap.h"
+#include "wpi/StringMap.h"
+#include "wpi/condition_variable.h"
+#include "wpi/mutex.h"
+
+namespace wpi {
+class Logger;
+}  // namespace wpi
+
+namespace wpi::log {
+
+namespace impl {
+
+enum ControlRecordType {
+  kControlStart = 0,
+  kControlFinish,
+  kControlSetMetadata
+};
+
+}  // namespace impl
+
+/**
+ * A data log. The log file is created immediately upon construction with a
+ * temporary filename.  The file may be renamed at any time using the
+ * SetFilename() function.
+ *
+ * The lifetime of the data log object must be longer than any data log entry
+ * objects that refer to it.
+ *
+ * The data log is periodically flushed to disk.  It can also be explicitly
+ * flushed to disk by using the Flush() function.
+ *
+ * Finish() is needed only to indicate in the log that a particular entry is
+ * no longer being used (it releases the name to ID mapping).  Finish() is not
+ * required to be called for data to be flushed to disk; entries in the log
+ * are written as Append() calls are being made.  In fact, Finish() does not
+ * need to be called at all; this is helpful to avoid shutdown races where the
+ * DataLog object might be destroyed before other objects.  It's often not a
+ * good idea to call Finish() from destructors for this reason.
+ *
+ * DataLog calls are thread safe.  DataLog uses a typical multiple-supplier,
+ * single-consumer setup.  Writes to the log are atomic, but there is no
+ * guaranteed order in the log when multiple threads are writing to it;
+ * whichever thread grabs the write mutex first will get written first.
+ * For this reason (as well as the fact that timestamps can be set to
+ * arbitrary values), records in the log are not guaranteed to be sorted by
+ * timestamp.
+ */
+class DataLog final {
+ public:
+  /**
+   * Construct a new Data Log.  The log will be initially created with a
+   * temporary filename.
+   *
+   * @param dir directory to store the log
+   * @param filename filename to use; if none provided, a random filename is
+   *                 generated of the form "wpilog_{}.wpilog"
+   * @param period time between automatic flushes to disk, in seconds;
+   *               this is a time/storage tradeoff
+   * @param extraHeader extra header data
+   */
+  explicit DataLog(std::string_view dir = "", std::string_view filename = "",
+                   double period = 0.25, std::string_view extraHeader = "");
+
+  /**
+   * Construct a new Data Log.  The log will be initially created with a
+   * temporary filename.
+   *
+   * @param msglog message logger (will be called from separate thread)
+   * @param dir directory to store the log
+   * @param filename filename to use; if none provided, a random filename is
+   *                 generated of the form "wpilog_{}.wpilog"
+   * @param period time between automatic flushes to disk, in seconds;
+   *               this is a time/storage tradeoff
+   * @param extraHeader extra header data
+   */
+  explicit DataLog(wpi::Logger& msglog, std::string_view dir = "",
+                   std::string_view filename = "", double period = 0.25,
+                   std::string_view extraHeader = "");
+
+  /**
+   * Construct a new Data Log that passes its output to the provided function
+   * rather than a file.  The write function will be called on a separate
+   * background thread and may block.  The write function is called with an
+   * empty data array when the thread is terminating.
+   *
+   * @param write write function
+   * @param period time between automatic calls to write, in seconds;
+   *               this is a time/storage tradeoff
+   * @param extraHeader extra header data
+   */
+  explicit DataLog(std::function<void(std::span<const uint8_t> data)> write,
+                   double period = 0.25, std::string_view extraHeader = "");
+
+  /**
+   * Construct a new Data Log that passes its output to the provided function
+   * rather than a file.  The write function will be called on a separate
+   * background thread and may block.  The write function is called with an
+   * empty data array when the thread is terminating.
+   *
+   * @param msglog message logger (will be called from separate thread)
+   * @param write write function
+   * @param period time between automatic calls to write, in seconds;
+   *               this is a time/storage tradeoff
+   * @param extraHeader extra header data
+   */
+  explicit DataLog(wpi::Logger& msglog,
+                   std::function<void(std::span<const uint8_t> data)> write,
+                   double period = 0.25, std::string_view extraHeader = "");
+
+  ~DataLog();
+  DataLog(const DataLog&) = delete;
+  DataLog& operator=(const DataLog&) = delete;
+  DataLog(DataLog&&) = delete;
+  DataLog& operator=(const DataLog&&) = delete;
+
+  /**
+   * Change log filename.
+   *
+   * @param filename filename
+   */
+  void SetFilename(std::string_view filename);
+
+  /**
+   * Explicitly flushes the log data to disk.
+   */
+  void Flush();
+
+  /**
+   * Pauses appending of data records to the log.  While paused, no data records
+   * are saved (e.g. AppendX is a no-op).  Has no effect on entry starts /
+   * finishes / metadata changes.
+   */
+  void Pause();
+
+  /**
+   * Resumes appending of data records to the log.
+   */
+  void Resume();
+
+  /**
+   * Start an entry.  Duplicate names are allowed (with the same type), and
+   * result in the same index being returned (Start/Finish are reference
+   * counted).  A duplicate name with a different type will result in an error
+   * message being printed to the console and 0 being returned (which will be
+   * ignored by the Append functions).
+   *
+   * @param name Name
+   * @param type Data type
+   * @param metadata Initial metadata (e.g. data properties)
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   *
+   * @return Entry index
+   */
+  int Start(std::string_view name, std::string_view type,
+            std::string_view metadata = {}, int64_t timestamp = 0);
+
+  /**
+   * Finish an entry.
+   *
+   * @param entry Entry index
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Finish(int entry, int64_t timestamp = 0);
+
+  /**
+   * Updates the metadata for an entry.
+   *
+   * @param entry Entry index
+   * @param metadata New metadata for the entry
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void SetMetadata(int entry, std::string_view metadata, int64_t timestamp = 0);
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param entry Entry index, as returned by Start()
+   * @param data Data to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void AppendRaw(int entry, std::span<const uint8_t> data, int64_t timestamp);
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param entry Entry index, as returned by Start()
+   * @param data Data to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void AppendRaw2(int entry, std::span<const std::span<const uint8_t>> data,
+                  int64_t timestamp);
+
+  void AppendBoolean(int entry, bool value, int64_t timestamp);
+  void AppendInteger(int entry, int64_t value, int64_t timestamp);
+  void AppendFloat(int entry, float value, int64_t timestamp);
+  void AppendDouble(int entry, double value, int64_t timestamp);
+  void AppendString(int entry, std::string_view value, int64_t timestamp);
+  void AppendBooleanArray(int entry, std::span<const bool> arr,
+                          int64_t timestamp);
+  void AppendBooleanArray(int entry, std::span<const int> arr,
+                          int64_t timestamp);
+  void AppendBooleanArray(int entry, std::span<const uint8_t> arr,
+                          int64_t timestamp);
+  void AppendIntegerArray(int entry, std::span<const int64_t> arr,
+                          int64_t timestamp);
+  void AppendFloatArray(int entry, std::span<const float> arr,
+                        int64_t timestamp);
+  void AppendDoubleArray(int entry, std::span<const double> arr,
+                         int64_t timestamp);
+  void AppendStringArray(int entry, std::span<const std::string> arr,
+                         int64_t timestamp);
+  void AppendStringArray(int entry, std::span<const std::string_view> arr,
+                         int64_t timestamp);
+
+ private:
+  void WriterThreadMain(std::string_view dir);
+  void WriterThreadMain(
+      std::function<void(std::span<const uint8_t> data)> write);
+
+  // must be called with m_mutex held
+  uint8_t* StartRecord(uint32_t entry, uint64_t timestamp, uint32_t payloadSize,
+                       size_t reserveSize);
+  uint8_t* Reserve(size_t size);
+  void AppendImpl(std::span<const uint8_t> data);
+  void AppendStringImpl(std::string_view str);
+
+  wpi::Logger& m_msglog;
+  mutable wpi::mutex m_mutex;
+  wpi::condition_variable m_cond;
+  bool m_active{true};
+  bool m_doFlush{false};
+  bool m_paused{false};
+  double m_period;
+  std::string m_extraHeader;
+  std::string m_newFilename;
+  class Buffer;
+  std::vector<Buffer> m_free;
+  std::vector<Buffer> m_outgoing;
+  struct EntryInfo {
+    std::string type;
+    int id{0};
+  };
+  wpi::StringMap<EntryInfo> m_entries;
+  wpi::DenseMap<int, unsigned int> m_entryCounts;
+  int m_lastId = 0;
+  std::thread m_thread;
+};
+
+/**
+ * Log entry base class.
+ */
+class DataLogEntry {
+ protected:
+  DataLogEntry() = default;
+  DataLogEntry(DataLog& log, std::string_view name, std::string_view type,
+               std::string_view metadata = {}, int64_t timestamp = 0)
+      : m_log{&log}, m_entry{log.Start(name, type, metadata, timestamp)} {}
+
+ public:
+  DataLogEntry(const DataLogEntry&) = delete;
+  DataLogEntry& operator=(const DataLogEntry&) = delete;
+
+  DataLogEntry(DataLogEntry&& rhs) : m_log{rhs.m_log}, m_entry{rhs.m_entry} {
+    rhs.m_log = nullptr;
+  }
+  DataLogEntry& operator=(DataLogEntry&& rhs) {
+    if (m_log) {
+      m_log->Finish(m_entry);
+    }
+    m_log = rhs.m_log;
+    rhs.m_log = nullptr;
+    m_entry = rhs.m_entry;
+    return *this;
+  }
+
+  explicit operator bool() const { return m_log != nullptr; }
+
+  /**
+   * Updates the metadata for the entry.
+   *
+   * @param metadata New metadata for the entry
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void SetMetadata(std::string_view metadata, int64_t timestamp = 0) {
+    m_log->SetMetadata(m_entry, metadata, timestamp);
+  }
+
+  /**
+   * Finishes the entry.
+   *
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Finish(int64_t timestamp = 0) { m_log->Finish(m_entry, timestamp); }
+
+ protected:
+  DataLog* m_log = nullptr;
+  int m_entry = 0;
+};
+
+/**
+ * Log arbitrary byte data.
+ */
+class RawLogEntry : public DataLogEntry {
+ public:
+  static constexpr std::string_view kDataType = "raw";
+
+  RawLogEntry() = default;
+  RawLogEntry(DataLog& log, std::string_view name, int64_t timestamp = 0)
+      : RawLogEntry{log, name, {}, kDataType, timestamp} {}
+  RawLogEntry(DataLog& log, std::string_view name, std::string_view metadata,
+              int64_t timestamp = 0)
+      : RawLogEntry{log, name, metadata, kDataType, timestamp} {}
+  RawLogEntry(DataLog& log, std::string_view name, std::string_view metadata,
+              std::string_view type, int64_t timestamp = 0)
+      : DataLogEntry{log, name, type, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param data Data to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const uint8_t> data, int64_t timestamp = 0) {
+    m_log->AppendRaw(m_entry, data, timestamp);
+  }
+};
+
+/**
+ * Log boolean values.
+ */
+class BooleanLogEntry : public DataLogEntry {
+ public:
+  static constexpr std::string_view kDataType = "boolean";
+
+  BooleanLogEntry() = default;
+  BooleanLogEntry(DataLog& log, std::string_view name, int64_t timestamp = 0)
+      : BooleanLogEntry{log, name, {}, timestamp} {}
+  BooleanLogEntry(DataLog& log, std::string_view name,
+                  std::string_view metadata, int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param value Value to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(bool value, int64_t timestamp = 0) {
+    m_log->AppendBoolean(m_entry, value, timestamp);
+  }
+};
+
+/**
+ * Log integer values.
+ */
+class IntegerLogEntry : public DataLogEntry {
+ public:
+  static constexpr std::string_view kDataType = "int64";
+
+  IntegerLogEntry() = default;
+  IntegerLogEntry(DataLog& log, std::string_view name, int64_t timestamp = 0)
+      : IntegerLogEntry{log, name, {}, timestamp} {}
+  IntegerLogEntry(DataLog& log, std::string_view name,
+                  std::string_view metadata, int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param value Value to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(int64_t value, int64_t timestamp = 0) {
+    m_log->AppendInteger(m_entry, value, timestamp);
+  }
+};
+
+/**
+ * Log float values.
+ */
+class FloatLogEntry : public DataLogEntry {
+ public:
+  static constexpr std::string_view kDataType = "float";
+
+  FloatLogEntry() = default;
+  FloatLogEntry(DataLog& log, std::string_view name, int64_t timestamp = 0)
+      : FloatLogEntry{log, name, {}, timestamp} {}
+  FloatLogEntry(DataLog& log, std::string_view name, std::string_view metadata,
+                int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param value Value to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(float value, int64_t timestamp = 0) {
+    m_log->AppendFloat(m_entry, value, timestamp);
+  }
+};
+
+/**
+ * Log double values.
+ */
+class DoubleLogEntry : public DataLogEntry {
+ public:
+  static constexpr std::string_view kDataType = "double";
+
+  DoubleLogEntry() = default;
+  DoubleLogEntry(DataLog& log, std::string_view name, int64_t timestamp = 0)
+      : DoubleLogEntry{log, name, {}, timestamp} {}
+  DoubleLogEntry(DataLog& log, std::string_view name, std::string_view metadata,
+                 int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param value Value to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(double value, int64_t timestamp = 0) {
+    m_log->AppendDouble(m_entry, value, timestamp);
+  }
+};
+
+/**
+ * Log string values.
+ */
+class StringLogEntry : public DataLogEntry {
+ public:
+  static constexpr const char* kDataType = "string";
+
+  StringLogEntry() = default;
+  StringLogEntry(DataLog& log, std::string_view name, int64_t timestamp = 0)
+      : StringLogEntry{log, name, {}, kDataType, timestamp} {}
+  StringLogEntry(DataLog& log, std::string_view name, std::string_view metadata,
+                 int64_t timestamp = 0)
+      : StringLogEntry{log, name, metadata, kDataType, timestamp} {}
+  StringLogEntry(DataLog& log, std::string_view name, std::string_view metadata,
+                 std::string_view type, int64_t timestamp = 0)
+      : DataLogEntry{log, name, type, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param value Value to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::string_view value, int64_t timestamp = 0) {
+    m_log->AppendString(m_entry, value, timestamp);
+  }
+};
+
+/**
+ * Log array of boolean values.
+ */
+class BooleanArrayLogEntry : public DataLogEntry {
+ public:
+  static constexpr const char* kDataType = "boolean[]";
+
+  BooleanArrayLogEntry() = default;
+  BooleanArrayLogEntry(DataLog& log, std::string_view name,
+                       int64_t timestamp = 0)
+      : BooleanArrayLogEntry{log, name, {}, timestamp} {}
+  BooleanArrayLogEntry(DataLog& log, std::string_view name,
+                       std::string_view metadata, int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.  For find functions to work, timestamp
+   * must be monotonically increasing.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const bool> arr, int64_t timestamp = 0) {
+    m_log->AppendBooleanArray(m_entry, arr, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::initializer_list<bool> arr, int64_t timestamp = 0) {
+    Append(std::span{arr.begin(), arr.end()}, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const int> arr, int64_t timestamp = 0) {
+    m_log->AppendBooleanArray(m_entry, arr, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::initializer_list<int> arr, int64_t timestamp = 0) {
+    Append(std::span{arr.begin(), arr.end()}, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const uint8_t> arr, int64_t timestamp = 0) {
+    m_log->AppendBooleanArray(m_entry, arr, timestamp);
+  }
+};
+
+/**
+ * Log array of integer values.
+ */
+class IntegerArrayLogEntry : public DataLogEntry {
+ public:
+  static constexpr const char* kDataType = "int64[]";
+
+  IntegerArrayLogEntry() = default;
+  IntegerArrayLogEntry(DataLog& log, std::string_view name,
+                       int64_t timestamp = 0)
+      : IntegerArrayLogEntry{log, name, {}, timestamp} {}
+  IntegerArrayLogEntry(DataLog& log, std::string_view name,
+                       std::string_view metadata, int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const int64_t> arr, int64_t timestamp = 0) {
+    m_log->AppendIntegerArray(m_entry, arr, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::initializer_list<int64_t> arr, int64_t timestamp = 0) {
+    Append({arr.begin(), arr.end()}, timestamp);
+  }
+};
+
+/**
+ * Log array of float values.
+ */
+class FloatArrayLogEntry : public DataLogEntry {
+ public:
+  static constexpr const char* kDataType = "float[]";
+
+  FloatArrayLogEntry() = default;
+  FloatArrayLogEntry(DataLog& log, std::string_view name, int64_t timestamp = 0)
+      : FloatArrayLogEntry{log, name, {}, timestamp} {}
+  FloatArrayLogEntry(DataLog& log, std::string_view name,
+                     std::string_view metadata, int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const float> arr, int64_t timestamp = 0) {
+    m_log->AppendFloatArray(m_entry, arr, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::initializer_list<float> arr, int64_t timestamp = 0) {
+    Append({arr.begin(), arr.end()}, timestamp);
+  }
+};
+
+/**
+ * Log array of double values.
+ */
+class DoubleArrayLogEntry : public DataLogEntry {
+ public:
+  static constexpr const char* kDataType = "double[]";
+
+  DoubleArrayLogEntry() = default;
+  DoubleArrayLogEntry(DataLog& log, std::string_view name,
+                      int64_t timestamp = 0)
+      : DoubleArrayLogEntry{log, name, {}, timestamp} {}
+  DoubleArrayLogEntry(DataLog& log, std::string_view name,
+                      std::string_view metadata, int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const double> arr, int64_t timestamp = 0) {
+    m_log->AppendDoubleArray(m_entry, arr, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::initializer_list<double> arr, int64_t timestamp = 0) {
+    Append({arr.begin(), arr.end()}, timestamp);
+  }
+};
+
+/**
+ * Log array of string values.
+ */
+class StringArrayLogEntry : public DataLogEntry {
+ public:
+  static constexpr const char* kDataType = "string[]";
+
+  StringArrayLogEntry() = default;
+  StringArrayLogEntry(DataLog& log, std::string_view name,
+                      int64_t timestamp = 0)
+      : StringArrayLogEntry{log, name, {}, timestamp} {}
+  StringArrayLogEntry(DataLog& log, std::string_view name,
+                      std::string_view metadata, int64_t timestamp = 0)
+      : DataLogEntry{log, name, kDataType, metadata, timestamp} {}
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const std::string> arr, int64_t timestamp = 0) {
+    m_log->AppendStringArray(m_entry, arr, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::span<const std::string_view> arr, int64_t timestamp = 0) {
+    m_log->AppendStringArray(m_entry, arr, timestamp);
+  }
+
+  /**
+   * Appends a record to the log.
+   *
+   * @param arr Values to record
+   * @param timestamp Time stamp (may be 0 to indicate now)
+   */
+  void Append(std::initializer_list<std::string_view> arr,
+              int64_t timestamp = 0) {
+    Append(std::span<const std::string_view>{arr.begin(), arr.end()},
+           timestamp);
+  }
+};
+
+}  // namespace wpi::log
diff --git a/wpiutil/src/main/native/include/wpi/DataLogReader.h b/wpiutil/src/main/native/include/wpi/DataLogReader.h
new file mode 100644
index 0000000..b1153e4
--- /dev/null
+++ b/wpiutil/src/main/native/include/wpi/DataLogReader.h
@@ -0,0 +1,369 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <stdint.h>
+
+#include <iterator>
+#include <memory>
+#include <span>
+#include <utility>
+#include <vector>
+
+#include "wpi/MemoryBuffer.h"
+
+namespace wpi::log {
+
+/**
+ * Data contained in a start control record as created by DataLog::Start() when
+ * writing the log. This can be read by calling DataLogRecord::GetStartData().
+ */
+struct StartRecordData {
+  /** Entry ID; this will be used for this entry in future records. */
+  int entry;
+
+  /** Entry name. */
+  std::string_view name;
+
+  /** Type of the stored data for this entry, as a string, e.g. "double". */
+  std::string_view type;
+
+  /** Initial metadata. */
+  std::string_view metadata;
+};
+
+/**
+ * Data contained in a set metadata control record as created by
+ * DataLog::SetMetadata(). This can be read by calling
+ * DataLogRecord::GetSetMetadataData().
+ */
+struct MetadataRecordData {
+  /** Entry ID. */
+  int entry;
+
+  /** New metadata for the entry. */
+  std::string_view metadata;
+};
+
+/**
+ * A record in the data log. May represent either a control record (entry == 0)
+ * or a data record. Used only for reading (e.g. with DataLogReader).
+ */
+class DataLogRecord {
+ public:
+  DataLogRecord() = default;
+  DataLogRecord(int entry, int64_t timestamp, std::span<const uint8_t> data)
+      : m_timestamp{timestamp}, m_data{data}, m_entry{entry} {}
+
+  /**
+   * Gets the entry ID.
+   *
+   * @return entry ID
+   */
+  int GetEntry() const { return m_entry; }
+
+  /**
+   * Gets the record timestamp.
+   *
+   * @return Timestamp, in integer microseconds
+   */
+  int64_t GetTimestamp() const { return m_timestamp; }
+
+  /**
+   * Gets the size of the raw data.
+   *
+   * @return size
+   */
+  size_t GetSize() const { return m_data.size(); }
+
+  /**
+   * Gets the raw data. Use the GetX functions to decode based on the data type
+   * in the entry's start record.
+   */
+  std::span<const uint8_t> GetRaw() const { return m_data; }
+
+  /**
+   * Returns true if the record is a control record.
+   *
+   * @return True if control record, false if normal data record.
+   */
+  bool IsControl() const { return m_entry == 0; }
+
+  /**
+   * Returns true if the record is a start control record. Use GetStartData()
+   * to decode the contents.
+   *
+   * @return True if start control record, false otherwise.
+   */
+  bool IsStart() const;
+
+  /**
+   * Returns true if the record is a finish control record. Use GetFinishEntry()
+   * to decode the contents.
+   *
+   * @return True if finish control record, false otherwise.
+   */
+  bool IsFinish() const;
+
+  /**
+   * Returns true if the record is a set metadata control record. Use
+   * GetSetMetadataData() to decode the contents.
+   *
+   * @return True if set metadata control record, false otherwise.
+   */
+  bool IsSetMetadata() const;
+
+  /**
+   * Decodes a start control record.
+   *
+   * @param[out] out start record decoded data (if successful)
+   * @return True on success, false on error
+   */
+  bool GetStartData(StartRecordData* out) const;
+
+  /**
+   * Decodes a finish control record.
+   *
+   * @param[out] out finish record entry ID (if successful)
+   * @return True on success, false on error
+   */
+  bool GetFinishEntry(int* out) const;
+
+  /**
+   * Decodes a set metadata control record.
+   *
+   * @param[out] out set metadata record decoded data (if successful)
+   * @return True on success, false on error
+   */
+  bool GetSetMetadataData(MetadataRecordData* out) const;
+
+  /**
+   * Decodes a data record as a boolean. Note if the data type (as indicated in
+   * the corresponding start control record for this entry) is not "boolean",
+   * invalid results may be returned.
+   *
+   * @param[out] value boolean value (if successful)
+   * @return True on success, false on error
+   */
+  bool GetBoolean(bool* value) const;
+
+  /**
+   * Decodes a data record as an integer. Note if the data type (as indicated in
+   * the corresponding start control record for this entry) is not "int64",
+   * invalid results may be returned.
+   *
+   * @param[out] value integer value (if successful)
+   * @return True on success, false on error
+   */
+  bool GetInteger(int64_t* value) const;
+
+  /**
+   * Decodes a data record as a float. Note if the data type (as indicated in
+   * the corresponding start control record for this entry) is not "float",
+   * invalid results may be returned.
+   *
+   * @param[out] value float value (if successful)
+   * @return True on success, false on error
+   */
+  bool GetFloat(float* value) const;
+
+  /**
+   * Decodes a data record as a double. Note if the data type (as indicated in
+   * the corresponding start control record for this entry) is not "double",
+   * invalid results may be returned.
+   *
+   * @param[out] value double value (if successful)
+   * @return True on success, false on error
+   */
+  bool GetDouble(double* value) const;
+
+  /**
+   * Decodes a data record as a string. Note if the data type (as indicated in
+   * the corresponding start control record for this entry) is not "string",
+   * invalid results may be returned.
+   *
+   * @param[out] value string value
+   * @return True (never fails)
+   */
+  bool GetString(std::string_view* value) const;
+
+  /**
+   * Decodes a data record as a boolean array. Note if the data type (as
+   * indicated in the corresponding start control record for this entry) is not
+   * "boolean[]", invalid results may be returned.
+   *
+   * @param[out] arr boolean array
+   * @return True (never fails)
+   */
+  bool GetBooleanArray(std::vector<int>* arr) const;
+
+  /**
+   * Decodes a data record as an integer array. Note if the data type (as
+   * indicated in the corresponding start control record for this entry) is not
+   * "int64[]", invalid results may be returned.
+   *
+   * @param[out] arr integer array (if successful)
+   * @return True on success, false on error
+   */
+  bool GetIntegerArray(std::vector<int64_t>* arr) const;
+
+  /**
+   * Decodes a data record as a float array. Note if the data type (as
+   * indicated in the corresponding start control record for this entry) is not
+   * "float[]", invalid results may be returned.
+   *
+   * @param[out] arr float array (if successful)
+   * @return True on success, false on error
+   */
+  bool GetFloatArray(std::vector<float>* arr) const;
+
+  /**
+   * Decodes a data record as a double array. Note if the data type (as
+   * indicated in the corresponding start control record for this entry) is not
+   * "double[]", invalid results may be returned.
+   *
+   * @param[out] arr double array (if successful)
+   * @return True on success, false on error
+   */
+  bool GetDoubleArray(std::vector<double>* arr) const;
+
+  /**
+   * Decodes a data record as a string array. Note if the data type (as
+   * indicated in the corresponding start control record for this entry) is not
+   * "string[]", invalid results may be returned.
+   *
+   * @param[out] arr string array (if successful)
+   * @return True on success, false on error
+   */
+  bool GetStringArray(std::vector<std::string_view>* arr) const;
+
+ private:
+  int64_t m_timestamp{0};
+  std::span<const uint8_t> m_data;
+  int m_entry{-1};
+};
+
+class DataLogReader;
+
+/** DataLogReader iterator. */
+class DataLogIterator {
+ public:
+  using iterator_category = std::forward_iterator_tag;
+  using value_type = DataLogRecord;
+  using pointer = const value_type*;
+  using reference = const value_type&;
+
+  DataLogIterator(const DataLogReader* reader, size_t pos)
+      : m_reader{reader}, m_pos{pos} {}
+
+  bool operator==(const DataLogIterator& oth) const {
+    return m_reader == oth.m_reader && m_pos == oth.m_pos;
+  }
+  bool operator!=(const DataLogIterator& oth) const {
+    return !this->operator==(oth);
+  }
+
+  bool operator<(const DataLogIterator& oth) const { return m_pos < oth.m_pos; }
+  bool operator>(const DataLogIterator& oth) const {
+    return !this->operator<(oth) && !this->operator==(oth);
+  }
+  bool operator<=(const DataLogIterator& oth) const {
+    return !this->operator>(oth);
+  }
+  bool operator>=(const DataLogIterator& oth) const {
+    return !this->operator<(oth);
+  }
+
+  DataLogIterator& operator++();
+
+  DataLogIterator operator++(int) {
+    DataLogIterator tmp = *this;
+    ++*this;
+    return tmp;
+  }
+
+  reference operator*() const;
+
+  pointer operator->() const { return &this->operator*(); }
+
+ private:
+  const DataLogReader* m_reader;
+  size_t m_pos;
+  mutable bool m_valid = false;
+  mutable DataLogRecord m_value;
+};
+
+/** Data log reader (reads logs written by the DataLog class). */
+class DataLogReader {
+  friend class DataLogIterator;
+
+ public:
+  using iterator = DataLogIterator;
+
+  /** Constructs from a memory buffer. */
+  explicit DataLogReader(std::unique_ptr<MemoryBuffer> buffer);
+
+  /** Returns true if the data log is valid (e.g. has a valid header). */
+  explicit operator bool() const { return IsValid(); }
+
+  /** Returns true if the data log is valid (e.g. has a valid header). */
+  bool IsValid() const;
+
+  /**
+   * Gets the data log version. Returns 0 if data log is invalid.
+   *
+   * @return Version number; most significant byte is major, least significant
+   *         is minor (so version 1.0 will be 0x0100)
+   */
+  uint16_t GetVersion() const;
+
+  /**
+   * Gets the extra header data.
+   *
+   * @return Extra header data
+   */
+  std::string_view GetExtraHeader() const;
+
+  /**
+   * Gets the buffer identifier, typically the filename.
+   *
+   * @return Identifier string
+   */
+  std::string_view GetBufferIdentifier() const {
+    return m_buf ? m_buf->GetBufferIdentifier() : "Invalid";
+  }
+
+  /** Returns iterator to first record. */
+  iterator begin() const;
+
+  /** Returns end iterator. */
+  iterator end() const { return DataLogIterator{this, SIZE_MAX}; }
+
+ private:
+  std::unique_ptr<MemoryBuffer> m_buf;
+
+  bool GetRecord(size_t* pos, DataLogRecord* out) const;
+  bool GetNextRecord(size_t* pos) const;
+};
+
+inline DataLogIterator& DataLogIterator::operator++() {
+  if (!m_reader->GetNextRecord(&m_pos)) {
+    m_pos = SIZE_MAX;
+  }
+  m_valid = false;
+  return *this;
+}
+
+inline DataLogIterator::reference DataLogIterator::operator*() const {
+  if (!m_valid) {
+    size_t pos = m_pos;
+    if (m_reader->GetRecord(&pos, &m_value)) {
+      m_valid = true;
+    }
+  }
+  return m_value;
+}
+
+}  // namespace wpi::log
diff --git a/wpiutil/src/main/native/include/wpi/DenseMapInfo.h b/wpiutil/src/main/native/include/wpi/DenseMapInfo.h
deleted file mode 100644
index b6525a3..0000000
--- a/wpiutil/src/main/native/include/wpi/DenseMapInfo.h
+++ /dev/null
@@ -1,274 +0,0 @@
-//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines DenseMapInfo traits for DenseMap.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_DENSEMAPINFO_H
-#define WPIUTIL_WPI_DENSEMAPINFO_H
-
-#include "wpi/Hashing.h"
-#include "wpi/PointerLikeTypeTraits.h"
-#include "wpi/span.h"
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <string_view>
-#include <utility>
-
-namespace wpi {
-
-template<typename T>
-struct DenseMapInfo {
-  //static inline T getEmptyKey();
-  //static inline T getTombstoneKey();
-  //static unsigned getHashValue(const T &Val);
-  //static bool isEqual(const T &LHS, const T &RHS);
-};
-
-// Provide DenseMapInfo for all pointers.
-template<typename T>
-struct DenseMapInfo<T*> {
-  static inline T* getEmptyKey() {
-    uintptr_t Val = static_cast<uintptr_t>(-1);
-    Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
-    return reinterpret_cast<T*>(Val);
-  }
-
-  static inline T* getTombstoneKey() {
-    uintptr_t Val = static_cast<uintptr_t>(-2);
-    Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
-    return reinterpret_cast<T*>(Val);
-  }
-
-  static unsigned getHashValue(const T *PtrVal) {
-    return (unsigned((uintptr_t)PtrVal) >> 4) ^
-           (unsigned((uintptr_t)PtrVal) >> 9);
-  }
-
-  static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
-};
-
-// Provide DenseMapInfo for chars.
-template<> struct DenseMapInfo<char> {
-  static inline char getEmptyKey() { return ~0; }
-  static inline char getTombstoneKey() { return ~0 - 1; }
-  static unsigned getHashValue(const char& Val) { return Val * 37U; }
-
-  static bool isEqual(const char &LHS, const char &RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for unsigned shorts.
-template <> struct DenseMapInfo<unsigned short> {
-  static inline unsigned short getEmptyKey() { return 0xFFFF; }
-  static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
-  static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
-
-  static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for unsigned ints.
-template<> struct DenseMapInfo<unsigned> {
-  static inline unsigned getEmptyKey() { return ~0U; }
-  static inline unsigned getTombstoneKey() { return ~0U - 1; }
-  static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
-
-  static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for unsigned longs.
-template<> struct DenseMapInfo<unsigned long> {
-  static inline unsigned long getEmptyKey() { return ~0UL; }
-  static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
-
-  static unsigned getHashValue(const unsigned long& Val) {
-    return (unsigned)(Val * 37UL);
-  }
-
-  static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for unsigned long longs.
-template<> struct DenseMapInfo<unsigned long long> {
-  static inline unsigned long long getEmptyKey() { return ~0ULL; }
-  static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
-
-  static unsigned getHashValue(const unsigned long long& Val) {
-    return (unsigned)(Val * 37ULL);
-  }
-
-  static bool isEqual(const unsigned long long& LHS,
-                      const unsigned long long& RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for shorts.
-template <> struct DenseMapInfo<short> {
-  static inline short getEmptyKey() { return 0x7FFF; }
-  static inline short getTombstoneKey() { return -0x7FFF - 1; }
-  static unsigned getHashValue(const short &Val) { return Val * 37U; }
-  static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
-};
-
-// Provide DenseMapInfo for ints.
-template<> struct DenseMapInfo<int> {
-  static inline int getEmptyKey() { return 0x7fffffff; }
-  static inline int getTombstoneKey() { return -0x7fffffff - 1; }
-  static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
-
-  static bool isEqual(const int& LHS, const int& RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for longs.
-template<> struct DenseMapInfo<long> {
-  static inline long getEmptyKey() {
-    return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
-  }
-
-  static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
-
-  static unsigned getHashValue(const long& Val) {
-    return (unsigned)(Val * 37UL);
-  }
-
-  static bool isEqual(const long& LHS, const long& RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for long longs.
-template<> struct DenseMapInfo<long long> {
-  static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
-  static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
-
-  static unsigned getHashValue(const long long& Val) {
-    return (unsigned)(Val * 37ULL);
-  }
-
-  static bool isEqual(const long long& LHS,
-                      const long long& RHS) {
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for all pairs whose members have info.
-template<typename T, typename U>
-struct DenseMapInfo<std::pair<T, U>> {
-  using Pair = std::pair<T, U>;
-  using FirstInfo = DenseMapInfo<T>;
-  using SecondInfo = DenseMapInfo<U>;
-
-  static inline Pair getEmptyKey() {
-    return std::make_pair(FirstInfo::getEmptyKey(),
-                          SecondInfo::getEmptyKey());
-  }
-
-  static inline Pair getTombstoneKey() {
-    return std::make_pair(FirstInfo::getTombstoneKey(),
-                          SecondInfo::getTombstoneKey());
-  }
-
-  static unsigned getHashValue(const Pair& PairVal) {
-    uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32
-          | (uint64_t)SecondInfo::getHashValue(PairVal.second);
-    key += ~(key << 32);
-    key ^= (key >> 22);
-    key += ~(key << 13);
-    key ^= (key >> 8);
-    key += (key << 3);
-    key ^= (key >> 15);
-    key += ~(key << 27);
-    key ^= (key >> 31);
-    return (unsigned)key;
-  }
-
-  static bool isEqual(const Pair &LHS, const Pair &RHS) {
-    return FirstInfo::isEqual(LHS.first, RHS.first) &&
-           SecondInfo::isEqual(LHS.second, RHS.second);
-  }
-};
-
-// Provide DenseMapInfo for std::string_view.
-template <> struct DenseMapInfo<std::string_view> {
-  static inline std::string_view getEmptyKey() {
-    return std::string_view(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
-                     0);
-  }
-
-  static inline std::string_view getTombstoneKey() {
-    return std::string_view(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
-                     0);
-  }
-
-  static unsigned getHashValue(std::string_view Val) {
-    assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
-    assert(Val.data() != getTombstoneKey().data() &&
-           "Cannot hash the tombstone key!");
-    return (unsigned)(hash_value(Val));
-  }
-
-  static bool isEqual(std::string_view LHS, std::string_view RHS) {
-    if (RHS.data() == getEmptyKey().data())
-      return LHS.data() == getEmptyKey().data();
-    if (RHS.data() == getTombstoneKey().data())
-      return LHS.data() == getTombstoneKey().data();
-    return LHS == RHS;
-  }
-};
-
-// Provide DenseMapInfo for spans.
-template <typename T> struct DenseMapInfo<span<T>> {
-  static inline span<T> getEmptyKey() {
-    return span<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
-                   size_t(0));
-  }
-
-  static inline span<T> getTombstoneKey() {
-    return span<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
-                   size_t(0));
-  }
-
-  static unsigned getHashValue(span<T> Val) {
-    assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
-    assert(Val.data() != getTombstoneKey().data() &&
-           "Cannot hash the tombstone key!");
-    return (unsigned)(hash_value(Val));
-  }
-
-  static bool isEqual(span<T> LHS, span<T> RHS) {
-    if (RHS.data() == getEmptyKey().data())
-      return LHS.data() == getEmptyKey().data();
-    if (RHS.data() == getTombstoneKey().data())
-      return LHS.data() == getTombstoneKey().data();
-    return LHS == RHS;
-  }
-};
-
-template <> struct DenseMapInfo<hash_code> {
-  static inline hash_code getEmptyKey() { return hash_code(-1); }
-  static inline hash_code getTombstoneKey() { return hash_code(-2); }
-  static unsigned getHashValue(hash_code val) { return static_cast<unsigned>(val); }
-  static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
-};
-
-} // end namespace wpi
-
-#endif // LLVM_ADT_DENSEMAPINFO_H
diff --git a/wpiutil/src/main/native/include/wpi/DsClient.h b/wpiutil/src/main/native/include/wpi/DsClient.h
deleted file mode 100644
index c24ba3b..0000000
--- a/wpiutil/src/main/native/include/wpi/DsClient.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <memory>
-#include <string>
-#include <string_view>
-
-#include "wpi/Signal.h"
-
-namespace wpi {
-
-class Logger;
-
-namespace uv {
-class Loop;
-class Tcp;
-class Timer;
-}  // namespace uv
-
-class DsClient : public std::enable_shared_from_this<DsClient> {
-  struct private_init {};
-
- public:
-  static std::shared_ptr<DsClient> Create(wpi::uv::Loop& loop,
-                                          wpi::Logger& logger) {
-    return std::make_shared<DsClient>(loop, logger, private_init{});
-  }
-
-  DsClient(wpi::uv::Loop& loop, wpi::Logger& logger, const private_init&);
-  ~DsClient();
-  DsClient(const DsClient&) = delete;
-  DsClient& operator=(const DsClient&) = delete;
-
-  void Close();
-
-  sig::Signal<std::string_view> setIp;
-  sig::Signal<> clearIp;
-
- private:
-  void Connect();
-  void HandleIncoming(std::string_view in);
-  void ParseJson();
-
-  wpi::Logger& m_logger;
-
-  std::shared_ptr<wpi::uv::Tcp> m_tcp;
-  std::shared_ptr<wpi::uv::Timer> m_timer;
-
-  std::string m_json;
-};
-
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/EventLoopRunner.h b/wpiutil/src/main/native/include/wpi/EventLoopRunner.h
deleted file mode 100644
index 5d35d40..0000000
--- a/wpiutil/src/main/native/include/wpi/EventLoopRunner.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_EVENTLOOPRUNNER_H_
-#define WPIUTIL_WPI_EVENTLOOPRUNNER_H_
-
-#include <functional>
-#include <memory>
-
-#include "wpi/SafeThread.h"
-#include "wpi/uv/Loop.h"
-
-namespace wpi {
-
-/**
- * Executes an event loop on a separate thread.
- */
-class EventLoopRunner {
- public:
-  using LoopFunc = std::function<void(uv::Loop&)>;
-
-  EventLoopRunner();
-  virtual ~EventLoopRunner();
-
-  /**
-   * Stop the loop.  Once the loop is stopped it cannot be restarted.
-   * This function does not return until the loop has exited.
-   */
-  void Stop();
-
-  /**
-   * Run a function asynchronously (once) on the loop.
-   * This is safe to call from any thread, but is NOT safe to call from the
-   * provided function (it will deadlock).
-   * @param func function to execute on the loop
-   */
-  void ExecAsync(LoopFunc func);
-
-  /**
-   * Run a function synchronously (once) on the loop.
-   * This is safe to call from any thread, but is NOT safe to call from the
-   * provided function (it will deadlock).
-   * This does not return until the function finishes executing.
-   * @param func function to execute on the loop
-   */
-  void ExecSync(LoopFunc func);
-
-  /**
-   * Get the loop.  If the loop thread is not running, returns nullptr.
-   * @return The loop
-   */
-  std::shared_ptr<uv::Loop> GetLoop();
-
- private:
-  class Thread;
-  SafeThreadOwner<Thread> m_owner;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_EVENTLOOPRUNNER_H_
diff --git a/wpiutil/src/main/native/include/wpi/EventVector.h b/wpiutil/src/main/native/include/wpi/EventVector.h
new file mode 100644
index 0000000..fc54df7
--- /dev/null
+++ b/wpiutil/src/main/native/include/wpi/EventVector.h
@@ -0,0 +1,51 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include "wpi/SmallVector.h"
+#include "wpi/Synchronization.h"
+#include "wpi/mutex.h"
+
+namespace wpi {
+struct EventVector {
+  wpi::mutex mutex;
+  wpi::SmallVector<WPI_EventHandle, 4> events;
+
+  /**
+   * Adds an event to the event vector.
+   *
+   * @param handle the event to add
+   */
+  void Add(WPI_EventHandle handle) {
+    std::scoped_lock lock{mutex};
+    events.emplace_back(handle);
+  }
+
+  /**
+   * Removes an event from the event vector.
+   *
+   * @param handle The event to remove
+   */
+  void Remove(WPI_EventHandle handle) {
+    std::scoped_lock lock{mutex};
+    auto it = std::find_if(
+        events.begin(), events.end(),
+        [=](const WPI_EventHandle fromHandle) { return fromHandle == handle; });
+    if (it != events.end()) {
+      events.erase(it);
+    }
+  }
+
+  /**
+   * Wakes up all events in the event vector.
+   */
+  void Wakeup() {
+    std::scoped_lock lock{mutex};
+    for (auto&& handle : events) {
+      wpi::SetEvent(handle);
+    }
+  }
+};
+}  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/FunctionExtras.h b/wpiutil/src/main/native/include/wpi/FunctionExtras.h
deleted file mode 100644
index 57bc8dc..0000000
--- a/wpiutil/src/main/native/include/wpi/FunctionExtras.h
+++ /dev/null
@@ -1,308 +0,0 @@
-//===- FunctionExtras.h - Function type erasure utilities -------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-/// \file
-/// This file provides a collection of function (or more generally, callable)
-/// type erasure utilities supplementing those provided by the standard library
-/// in `<function>`.
-///
-/// It provides `unique_function`, which works like `std::function` but supports
-/// move-only callable objects.
-///
-/// Future plans:
-/// - Add a `function` that provides const, volatile, and ref-qualified support,
-///   which doesn't work with `std::function`.
-/// - Provide support for specifying multiple signatures to type erase callable
-///   objects with an overload set, such as those produced by generic lambdas.
-/// - Expand to include a copyable utility that directly replaces std::function
-///   but brings the above improvements.
-///
-/// Note that LLVM's utilities are greatly simplified by not supporting
-/// allocators.
-///
-/// If the standard library ever begins to provide comparable facilities we can
-/// consider switching to those.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_FUNCTION_EXTRAS_H
-#define WPIUTIL_WPI_FUNCTION_EXTRAS_H
-
-#include "wpi/Compiler.h"
-#include "wpi/PointerIntPair.h"
-#include "wpi/PointerUnion.h"
-#include <memory>
-#include <type_traits>
-
-namespace wpi {
-
-template <typename FunctionT> class unique_function;
-
-// GCC warns on OutOfLineStorage
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
-
-template <typename ReturnT, typename... ParamTs>
-class unique_function<ReturnT(ParamTs...)> {
-  static constexpr size_t InlineStorageSize = sizeof(void *) * 4;
-
-  // MSVC has a bug and ICEs if we give it a particular dependent value
-  // expression as part of the `std::conditional` below. To work around this,
-  // we build that into a template struct's constexpr bool.
-  template <typename T> struct IsSizeLessThanThresholdT {
-    static constexpr bool value = sizeof(T) <= (2 * sizeof(void *));
-  };
-
-  // Provide a type function to map parameters that won't observe extra copies
-  // or moves and which are small enough to likely pass in register to values
-  // and all other types to l-value reference types. We use this to compute the
-  // types used in our erased call utility to minimize copies and moves unless
-  // doing so would force things unnecessarily into memory.
-  //
-  // The heuristic used is related to common ABI register passing conventions.
-  // It doesn't have to be exact though, and in one way it is more strict
-  // because we want to still be able to observe either moves *or* copies.
-  template <typename T>
-  using AdjustedParamT = typename std::conditional<
-      !std::is_reference<T>::value &&
-          std::is_trivially_copy_constructible<T>::value &&
-          std::is_trivially_move_constructible<T>::value &&
-          IsSizeLessThanThresholdT<T>::value,
-      T, T &>::type;
-
-  // The type of the erased function pointer we use as a callback to dispatch to
-  // the stored callable when it is trivial to move and destroy.
-  using CallPtrT = ReturnT (*)(void *CallableAddr,
-                               AdjustedParamT<ParamTs>... Params);
-  using MovePtrT = void (*)(void *LHSCallableAddr, void *RHSCallableAddr);
-  using DestroyPtrT = void (*)(void *CallableAddr);
-
-  /// A struct to hold a single trivial callback with sufficient alignment for
-  /// our bitpacking.
-  struct alignas(8) TrivialCallback {
-    CallPtrT CallPtr;
-  };
-
-  /// A struct we use to aggregate three callbacks when we need full set of
-  /// operations.
-  struct alignas(8) NonTrivialCallbacks {
-    CallPtrT CallPtr;
-    MovePtrT MovePtr;
-    DestroyPtrT DestroyPtr;
-  };
-
-  // Create a pointer union between either a pointer to a static trivial call
-  // pointer in a struct or a pointer to a static struct of the call, move, and
-  // destroy pointers.
-  using CallbackPointerUnionT =
-      PointerUnion<TrivialCallback *, NonTrivialCallbacks *>;
-
-  // The main storage buffer. This will either have a pointer to out-of-line
-  // storage or an inline buffer storing the callable.
-  union StorageUnionT {
-    // For out-of-line storage we keep a pointer to the underlying storage and
-    // the size. This is enough to deallocate the memory.
-    struct OutOfLineStorageT {
-      void *StoragePtr;
-      size_t Size;
-      size_t Alignment;
-    } OutOfLineStorage;
-    static_assert(
-        sizeof(OutOfLineStorageT) <= InlineStorageSize,
-        "Should always use all of the out-of-line storage for inline storage!");
-
-    // For in-line storage, we just provide an aligned character buffer. We
-    // provide four pointers worth of storage here.
-    typename std::aligned_storage<InlineStorageSize, alignof(void *)>::type
-        InlineStorage;
-  } StorageUnion;
-
-  // A compressed pointer to either our dispatching callback or our table of
-  // dispatching callbacks and the flag for whether the callable itself is
-  // stored inline or not.
-  PointerIntPair<CallbackPointerUnionT, 1, bool> CallbackAndInlineFlag;
-
-  bool isInlineStorage() const { return CallbackAndInlineFlag.getInt(); }
-
-  bool isTrivialCallback() const {
-    return CallbackAndInlineFlag.getPointer().template is<TrivialCallback *>();
-  }
-
-  CallPtrT getTrivialCallback() const {
-    return CallbackAndInlineFlag.getPointer().template get<TrivialCallback *>()->CallPtr;
-  }
-
-  NonTrivialCallbacks *getNonTrivialCallbacks() const {
-    return CallbackAndInlineFlag.getPointer()
-        .template get<NonTrivialCallbacks *>();
-  }
-
-  void *getInlineStorage() { return &StorageUnion.InlineStorage; }
-
-  void *getOutOfLineStorage() {
-    return StorageUnion.OutOfLineStorage.StoragePtr;
-  }
-  size_t getOutOfLineStorageSize() const {
-    return StorageUnion.OutOfLineStorage.Size;
-  }
-  size_t getOutOfLineStorageAlignment() const {
-    return StorageUnion.OutOfLineStorage.Alignment;
-  }
-
-  void setOutOfLineStorage(void *Ptr, size_t Size, size_t Alignment) {
-    StorageUnion.OutOfLineStorage = {Ptr, Size, Alignment};
-  }
-
-  template <typename CallableT>
-  static ReturnT CallImpl(void *CallableAddr, AdjustedParamT<ParamTs>... Params) {
-    return (*reinterpret_cast<CallableT *>(CallableAddr))(
-        std::forward<ParamTs>(Params)...);
-  }
-
-  template <typename CallableT>
-  static void MoveImpl(void *LHSCallableAddr, void *RHSCallableAddr) noexcept {
-    new (LHSCallableAddr)
-        CallableT(std::move(*reinterpret_cast<CallableT *>(RHSCallableAddr)));
-  }
-
-  template <typename CallableT>
-  static void DestroyImpl(void *CallableAddr) noexcept {
-    reinterpret_cast<CallableT *>(CallableAddr)->~CallableT();
-  }
-
-public:
-  unique_function() = default;
-  unique_function(std::nullptr_t /*null_callable*/) {}
-
-  ~unique_function() {
-    if (!CallbackAndInlineFlag.getPointer())
-      return;
-
-    // Cache this value so we don't re-check it after type-erased operations.
-    bool IsInlineStorage = isInlineStorage();
-
-    if (!isTrivialCallback())
-      getNonTrivialCallbacks()->DestroyPtr(
-          IsInlineStorage ? getInlineStorage() : getOutOfLineStorage());
-
-    if (!IsInlineStorage)
-      deallocate_buffer(getOutOfLineStorage(), getOutOfLineStorageSize(),
-                        getOutOfLineStorageAlignment());
-  }
-
-  unique_function(unique_function &&RHS) noexcept {
-    // Copy the callback and inline flag.
-    CallbackAndInlineFlag = RHS.CallbackAndInlineFlag;
-
-    // If the RHS is empty, just copying the above is sufficient.
-    if (!RHS)
-      return;
-
-    if (!isInlineStorage()) {
-      // The out-of-line case is easiest to move.
-      StorageUnion.OutOfLineStorage = RHS.StorageUnion.OutOfLineStorage;
-    } else if (isTrivialCallback()) {
-      // Move is trivial, just memcpy the bytes across.
-      memcpy(getInlineStorage(), RHS.getInlineStorage(), InlineStorageSize);
-    } else {
-      // Non-trivial move, so dispatch to a type-erased implementation.
-      getNonTrivialCallbacks()->MovePtr(getInlineStorage(),
-                                        RHS.getInlineStorage());
-    }
-
-    // Clear the old callback and inline flag to get back to as-if-null.
-    RHS.CallbackAndInlineFlag = {};
-
-#ifndef NDEBUG
-    // In debug builds, we also scribble across the rest of the storage.
-    memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize);
-#endif
-  }
-
-  unique_function &operator=(unique_function &&RHS) noexcept {
-    if (this == &RHS)
-      return *this;
-
-    // Because we don't try to provide any exception safety guarantees we can
-    // implement move assignment very simply by first destroying the current
-    // object and then move-constructing over top of it.
-    this->~unique_function();
-    new (this) unique_function(std::move(RHS));
-    return *this;
-  }
-
-  template <typename CallableT>
-  unique_function(CallableT Callable,
-                  std::enable_if_t<
-                    std::is_invocable_r_v<
-                      ReturnT, CallableT, ParamTs...>>* = nullptr) {
-    bool IsInlineStorage = true;
-    void *CallableAddr = getInlineStorage();
-    if (sizeof(CallableT) > InlineStorageSize ||
-        alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) {
-      IsInlineStorage = false;
-      // Allocate out-of-line storage. FIXME: Use an explicit alignment
-      // parameter in C++17 mode.
-      auto Size = sizeof(CallableT);
-      auto Alignment = alignof(CallableT);
-      CallableAddr = allocate_buffer(Size, Alignment);
-      setOutOfLineStorage(CallableAddr, Size, Alignment);
-    }
-
-    // Now move into the storage.
-    new (CallableAddr) CallableT(std::move(Callable));
-
-    // See if we can create a trivial callback. We need the callable to be
-    // trivially moved and trivially destroyed so that we don't have to store
-    // type erased callbacks for those operations.
-    //
-    // FIXME: We should use constexpr if here and below to avoid instantiating
-    // the non-trivial static objects when unnecessary. While the linker should
-    // remove them, it is still wasteful.
-    if (std::is_trivially_move_constructible<CallableT>::value &&
-        std::is_trivially_destructible<CallableT>::value) {
-      // We need to create a nicely aligned object. We use a static variable
-      // for this because it is a trivial struct.
-      static TrivialCallback Callback = { &CallImpl<CallableT> };
-
-      CallbackAndInlineFlag = {&Callback, IsInlineStorage};
-      return;
-    }
-
-    // Otherwise, we need to point at an object that contains all the different
-    // type erased behaviors needed. Create a static instance of the struct type
-    // here and then use a pointer to that.
-    static NonTrivialCallbacks Callbacks = {
-        &CallImpl<CallableT>, &MoveImpl<CallableT>, &DestroyImpl<CallableT>};
-
-    CallbackAndInlineFlag = {&Callbacks, IsInlineStorage};
-  }
-
-  ReturnT operator()(ParamTs... Params) {
-    void *CallableAddr =
-        isInlineStorage() ? getInlineStorage() : getOutOfLineStorage();
-
-    return (isTrivialCallback()
-                ? getTrivialCallback()
-                : getNonTrivialCallbacks()->CallPtr)(CallableAddr, Params...);
-  }
-
-  explicit operator bool() const {
-    return (bool)CallbackAndInlineFlag.getPointer();
-  }
-};
-
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-
-} // end namespace wpi
-
-#endif // WPIUTIL_WPI_FUNCTION_H
diff --git a/wpiutil/src/main/native/include/wpi/HttpParser.h b/wpiutil/src/main/native/include/wpi/HttpParser.h
deleted file mode 100644
index 72e5dad..0000000
--- a/wpiutil/src/main/native/include/wpi/HttpParser.h
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_HTTPPARSER_H_
-#define WPIUTIL_WPI_HTTPPARSER_H_
-
-#include <stdint.h>
-
-#include <string_view>
-
-#include "wpi/Signal.h"
-#include "wpi/SmallString.h"
-#include "wpi/http_parser.h"
-
-namespace wpi {
-
-/**
- * HTTP protocol parser.  Performs incremental parsing with callbacks for each
- * part of the HTTP protocol.  As this is incremental, it's suitable for use
- * with event based frameworks that provide arbitrary chunks of data.
- */
-class HttpParser {
- public:
-  enum Type {
-    kRequest = HTTP_REQUEST,
-    kResponse = HTTP_RESPONSE,
-    kBoth = HTTP_BOTH
-  };
-
-  /**
-   * Returns the library version. Bits 16-23 contain the major version number,
-   * bits 8-15 the minor version number and bits 0-7 the patch level.
-   */
-  static uint32_t GetParserVersion();
-
-  /**
-   * Constructor.
-   * @param type Type of parser (request or response or both)
-   */
-  explicit HttpParser(Type type);
-
-  /**
-   * Reset the parser to initial state.
-   * This allows reusing the same parser object from request to request.
-   * @param type Type of parser (request or response or both)
-   */
-  void Reset(Type type);
-
-  /**
-   * Set the maximum accepted length for URLs, field names, and field values.
-   * The default is 1024.
-   * @param len maximum length
-   */
-  void SetMaxLength(size_t len) { m_maxLength = len; }
-
-  /**
-   * Executes the parser.  An empty input is treated as EOF.
-   * @param in input data
-   * @return Trailing input data after the parse.
-   */
-  std::string_view Execute(std::string_view in) {
-    in.remove_prefix(
-        http_parser_execute(&m_parser, &m_settings, in.data(), in.size()));
-    return in;
-  }
-
-  /**
-   * Get HTTP major version.
-   */
-  unsigned int GetMajor() const { return m_parser.http_major; }
-
-  /**
-   * Get HTTP minor version.
-   */
-  unsigned int GetMinor() const { return m_parser.http_minor; }
-
-  /**
-   * Get HTTP status code.  Valid only on responses.  Valid in and after
-   * the OnStatus() callback has been called.
-   */
-  unsigned int GetStatusCode() const { return m_parser.status_code; }
-
-  /**
-   * Get HTTP method.  Valid only on requests.
-   */
-  http_method GetMethod() const {
-    return static_cast<http_method>(m_parser.method);
-  }
-
-  /**
-   * Determine if an error occurred.
-   * @return False if no error.
-   */
-  bool HasError() const { return m_parser.http_errno != HPE_OK; }
-
-  /**
-   * Get error number.
-   */
-  http_errno GetError() const {
-    return static_cast<http_errno>(m_parser.http_errno);
-  }
-
-  /**
-   * Abort the parse.  Call this from a callback handler to indicate an error.
-   * This will result in GetError() returning one of the callback-related
-   * errors (e.g. HPE_CB_message_begin).
-   */
-  void Abort() { m_aborted = true; }
-
-  /**
-   * Determine if an upgrade header was present and the parser has exited
-   * because of that.  Should be checked when Execute() returns in addition to
-   * checking GetError().
-   * @return True if upgrade header, false otherwise.
-   */
-  bool IsUpgrade() const { return m_parser.upgrade; }
-
-  /**
-   * If this returns false in the headersComplete or messageComplete
-   * callback, then this should be the last message on the connection.
-   * If you are the server, respond with the "Connection: close" header.
-   * If you are the client, close the connection.
-   */
-  bool ShouldKeepAlive() const { return http_should_keep_alive(&m_parser); }
-
-  /**
-   * Pause the parser.
-   * @param paused True to pause, false to unpause.
-   */
-  void Pause(bool paused) { http_parser_pause(&m_parser, paused); }
-
-  /**
-   * Checks if this is the final chunk of the body.
-   */
-  bool IsBodyFinal() const { return http_body_is_final(&m_parser); }
-
-  /**
-   * Get URL.  Valid in and after the url callback has been called.
-   */
-  std::string_view GetUrl() const { return m_urlBuf.str(); }
-
-  /**
-   * Message begin callback.
-   */
-  sig::Signal<> messageBegin;
-
-  /**
-   * URL callback.
-   *
-   * The parameter to the callback is the complete URL string.
-   */
-  sig::Signal<std::string_view> url;
-
-  /**
-   * Status callback.
-   *
-   * The parameter to the callback is the complete status string.
-   * GetStatusCode() can be used to get the numeric status code.
-   */
-  sig::Signal<std::string_view> status;
-
-  /**
-   * Header field callback.
-   *
-   * The parameters to the callback are the field name and field value.
-   */
-  sig::Signal<std::string_view, std::string_view> header;
-
-  /**
-   * Headers complete callback.
-   *
-   * The parameter to the callback is whether the connection should be kept
-   * alive.  If this is false, then this should be the last message on the
-   * connection.  If you are the server, respond with the "Connection: close"
-   * header.  If you are the client, close the connection.
-   */
-  sig::Signal<bool> headersComplete;
-
-  /**
-   * Body data callback.
-   *
-   * The parameters to the callback is the data chunk and whether this is the
-   * final chunk of data in the message.  Note this callback will be called
-   * multiple times arbitrarily (e.g. it's possible that it may be called with
-   * just a few characters at a time).
-   */
-  sig::Signal<std::string_view, bool> body;
-
-  /**
-   * Headers complete callback.
-   *
-   * The parameter to the callback is whether the connection should be kept
-   * alive.  If this is false, then this should be the last message on the
-   * connection.  If you are the server, respond with the "Connection: close"
-   * header.  If you are the client, close the connection.
-   */
-  sig::Signal<bool> messageComplete;
-
-  /**
-   * Chunk header callback.
-   *
-   * The parameter to the callback is the chunk size.
-   */
-  sig::Signal<uint64_t> chunkHeader;
-
-  /**
-   * Chunk complete callback.
-   */
-  sig::Signal<> chunkComplete;
-
- private:
-  http_parser m_parser;
-  http_parser_settings m_settings;
-
-  size_t m_maxLength = 1024;
-  enum { kStart, kUrl, kStatus, kField, kValue } m_state = kStart;
-  SmallString<128> m_urlBuf;
-  SmallString<32> m_fieldBuf;
-  SmallString<128> m_valueBuf;
-
-  bool m_aborted = false;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_HTTPPARSER_H_
diff --git a/wpiutil/src/main/native/include/wpi/HttpServerConnection.h b/wpiutil/src/main/native/include/wpi/HttpServerConnection.h
deleted file mode 100644
index a4d4cf8..0000000
--- a/wpiutil/src/main/native/include/wpi/HttpServerConnection.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_HTTPSERVERCONNECTION_H_
-#define WPIUTIL_WPI_HTTPSERVERCONNECTION_H_
-
-#include <memory>
-#include <string_view>
-
-#include "wpi/HttpParser.h"
-#include "wpi/span.h"
-#include "wpi/uv/Stream.h"
-
-namespace wpi {
-
-class raw_ostream;
-
-class HttpServerConnection {
- public:
-  explicit HttpServerConnection(std::shared_ptr<uv::Stream> stream);
-  virtual ~HttpServerConnection() = default;
-
- protected:
-  /**
-   * Process an incoming HTTP request.  This is called after the incoming
-   * message completes (e.g. from the HttpParser::messageComplete callback).
-   *
-   * The implementation should read request details from m_request and call the
-   * appropriate Send() functions to send a response back to the client.
-   */
-  virtual void ProcessRequest() = 0;
-
-  /**
-   * Build common response headers.
-   *
-   * Called by SendHeader() to send headers common to every response.
-   * Each line must be terminated with "\r\n".
-   *
-   * The default implementation sends the following:
-   * "Server: WebServer/1.0\r\n"
-   * "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, "
-   * "post-check=0, max-age=0\r\n"
-   * "Pragma: no-cache\r\n"
-   * "Expires: Mon, 3 Jan 2000 12:34:56 GMT\r\n"
-   *
-   * These parameters should ensure the browser does not cache the response.
-   * A browser should connect for each file and not serve files from its cache.
-   *
-   * @param os response stream
-   */
-  virtual void BuildCommonHeaders(raw_ostream& os);
-
-  /**
-   * Build HTTP response header, along with other header information like
-   * mimetype.  Calls BuildCommonHeaders().
-   *
-   * @param os response stream
-   * @param code HTTP response code (e.g. 200)
-   * @param codeText HTTP response code text (e.g. "OK")
-   * @param contentType MIME content type (e.g. "text/plain")
-   * @param contentLength Length of content.  If 0 is provided, m_keepAlive will
-   *                      be set to false.
-   * @param extra Extra HTTP headers to send, including final "\r\n"
-   */
-  virtual void BuildHeader(raw_ostream& os, int code, std::string_view codeText,
-                           std::string_view contentType, uint64_t contentLength,
-                           std::string_view extra = {});
-
-  /**
-   * Send data to client.
-   *
-   * This is a convenience wrapper around m_stream.Write() to provide
-   * auto-close functionality.
-   *
-   * @param bufs Buffers to write.  Deallocate() will be called on each
-   *             buffer after the write completes.  If different behavior
-   *             is desired, call m_stream.Write() directly instead.
-   * @param closeAfter close the connection after the write completes
-   */
-  void SendData(span<const uv::Buffer> bufs, bool closeAfter = false);
-
-  /**
-   * Send HTTP response, along with other header information like mimetype.
-   * Calls BuildHeader().
-   *
-   * @param code HTTP response code (e.g. 200)
-   * @param codeText HTTP response code text (e.g. "OK")
-   * @param contentType MIME content type (e.g. "text/plain")
-   * @param content Response message content
-   * @param extraHeader Extra HTTP headers to send, including final "\r\n"
-   */
-  virtual void SendResponse(int code, std::string_view codeText,
-                            std::string_view contentType,
-                            std::string_view content,
-                            std::string_view extraHeader = {});
-
-  /**
-   * Send HTTP response from static data, along with other header information
-   * like mimetype.  Calls BuildHeader().  Supports gzip pre-compressed data
-   * (it will decompress if the client does not accept gzip encoded data).
-   * Unlike SendResponse(), content is not copied and its contents must remain
-   * valid for an unspecified lifetime.
-   *
-   * @param code HTTP response code (e.g. 200)
-   * @param codeText HTTP response code text (e.g. "OK")
-   * @param contentType MIME content type (e.g. "text/plain")
-   * @param content Response message content
-   * @param gzipped True if content is gzip compressed
-   * @param extraHeader Extra HTTP headers to send, including final "\r\n"
-   */
-  virtual void SendStaticResponse(int code, std::string_view codeText,
-                                  std::string_view contentType,
-                                  std::string_view content, bool gzipped,
-                                  std::string_view extraHeader = {});
-
-  /**
-   * Send error header and message.
-   * This provides standard code responses for 400, 401, 403, 404, 500, and 503.
-   * Other codes will be reported as 501.  For arbitrary code handling, use
-   * SendResponse() instead.
-   *
-   * @param code HTTP error code (e.g. 404)
-   * @param message Additional message text
-   */
-  virtual void SendError(int code, std::string_view message = {});
-
-  /** The HTTP request. */
-  HttpParser m_request{HttpParser::kRequest};
-
-  /** Whether the connection should be kept alive. */
-  bool m_keepAlive = false;
-
-  /** If gzip is an acceptable encoding for responses. */
-  bool m_acceptGzip = false;
-
-  /** The underlying stream for the connection. */
-  uv::Stream& m_stream;
-
-  /** The header reader connection. */
-  sig::ScopedConnection m_dataConn;
-
-  /** The end stream connection. */
-  sig::ScopedConnection m_endConn;
-
-  /** The message complete connection. */
-  sig::Connection m_messageCompleteConn;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_HTTPSERVERCONNECTION_H_
diff --git a/wpiutil/src/main/native/include/wpi/HttpUtil.h b/wpiutil/src/main/native/include/wpi/HttpUtil.h
deleted file mode 100644
index b10d127..0000000
--- a/wpiutil/src/main/native/include/wpi/HttpUtil.h
+++ /dev/null
@@ -1,422 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_HTTPUTIL_H_
-#define WPIUTIL_WPI_HTTPUTIL_H_
-
-#include <initializer_list>
-#include <memory>
-#include <optional>
-#include <string>
-#include <string_view>
-#include <utility>
-#include <vector>
-
-#include "wpi/NetworkStream.h"
-#include "wpi/SmallString.h"
-#include "wpi/SmallVector.h"
-#include "wpi/StringMap.h"
-#include "wpi/raw_istream.h"
-#include "wpi/raw_socket_istream.h"
-#include "wpi/raw_socket_ostream.h"
-#include "wpi/span.h"
-
-namespace wpi {
-
-// Unescape a %xx-encoded URI.
-// @param buf Buffer for output
-// @param error Set to true if an error occurred
-// @return Escaped string
-std::string_view UnescapeURI(std::string_view str, SmallVectorImpl<char>& buf,
-                             bool* error);
-
-// Escape a string with %xx-encoding.
-// @param buf Buffer for output
-// @param spacePlus If true, encodes spaces to '+' rather than "%20"
-// @return Escaped string
-std::string_view EscapeURI(std::string_view str, SmallVectorImpl<char>& buf,
-                           bool spacePlus = true);
-
-// Parse a set of HTTP headers.  Saves just the Content-Type and Content-Length
-// fields.
-// @param is Input stream
-// @param contentType If not null, Content-Type contents are saved here.
-// @param contentLength If not null, Content-Length contents are saved here.
-// @return False if error occurred in input stream
-bool ParseHttpHeaders(raw_istream& is, SmallVectorImpl<char>* contentType,
-                      SmallVectorImpl<char>* contentLength);
-
-// Look for a MIME multi-part boundary.  On return, the input stream will
-// be located at the character following the boundary (usually "\r\n").
-// @param is Input stream
-// @param boundary Boundary string to scan for (not including "--" prefix)
-// @param saveBuf If not null, all scanned characters up to but not including
-//     the boundary are saved to this string
-// @return False if error occurred on input stream, true if boundary found.
-bool FindMultipartBoundary(wpi::raw_istream& is, std::string_view boundary,
-                           std::string* saveBuf);
-
-/**
- * Map for looking up elements of the query portion of a URI.  Does not
- * handle multiple elements with the same name.  This is a reference type;
- * it does not make a copy of the query string, so it is important that the
- * query string has a lifetime at least as long as this object.
- */
-class HttpQueryMap {
- public:
-  /**
-   * Constructs an empty map (with no entries).
-   */
-  HttpQueryMap() = default;
-
-  /**
-   * Constructs from an escaped query string.  Note: does not make a copy of
-   * the query string, so it must not be a temporary.
-   *
-   * @param query query string
-   */
-  explicit HttpQueryMap(std::string_view query);
-
-  /**
-   * Gets an element of the query string.  Both the name and the returned
-   * value are unescaped strings.
-   *
-   * @param name name (unescaped)
-   * @param buf result buffer for value
-   * @return Optional unescaped value.  Returns an empty optional if the
-   *         name is not present in the query map.
-   */
-  std::optional<std::string_view> Get(std::string_view name,
-                                      SmallVectorImpl<char>& buf) const;
-
- private:
-  StringMap<std::string_view> m_elems;
-};
-
-class HttpPathRef;
-
-/**
- * Class for HTTP path matching.  A root path is represented as a single
- * empty element, otherwise the path consists of each non-empty element
- * between the '/' characters:
- *  - "" -> []
- *  - "/" -> [""]
- *  - "/foo" -> ["foo"]
- *  - "/foo/bar" -> ["foo", "bar"]
- *  - "/foo//bar/" -> ["foo", "bar"]
- *
- * All path elements are unescaped.
- */
-class HttpPath {
- public:
-  /**
-   * Constructs an empty HTTP path.
-   */
-  HttpPath() = default;
-
-  /**
-   * Constructs a HTTP path from an escaped path string.  Makes a copy of the
-   * path, so it's safe to be a temporary.
-   */
-  explicit HttpPath(std::string_view path);
-
-  /**
-   * Evaluates to true if the path is not empty.
-   */
-  explicit operator bool() const { return !empty(); }
-
-  /**
-   * Returns true if the path has no elements.
-   */
-  bool empty() const { return m_pathEnds.empty(); }
-
-  /**
-   * Returns number of elements in the path.
-   */
-  size_t size() const { return m_pathEnds.size(); }
-
-  /**
-   * Returns true if the path exactly matches the provided match list.
-   *
-   * @param match match list
-   * @return True if path equals match list
-   */
-  bool equals(std::initializer_list<std::string_view> match) const {
-    return equals(0, {match.begin(), match.end()});
-  }
-  bool equals(span<const std::string_view> match) const {
-    return equals(0, match);
-  }
-  bool equals(std::string_view match) const { return equals(0, {match}); }
-
-  /**
-   * Returns true if the elements of the path starting at the "start" element
-   * match the provided match list, and there are no additional elements.
-   *
-   * @param start element to start matching at
-   * @param match match list
-   * @return True if match
-   */
-  bool equals(size_t start,
-              std::initializer_list<std::string_view> match) const {
-    return equals(start, {match.begin(), match.end()});
-  }
-  bool equals(size_t start, span<const std::string_view> match) const {
-    if (m_pathEnds.size() != (start + match.size())) {
-      return false;
-    }
-    return startswith(start, match);
-  }
-  bool equals(size_t start, std::string_view match) const {
-    return equals(start, {match});
-  }
-
-  /**
-   * Returns true if the first elements of the path match the provided match
-   * list.  The path may have additional elements.
-   *
-   * @param match match list
-   * @return True if path starts with match list
-   */
-  bool startswith(std::initializer_list<std::string_view> match) const {
-    return startswith(0, {match.begin(), match.end()});
-  }
-  bool startswith(span<const std::string_view> match) const {
-    return startswith(0, match);
-  }
-  bool startswith(std::string_view match) const {
-    return startswith(0, {match});
-  }
-
-  /**
-   * Returns true if the elements of the path starting at the "start" element
-   * match the provided match list.  The path may have additional elements.
-   *
-   * @param start element to start matching at
-   * @param match match list
-   * @return True if path starting at the start element matches the match list
-   */
-  bool startswith(size_t start,
-                  std::initializer_list<std::string_view> match) const {
-    return startswith(start, {match.begin(), match.end()});
-  }
-
-  bool startswith(size_t start, span<const std::string_view> match) const;
-
-  bool startswith(size_t start, std::string_view match) const {
-    return startswith(start, {match});
-  }
-
-  /**
-   * Gets a single element of the path.
-   */
-  std::string_view operator[](size_t n) const;
-
-  /**
-   * Returns a path reference with the first N elements of the path removed.
-   */
-  HttpPathRef drop_front(size_t n) const;
-
- private:
-  SmallString<128> m_pathBuf;
-  SmallVector<size_t, 16> m_pathEnds;
-};
-
-/**
- * Proxy reference object for a portion of a HttpPath.
- */
-class HttpPathRef {
- public:
-  HttpPathRef() = default;
-  /*implicit*/ HttpPathRef(const HttpPath& path,  // NOLINT
-                           size_t start = 0)
-      : m_path(&path), m_start(start) {}
-
-  explicit operator bool() const { return !empty(); }
-  bool empty() const { return m_path && m_path->size() == m_start; }
-  size_t size() const { return m_path ? m_path->size() - m_start : 0; }
-
-  bool equals(std::initializer_list<std::string_view> match) const {
-    return equals(0, {match.begin(), match.end()});
-  }
-  bool equals(span<const std::string_view> match) const {
-    return equals(0, match);
-  }
-  bool equals(std::string_view match) const { return equals(0, {match}); }
-
-  bool equals(size_t start,
-              std::initializer_list<std::string_view> match) const {
-    return equals(start, {match.begin(), match.end()});
-  }
-  bool equals(size_t start, span<const std::string_view> match) const {
-    return m_path ? m_path->equals(m_start + start, match) : false;
-  }
-  bool equals(size_t start, std::string_view match) const {
-    return equals(start, {match});
-  }
-
-  bool startswith(std::initializer_list<std::string_view> match) const {
-    return startswith(0, {match.begin(), match.end()});
-  }
-  bool startswith(span<const std::string_view> match) const {
-    return startswith(0, match);
-  }
-  bool startswith(std::string_view match) const {
-    return startswith(0, {match});
-  }
-
-  bool startswith(size_t start,
-                  std::initializer_list<std::string_view> match) const {
-    return startswith(start, {match.begin(), match.end()});
-  }
-  bool startswith(size_t start, span<const std::string_view> match) const {
-    return m_path ? m_path->startswith(m_start + start, match) : false;
-  }
-  bool startswith(size_t start, std::string_view match) const {
-    return startswith(start, {match});
-  }
-
-  std::string_view operator[](size_t n) const {
-    return m_path ? m_path->operator[](m_start + n) : std::string_view{};
-  }
-  HttpPathRef drop_front(size_t n) const {
-    return m_path ? m_path->drop_front(m_start + n) : HttpPathRef{};
-  }
-
- private:
-  const HttpPath* m_path = nullptr;
-  size_t m_start = 0;
-};
-
-class HttpLocation {
- public:
-  HttpLocation() = default;
-  HttpLocation(std::string_view url_, bool* error, std::string* errorMsg);
-
-  std::string url;       // retain copy
-  std::string user;      // unescaped
-  std::string password;  // unescaped
-  std::string host;
-  int port;
-  std::string path;  // escaped, not including leading '/'
-  std::vector<std::pair<std::string, std::string>> params;  // unescaped
-  std::string fragment;
-};
-
-class HttpRequest {
- public:
-  HttpRequest() = default;
-
-  explicit HttpRequest(const HttpLocation& loc)
-      : host{loc.host}, port{loc.port} {
-    SetPath(loc.path, loc.params);
-    SetAuth(loc);
-  }
-
-  template <typename T>
-  HttpRequest(const HttpLocation& loc, const T& extraParams);
-
-  HttpRequest(const HttpLocation& loc, std::string_view path_)
-      : host{loc.host}, port{loc.port}, path{path_} {
-    SetAuth(loc);
-  }
-
-  template <typename T>
-  HttpRequest(const HttpLocation& loc, std::string_view path_, const T& params)
-      : host{loc.host}, port{loc.port} {
-    SetPath(path_, params);
-    SetAuth(loc);
-  }
-
-  SmallString<128> host;
-  int port;
-  std::string auth;
-  SmallString<128> path;
-
- private:
-  void SetAuth(const HttpLocation& loc);
-  template <typename T>
-  void SetPath(std::string_view path_, const T& params);
-
-  template <typename T>
-  static std::string_view GetFirst(const T& elem) {
-    return elem.first;
-  }
-  template <typename T>
-  static std::string_view GetFirst(const StringMapEntry<T>& elem) {
-    return elem.getKey();
-  }
-  template <typename T>
-  static std::string_view GetSecond(const T& elem) {
-    return elem.second;
-  }
-};
-
-class HttpConnection {
- public:
-  HttpConnection(std::unique_ptr<wpi::NetworkStream> stream_, int timeout)
-      : stream{std::move(stream_)}, is{*stream, timeout}, os{*stream, true} {}
-
-  bool Handshake(const HttpRequest& request, std::string* warnMsg);
-
-  std::unique_ptr<wpi::NetworkStream> stream;
-  wpi::raw_socket_istream is;
-  wpi::raw_socket_ostream os;
-
-  // Valid after Handshake() is successful
-  SmallString<64> contentType;
-  SmallString<64> contentLength;
-
-  explicit operator bool() const { return stream && !is.has_error(); }
-};
-
-class HttpMultipartScanner {
- public:
-  explicit HttpMultipartScanner(std::string_view boundary,
-                                bool saveSkipped = false) {
-    Reset(saveSkipped);
-    SetBoundary(boundary);
-  }
-
-  // Change the boundary.  This is only safe to do when IsDone() is true (or
-  // immediately after construction).
-  void SetBoundary(std::string_view boundary);
-
-  // Reset the scanner.  This allows reuse of internal buffers.
-  void Reset(bool saveSkipped = false);
-
-  // Execute the scanner.  Will automatically call Reset() on entry if IsDone()
-  // is true.
-  // @param in input data
-  // @return the input not consumed; empty if all input consumed
-  std::string_view Execute(std::string_view in);
-
-  // Returns true when the boundary has been found.
-  bool IsDone() const { return m_state == kDone; }
-
-  // Get the skipped data.  Will be empty if saveSkipped was false.
-  std::string_view GetSkipped() const {
-    return m_saveSkipped ? std::string_view{m_buf} : std::string_view{};
-  }
-
- private:
-  SmallString<64> m_boundaryWith, m_boundaryWithout;
-
-  // Internal state
-  enum State { kBoundary, kPadding, kDone };
-  State m_state;
-  size_t m_posWith, m_posWithout;
-  enum Dashes { kUnknown, kWith, kWithout };
-  Dashes m_dashes;
-
-  // Buffer
-  bool m_saveSkipped;
-  std::string m_buf;
-};
-
-}  // namespace wpi
-
-#include "HttpUtil.inc"
-
-#endif  // WPIUTIL_WPI_HTTPUTIL_H_
diff --git a/wpiutil/src/main/native/include/wpi/HttpUtil.inc b/wpiutil/src/main/native/include/wpi/HttpUtil.inc
deleted file mode 100644
index 726cdfb..0000000
--- a/wpiutil/src/main/native/include/wpi/HttpUtil.inc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_HTTPUTIL_INC_
-#define WPIUTIL_WPI_HTTPUTIL_INC_
-
-#include <utility>
-
-#include "wpi/HttpUtil.h"
-
-namespace wpi {
-
-inline HttpPathRef HttpPath::drop_front(size_t n) const {
-  return HttpPathRef(*this, n);
-}
-
-template <typename T>
-HttpRequest::HttpRequest(const HttpLocation& loc, const T& extraParams)
-    : host{loc.host}, port{loc.port} {
-  StringMap<std::string_view> params;
-  for (const auto& p : loc.params) {
-    params.insert(std::make_pair(GetFirst(p), GetSecond(p)));
-  }
-  for (const auto& p : extraParams) {
-    params.insert(std::make_pair(GetFirst(p), GetSecond(p)));
-  }
-  SetPath(loc.path, params);
-  SetAuth(loc);
-}
-
-template <typename T>
-void HttpRequest::SetPath(std::string_view path_, const T& params) {
-  // Build location including query string
-  raw_svector_ostream pathOs{path};
-  pathOs << path_;
-  bool first = true;
-  for (const auto& param : params) {
-    if (first) {
-      pathOs << '?';
-      first = false;
-    } else {
-      pathOs << '&';
-    }
-    SmallString<64> escapeBuf;
-    pathOs << EscapeURI(GetFirst(param), escapeBuf, false);
-    if (!GetSecond(param).empty()) {
-      pathOs << '=' << EscapeURI(GetSecond(param), escapeBuf, false);
-    }
-  }
-}
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_HTTPUTIL_INC_
diff --git a/wpiutil/src/main/native/include/wpi/HttpWebSocketServerConnection.h b/wpiutil/src/main/native/include/wpi/HttpWebSocketServerConnection.h
deleted file mode 100644
index d89b61f..0000000
--- a/wpiutil/src/main/native/include/wpi/HttpWebSocketServerConnection.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_HTTPWEBSOCKETSERVERCONNECTION_H_
-#define WPIUTIL_WPI_HTTPWEBSOCKETSERVERCONNECTION_H_
-
-#include <initializer_list>
-#include <memory>
-#include <string>
-#include <string_view>
-
-#include "wpi/HttpServerConnection.h"
-#include "wpi/SmallVector.h"
-#include "wpi/WebSocket.h"
-#include "wpi/WebSocketServer.h"
-#include "wpi/span.h"
-#include "wpi/uv/Stream.h"
-
-namespace wpi {
-
-/**
- * A server-side HTTP connection that also accepts WebSocket upgrades.
- *
- * @tparam Derived derived class for std::enable_shared_from_this.
- */
-template <typename Derived>
-class HttpWebSocketServerConnection
-    : public HttpServerConnection,
-      public std::enable_shared_from_this<Derived> {
- public:
-  /**
-   * Constructor.
-   *
-   * @param stream network stream
-   * @param protocols Acceptable subprotocols
-   */
-  HttpWebSocketServerConnection(std::shared_ptr<uv::Stream> stream,
-                                span<const std::string_view> protocols);
-
-  /**
-   * Constructor.
-   *
-   * @param stream network stream
-   * @param protocols Acceptable subprotocols
-   */
-  HttpWebSocketServerConnection(
-      std::shared_ptr<uv::Stream> stream,
-      std::initializer_list<std::string_view> protocols)
-      : HttpWebSocketServerConnection(stream,
-                                      {protocols.begin(), protocols.end()}) {}
-
- protected:
-  /**
-   * Check that an incoming WebSocket upgrade is okay.  This is called prior
-   * to accepting the upgrade (so prior to ProcessWsUpgrade()).
-   *
-   * The implementation should check other headers and return true if the
-   * WebSocket connection should be accepted.
-   *
-   * @param protocol negotiated subprotocol
-   */
-  virtual bool IsValidWsUpgrade(std::string_view protocol) { return true; }
-
-  /**
-   * Process an incoming WebSocket upgrade.  This is called after the header
-   * reader has been disconnected and the websocket has been accepted.
-   *
-   * The implementation should set up appropriate callbacks on the websocket
-   * object to continue communication.
-   *
-   * @note When a WebSocket upgrade occurs, the stream user data is replaced
-   *       with the websocket, and the websocket user data points to "this".
-   *       Replace the websocket user data with caution!
-   */
-  virtual void ProcessWsUpgrade() = 0;
-
-  /**
-   * WebSocket connection; not valid until ProcessWsUpgrade is called.
-   */
-  WebSocket* m_websocket = nullptr;
-
- private:
-  WebSocketServerHelper m_helper;
-  SmallVector<std::string, 2> m_protocols;
-};
-
-}  // namespace wpi
-
-#include "HttpWebSocketServerConnection.inc"
-
-#endif  // WPIUTIL_WPI_HTTPWEBSOCKETSERVERCONNECTION_H_
diff --git a/wpiutil/src/main/native/include/wpi/HttpWebSocketServerConnection.inc b/wpiutil/src/main/native/include/wpi/HttpWebSocketServerConnection.inc
deleted file mode 100644
index 68b9f2d..0000000
--- a/wpiutil/src/main/native/include/wpi/HttpWebSocketServerConnection.inc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_HTTPWEBSOCKETSERVERCONNECTION_INC_
-#define WPIUTIL_WPI_HTTPWEBSOCKETSERVERCONNECTION_INC_
-
-#include <memory>
-
-#include "wpi/HttpWebSocketServerConnection.h"
-
-namespace wpi {
-
-template <typename Derived>
-HttpWebSocketServerConnection<Derived>::HttpWebSocketServerConnection(
-    std::shared_ptr<uv::Stream> stream, span<const std::string_view> protocols)
-    : HttpServerConnection{stream},
-      m_helper{m_request},
-      m_protocols{protocols.begin(), protocols.end()} {
-  // Handle upgrade event
-  m_helper.upgrade.connect([this] {
-    // Negotiate sub-protocol
-    SmallVector<std::string_view, 2> protocols{m_protocols.begin(),
-                                               m_protocols.end()};
-    std::string_view protocol = m_helper.MatchProtocol(protocols).second;
-
-    // Check that the upgrade is valid
-    if (!IsValidWsUpgrade(protocol)) {
-      return;
-    }
-
-    // Disconnect HttpServerConnection header reader
-    m_dataConn.disconnect();
-    m_messageCompleteConn.disconnect();
-
-    // Accepting the stream may destroy this (as it replaces the stream user
-    // data), so grab a shared pointer first.
-    auto self = this->shared_from_this();
-
-    // Accept the upgrade
-    auto ws = m_helper.Accept(m_stream, protocol);
-
-    // Set this as the websocket user data to keep it around
-    ws->SetData(self);
-
-    // Store in member
-    m_websocket = ws.get();
-
-    // Call derived class function
-    ProcessWsUpgrade();
-  });
-}
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_HTTPWEBSOCKETSERVERCONNECTION_INC_
diff --git a/wpiutil/src/main/native/include/wpi/Logger.h b/wpiutil/src/main/native/include/wpi/Logger.h
index 807e472..883336f 100644
--- a/wpiutil/src/main/native/include/wpi/Logger.h
+++ b/wpiutil/src/main/native/include/wpi/Logger.h
@@ -45,12 +45,11 @@
   void LogV(unsigned int level, const char* file, unsigned int line,
             fmt::string_view format, fmt::format_args args);
 
-  template <typename S, typename... Args>
+  template <typename... Args>
   void Log(unsigned int level, const char* file, unsigned int line,
-           const S& format, Args&&... args) {
+           fmt::string_view format, Args&&... args) {
     if (m_func && level >= m_min_level) {
-      LogV(level, file, line, format,
-           fmt::make_args_checked<Args...>(format, args...));
+      LogV(level, file, line, format, fmt::make_format_args(args...));
     }
   }
 
@@ -61,15 +60,25 @@
   unsigned int m_min_level = 20;
 };
 
-#define WPI_LOG(logger_inst, level, format, ...) \
-  logger_inst.Log(level, __FILE__, __LINE__, FMT_STRING(format), __VA_ARGS__)
+// C++20 relaxed the number of arguments to variadics, but Apple Clang's
+// warnings haven't caught up yet: https://stackoverflow.com/a/67996331
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
+#endif
+
+#define WPI_LOG(logger_inst, level, format, ...)                         \
+  if ((logger_inst).HasLogger() && level >= (logger_inst).min_level()) { \
+    (logger_inst)                                                        \
+        .Log(level, __FILE__, __LINE__,                                  \
+             FMT_STRING(format) __VA_OPT__(, ) __VA_ARGS__);             \
+  }
 
 #define WPI_ERROR(inst, format, ...) \
-  WPI_LOG(inst, ::wpi::WPI_LOG_ERROR, format, __VA_ARGS__)
+  WPI_LOG(inst, ::wpi::WPI_LOG_ERROR, format __VA_OPT__(, ) __VA_ARGS__)
 #define WPI_WARNING(inst, format, ...) \
-  WPI_LOG(inst, ::wpi::WPI_LOG_WARNING, format, __VA_ARGS__)
+  WPI_LOG(inst, ::wpi::WPI_LOG_WARNING, format __VA_OPT__(, ) __VA_ARGS__)
 #define WPI_INFO(inst, format, ...) \
-  WPI_LOG(inst, ::wpi::WPI_LOG_INFO, format, __VA_ARGS__)
+  WPI_LOG(inst, ::wpi::WPI_LOG_INFO, format __VA_OPT__(, ) __VA_ARGS__)
 
 #ifdef NDEBUG
 #define WPI_DEBUG(inst, format, ...) \
@@ -89,15 +98,15 @@
   } while (0)
 #else
 #define WPI_DEBUG(inst, format, ...) \
-  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG, format, __VA_ARGS__)
+  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG, format __VA_OPT__(, ) __VA_ARGS__)
 #define WPI_DEBUG1(inst, format, ...) \
-  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG1, format, __VA_ARGS__)
+  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG1, format __VA_OPT__(, ) __VA_ARGS__)
 #define WPI_DEBUG2(inst, format, ...) \
-  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG2, format, __VA_ARGS__)
+  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG2, format __VA_OPT__(, ) __VA_ARGS__)
 #define WPI_DEBUG3(inst, format, ...) \
-  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG3, format, __VA_ARGS__)
+  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG3, format __VA_OPT__(, ) __VA_ARGS__)
 #define WPI_DEBUG4(inst, format, ...) \
-  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG4, format, __VA_ARGS__)
+  WPI_LOG(inst, ::wpi::WPI_LOG_DEBUG4, format __VA_OPT__(, ) __VA_ARGS__)
 #endif
 
 }  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/ManagedStatic.h b/wpiutil/src/main/native/include/wpi/ManagedStatic.h
deleted file mode 100644
index 28c11fa..0000000
--- a/wpiutil/src/main/native/include/wpi/ManagedStatic.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the ManagedStatic class and the wpi_shutdown() function.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_MANAGEDSTATIC_H
-#define WPIUTIL_WPI_MANAGEDSTATIC_H
-
-#include <atomic>
-#include <cstddef>
-
-namespace wpi {
-
-/// object_creator - Helper method for ManagedStatic.
-template <class C> struct object_creator {
-  static void *call() { return new C(); }
-};
-
-/// object_deleter - Helper method for ManagedStatic.
-///
-template <typename T> struct object_deleter {
-  static void call(void *Ptr) { delete (T *)Ptr; }
-};
-template <typename T, size_t N> struct object_deleter<T[N]> {
-  static void call(void *Ptr) { delete[](T *)Ptr; }
-};
-
-/// ManagedStaticBase - Common base class for ManagedStatic instances.
-class ManagedStaticBase {
-protected:
-  // This should only be used as a static variable, which guarantees that this
-  // will be zero initialized.
-  mutable std::atomic<void *> Ptr;
-  mutable void (*DeleterFn)(void*);
-  mutable const ManagedStaticBase *Next;
-
-  void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
-  void RegisterManagedStatic(void *created, void (*deleter)(void*)) const;
-
-public:
-  /// isConstructed - Return true if this object has not been created yet.
-  bool isConstructed() const { return Ptr != nullptr; }
-
-  void destroy() const;
-};
-
-/// ManagedStatic - This transparently changes the behavior of global statics to
-/// be lazily constructed on demand (good for reducing startup times of dynamic
-/// libraries that link in LLVM components) and for making destruction be
-/// explicit through the wpi_shutdown() function call.
-///
-template <class C, class Creator = object_creator<C>,
-          class Deleter = object_deleter<C>>
-class ManagedStatic : public ManagedStaticBase {
-public:
-  ManagedStatic() = default;
-
-  ManagedStatic(C* created, void(*deleter)(void*)) {
-    RegisterManagedStatic(created, deleter);
-  }
-
-  // Accessors.
-  C &operator*() {
-    void *Tmp = Ptr.load(std::memory_order_acquire);
-    if (!Tmp)
-      RegisterManagedStatic(Creator::call, Deleter::call);
-
-    return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
-  }
-
-  C *operator->() { return &**this; }
-
-  const C &operator*() const {
-    void *Tmp = Ptr.load(std::memory_order_acquire);
-    if (!Tmp)
-      RegisterManagedStatic(Creator::call, Deleter::call);
-
-    return *static_cast<C *>(Ptr.load(std::memory_order_relaxed));
-  }
-
-  const C *operator->() const { return &**this; }
-};
-
-/// wpi_shutdown - Deallocate and destroy all ManagedStatic variables.
-void wpi_shutdown();
-
-/// wpi_shutdown_obj - This is a simple helper class that calls
-/// wpi_shutdown() when it is destroyed.
-struct wpi_shutdown_obj {
-  wpi_shutdown_obj() = default;
-  ~wpi_shutdown_obj() { wpi_shutdown(); }
-};
-
-} // end namespace wpi
-
-#endif // WPIUTIL_WPI_MANAGEDSTATIC_H
diff --git a/wpiutil/src/main/native/include/wpi/MappedFileRegion.h b/wpiutil/src/main/native/include/wpi/MappedFileRegion.h
new file mode 100644
index 0000000..05e487e
--- /dev/null
+++ b/wpiutil/src/main/native/include/wpi/MappedFileRegion.h
@@ -0,0 +1,92 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <stdint.h>
+
+#include <system_error>
+
+// Duplicated from fs.h to avoid a dependency
+namespace fs {
+#if defined(_WIN32)
+// A Win32 HANDLE is a typedef of void*
+using file_t = void*;
+#else
+using file_t = int;
+#endif
+}  // namespace fs
+
+namespace wpi {
+
+class MappedFileRegion {
+ public:
+  enum MapMode {
+    kReadOnly,   ///< May only access map via const_data as read only.
+    kReadWrite,  ///< May access map via data and modify it. Written to path.
+    kPriv        ///< May modify via data, but changes are lost on destruction.
+  };
+
+  MappedFileRegion() = default;
+  MappedFileRegion(fs::file_t f, uint64_t length, uint64_t offset,
+                   MapMode mapMode, std::error_code& ec);
+  ~MappedFileRegion() { Unmap(); }
+
+  MappedFileRegion(const MappedFileRegion&) = delete;
+  MappedFileRegion& operator=(const MappedFileRegion&) = delete;
+
+  MappedFileRegion(MappedFileRegion&& rhs)
+      : m_size(rhs.m_size), m_mapping(rhs.m_mapping) {
+    rhs.m_mapping = nullptr;
+#ifdef _WIN32
+    m_fileHandle = rhs.m_fileHandle;
+    rhs.m_fileHandle = nullptr;
+#endif
+  }
+
+  MappedFileRegion& operator=(MappedFileRegion&& rhs) {
+    if (m_mapping) {
+      Unmap();
+    }
+    m_size = rhs.m_size;
+    m_mapping = rhs.m_mapping;
+    rhs.m_mapping = nullptr;
+#ifdef _WIN32
+    m_fileHandle = rhs.m_fileHandle;
+    rhs.m_fileHandle = nullptr;
+#endif
+    return *this;
+  }
+
+  explicit operator bool() const {
+    return m_mapping != nullptr;
+  }
+
+  void Flush();
+  void Unmap();
+
+  uint64_t size() const {
+    return m_size;
+  }
+  uint8_t* data() const {
+    return static_cast<uint8_t*>(m_mapping);
+  }
+  const uint8_t* const_data() const {
+    return static_cast<const uint8_t*>(m_mapping);
+  }
+
+  /**
+   * Returns required alignment.
+   */
+  static size_t GetAlignment();
+
+ private:
+  uint64_t m_size = 0;
+  void* m_mapping = nullptr;
+#ifdef _WIN32
+  fs::file_t m_fileHandle = nullptr;
+#endif
+};
+
+}  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/MemAlloc.h b/wpiutil/src/main/native/include/wpi/MemAlloc.h
deleted file mode 100644
index addccb5..0000000
--- a/wpiutil/src/main/native/include/wpi/MemAlloc.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- MemAlloc.h - Memory allocation functions -----------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-/// \file
-///
-/// This file defines counterparts of C library allocation functions defined in
-/// the namespace 'std'. The new allocation functions crash on allocation
-/// failure instead of returning null pointer.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_MEMALLOC_H
-#define WPIUTIL_WPI_MEMALLOC_H
-
-#include "wpi/Compiler.h"
-#include "wpi/ErrorHandling.h"
-#include <cstdlib>
-
-namespace wpi {
-
-#ifdef _WIN32
-#pragma warning(push)
-// Warning on NONNULL, report is not known to abort
-#pragma warning(disable : 6387)
-#pragma warning(disable : 28196)
-#pragma warning(disable : 28183)
-#endif
-
-LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_malloc(size_t Sz) {
-  void *Result = std::malloc(Sz);
-  if (Result == nullptr)
-    report_bad_alloc_error("Allocation failed");
-  return Result;
-}
-
-LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_calloc(size_t Count,
-                                                        size_t Sz) {
-  void *Result = std::calloc(Count, Sz);
-  if (Result == nullptr)
-    report_bad_alloc_error("Allocation failed");
-  return Result;
-}
-
-LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
-  void *Result = std::realloc(Ptr, Sz);
-  if (Result == nullptr)
-    report_bad_alloc_error("Allocation failed");
-  return Result;
-}
-
-#ifdef _WIN32
-#pragma warning(pop)
-#endif
-
-}
-#endif
diff --git a/wpiutil/src/main/native/include/wpi/MessagePack.h b/wpiutil/src/main/native/include/wpi/MessagePack.h
new file mode 100644
index 0000000..e1f54e5
--- /dev/null
+++ b/wpiutil/src/main/native/include/wpi/MessagePack.h
@@ -0,0 +1,39 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <stdint.h>
+
+#include <span>
+#include <string>
+#include <string_view>
+
+#include "wpi/mpack.h"
+
+namespace mpack {
+
+inline void mpack_write_str(mpack_writer_t* writer, std::string_view str) {
+  mpack_write_str(writer, str.data(), str.size());
+}
+
+inline void mpack_write_bytes(mpack_writer_t* writer,
+                              std::span<const uint8_t> data) {
+  mpack_write_bytes(writer, reinterpret_cast<const char*>(data.data()),
+                    data.size());
+}
+
+inline void mpack_reader_init_data(mpack_reader_t* reader,
+                                   std::span<const uint8_t> data) {
+  mpack_reader_init_data(reader, reinterpret_cast<const char*>(data.data()),
+                         data.size());
+}
+
+mpack_error_t mpack_expect_str(mpack_reader_t* reader, std::string* out,
+                               uint32_t maxLen = 1024);
+
+mpack_error_t mpack_read_str(mpack_reader_t* reader, mpack_tag_t* tag,
+                             std::string* out, uint32_t maxLen = 1024);
+
+}  // namespace mpack
diff --git a/wpiutil/src/main/native/include/wpi/MimeTypes.h b/wpiutil/src/main/native/include/wpi/MimeTypes.h
deleted file mode 100644
index ce36ea2..0000000
--- a/wpiutil/src/main/native/include/wpi/MimeTypes.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_MIMETYPES_H_
-#define WPIUTIL_WPI_MIMETYPES_H_
-
-#include <string_view>
-
-namespace wpi {
-
-std::string_view MimeTypeFromPath(std::string_view path);
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_MIMETYPES_H_
diff --git a/wpiutil/src/main/native/include/wpi/MulticastServiceAnnouncer.h b/wpiutil/src/main/native/include/wpi/MulticastServiceAnnouncer.h
deleted file mode 100644
index 5d2048d..0000000
--- a/wpiutil/src/main/native/include/wpi/MulticastServiceAnnouncer.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-#include <memory>
-#include <string>
-#include <string_view>
-#include <utility>
-
-#include "wpi/span.h"
-namespace wpi {
-class MulticastServiceAnnouncer {
- public:
-  MulticastServiceAnnouncer(
-      std::string_view serviceName, std::string_view serviceType, int port,
-      wpi::span<const std::pair<std::string, std::string>> txt);
-  MulticastServiceAnnouncer(
-      std::string_view serviceName, std::string_view serviceType, int port,
-      wpi::span<const std::pair<std::string_view, std::string_view>> txt);
-  ~MulticastServiceAnnouncer() noexcept;
-  void Start();
-  void Stop();
-  bool HasImplementation() const;
-  struct Impl;
-
- private:
-  std::unique_ptr<Impl> pImpl;
-};
-}  // namespace wpi
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef unsigned int WPI_MulticastServiceAnnouncerHandle;  // NOLINT
-
-WPI_MulticastServiceAnnouncerHandle WPI_CreateMulticastServiceAnnouncer(
-    const char* serviceName, const char* serviceType, int32_t port,
-    int32_t txtCount, const char** keys, const char** values);
-
-void WPI_FreeMulticastServiceAnnouncer(
-    WPI_MulticastServiceAnnouncerHandle handle);
-
-void WPI_StartMulticastServiceAnnouncer(
-    WPI_MulticastServiceAnnouncerHandle handle);
-
-void WPI_StopMulticastServiceAnnouncer(
-    WPI_MulticastServiceAnnouncerHandle handle);
-
-int32_t WPI_GetMulticastServiceAnnouncerHasImplementation(
-    WPI_MulticastServiceAnnouncerHandle handle);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
diff --git a/wpiutil/src/main/native/include/wpi/MulticastServiceResolver.h b/wpiutil/src/main/native/include/wpi/MulticastServiceResolver.h
deleted file mode 100644
index 0b63c2f..0000000
--- a/wpiutil/src/main/native/include/wpi/MulticastServiceResolver.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include "wpi/Synchronization.h"
-
-#ifdef __cplusplus
-#include <functional>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <utility>
-#include <vector>
-
-#include "wpi/mutex.h"
-#include "wpi/span.h"
-namespace wpi {
-class MulticastServiceResolver {
- public:
-  explicit MulticastServiceResolver(std::string_view serviceType);
-  ~MulticastServiceResolver() noexcept;
-  struct ServiceData {
-    unsigned int ipv4Address;
-    int port;
-    std::string serviceName;
-    std::string hostName;
-    std::vector<std::pair<std::string, std::string>> txt;
-  };
-  void Start();
-  void Stop();
-  WPI_EventHandle GetEventHandle() const { return event.GetHandle(); }
-  std::vector<ServiceData> GetData() {
-    std::scoped_lock lock{mutex};
-    event.Reset();
-    if (queue.empty()) {
-      return {};
-    }
-    std::vector<ServiceData> ret;
-    queue.swap(ret);
-    return ret;
-  }
-  bool HasImplementation() const;
-  struct Impl;
-
- private:
-  void PushData(ServiceData&& data) {
-    std::scoped_lock lock{mutex};
-    queue.emplace_back(std::forward<ServiceData>(data));
-    event.Set();
-  }
-  wpi::Event event{true};
-  std::vector<ServiceData> queue;
-  wpi::mutex mutex;
-  std::unique_ptr<Impl> pImpl;
-};
-}  // namespace wpi
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef unsigned int WPI_MulticastServiceResolverHandle;  // NOLINT
-
-WPI_MulticastServiceResolverHandle WPI_CreateMulticastServiceResolver(
-    const char* serviceType);
-
-void WPI_FreeMulticastServiceResolver(
-    WPI_MulticastServiceResolverHandle handle);
-
-void WPI_StartMulticastServiceResolver(
-    WPI_MulticastServiceResolverHandle handle);
-
-void WPI_StopMulticastServiceResolver(
-    WPI_MulticastServiceResolverHandle handle);
-
-int32_t WPI_GetMulticastServiceResolverHasImplementation(
-    WPI_MulticastServiceResolverHandle handle);
-
-WPI_EventHandle WPI_GetMulticastServiceResolverEventHandle(
-    WPI_MulticastServiceResolverHandle handle);
-
-typedef struct WPI_ServiceData {  // NOLINT
-  uint32_t ipv4Address;
-  int32_t port;
-  const char* serviceName;
-  const char* hostName;
-  int32_t txtCount;
-  const char** txtKeys;
-  const char** txtValues;
-} WPI_ServiceData;
-
-WPI_ServiceData* WPI_GetMulticastServiceResolverData(
-    WPI_MulticastServiceResolverHandle handle, int32_t* dataCount);
-
-void WPI_FreeServiceData(WPI_ServiceData* serviceData, int32_t length);
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
diff --git a/wpiutil/src/main/native/include/wpi/NetworkAcceptor.h b/wpiutil/src/main/native/include/wpi/NetworkAcceptor.h
deleted file mode 100644
index 9982360..0000000
--- a/wpiutil/src/main/native/include/wpi/NetworkAcceptor.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_NETWORKACCEPTOR_H_
-#define WPIUTIL_WPI_NETWORKACCEPTOR_H_
-
-#include <memory>
-
-#include "wpi/NetworkStream.h"
-
-namespace wpi {
-
-class NetworkAcceptor {
- public:
-  NetworkAcceptor() = default;
-  virtual ~NetworkAcceptor() = default;
-
-  virtual int start() = 0;
-  virtual void shutdown() = 0;
-  virtual std::unique_ptr<NetworkStream> accept() = 0;
-
-  NetworkAcceptor(const NetworkAcceptor&) = delete;
-  NetworkAcceptor& operator=(const NetworkAcceptor&) = delete;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_NETWORKACCEPTOR_H_
diff --git a/wpiutil/src/main/native/include/wpi/NetworkStream.h b/wpiutil/src/main/native/include/wpi/NetworkStream.h
deleted file mode 100644
index b842ecd..0000000
--- a/wpiutil/src/main/native/include/wpi/NetworkStream.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_NETWORKSTREAM_H_
-#define WPIUTIL_WPI_NETWORKSTREAM_H_
-
-#include <cstddef>
-#include <string_view>
-
-namespace wpi {
-
-class NetworkStream {
- public:
-  NetworkStream() = default;
-  virtual ~NetworkStream() = default;
-
-  enum Error {
-    kConnectionClosed = 0,
-    kConnectionReset = -1,
-    kConnectionTimedOut = -2,
-    kWouldBlock = -3
-  };
-
-  virtual size_t send(const char* buffer, size_t len, Error* err) = 0;
-  virtual size_t receive(char* buffer, size_t len, Error* err,
-                         int timeout = 0) = 0;
-  virtual void close() = 0;
-
-  virtual std::string_view getPeerIP() const = 0;
-  virtual int getPeerPort() const = 0;
-  virtual void setNoDelay() = 0;
-
-  // returns false on failure
-  virtual bool setBlocking(bool enabled) = 0;
-  virtual int getNativeHandle() const = 0;
-
-  NetworkStream(const NetworkStream&) = delete;
-  NetworkStream& operator=(const NetworkStream&) = delete;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_NETWORKSTREAM_H_
diff --git a/wpiutil/src/main/native/include/wpi/ParallelTcpConnector.h b/wpiutil/src/main/native/include/wpi/ParallelTcpConnector.h
deleted file mode 100644
index 47c29d0..0000000
--- a/wpiutil/src/main/native/include/wpi/ParallelTcpConnector.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <stdint.h>
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "wpi/span.h"
-#include "wpi/uv/Timer.h"
-
-namespace wpi {
-
-class Logger;
-
-namespace uv {
-class GetAddrInfoReq;
-class Loop;
-class Tcp;
-class Timer;
-}  // namespace uv
-
-/**
- * Parallel TCP connector.  Attempts parallel resolution and connection to
- * multiple servers with automatic retry if none connect.
- *
- * Each successful TCP connection results in a call to the connected callback.
- * For correct operation, the consuming code (either the connected callback or
- * e.g. task it starts) must call Succeeded() to indicate if the connection has
- * succeeded prior to the reconnect rate timeout.  A successful connection
- * results in the connector terminating all other connection attempts.
- *
- * After the reconnect rate times out, all remaining active connection attempts
- * are canceled and new ones started.
- */
-class ParallelTcpConnector
-    : public std::enable_shared_from_this<ParallelTcpConnector> {
-  struct private_init {};
-
- public:
-  /**
-   * Create.
-   *
-   * @param loop loop
-   * @param reconnectRate how long to wait after starting connection attempts
-   *                      to cancel and attempt connecting again
-   * @param logger logger
-   * @param connected callback function when a connection succeeds; may be
-   *                  called multiple times if it does not call Succeeded()
-   *                  before returning
-   * @return Parallel connector
-   */
-  static std::shared_ptr<ParallelTcpConnector> Create(
-      wpi::uv::Loop& loop, wpi::uv::Timer::Time reconnectRate,
-      wpi::Logger& logger, std::function<void(wpi::uv::Tcp& tcp)> connected) {
-    return std::make_shared<ParallelTcpConnector>(
-        loop, reconnectRate, logger, std::move(connected), private_init{});
-  }
-
-  ParallelTcpConnector(wpi::uv::Loop& loop, wpi::uv::Timer::Time reconnectRate,
-                       wpi::Logger& logger,
-                       std::function<void(wpi::uv::Tcp& tcp)> connected,
-                       const private_init&);
-  ~ParallelTcpConnector();
-
-  ParallelTcpConnector(const ParallelTcpConnector&) = delete;
-  ParallelTcpConnector& operator=(const ParallelTcpConnector&) = delete;
-
-  /**
-   * Closes resources, canceling all pending action attempts.
-   */
-  void Close();
-
-  /**
-   * Changes the servers/ports to connect to.  Starts connection attempts if not
-   * already connected.
-   *
-   * @param servers array of server/port pairs
-   */
-  void SetServers(
-      wpi::span<const std::pair<std::string, unsigned int>> servers);
-
-  /**
-   * Tells the parallel connector that the current connection has terminated and
-   * it is necessary to start reconnection attempts.
-   */
-  void Disconnected();
-
-  /**
-   * Tells the parallel connector that a particular connection has succeeded and
-   * it should stop trying to connect.
-   *
-   * @param tcp connection passed to connected callback
-   */
-  void Succeeded(wpi::uv::Tcp& tcp);
-
- private:
-  bool IsConnected() const { return m_isConnected || m_servers.empty(); }
-  void Connect();
-  void CancelAll(wpi::uv::Tcp* except = nullptr);
-
-  wpi::uv::Loop& m_loop;
-  wpi::Logger& m_logger;
-  wpi::uv::Timer::Time m_reconnectRate;
-  std::function<void(wpi::uv::Tcp& tcp)> m_connected;
-  std::shared_ptr<wpi::uv::Timer> m_reconnectTimer;
-  std::vector<std::pair<std::string, unsigned int>> m_servers;
-  std::vector<std::weak_ptr<wpi::uv::GetAddrInfoReq>> m_resolvers;
-  std::vector<std::weak_ptr<wpi::uv::Tcp>> m_attempts;
-  bool m_isConnected{false};
-};
-
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/PointerUnion.h b/wpiutil/src/main/native/include/wpi/PointerUnion.h
deleted file mode 100644
index 8d6e580..0000000
--- a/wpiutil/src/main/native/include/wpi/PointerUnion.h
+++ /dev/null
@@ -1,491 +0,0 @@
-//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the PointerUnion class, which is a discriminated union of
-// pointer types.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_POINTERUNION_H
-#define WPIUTIL_WPI_POINTERUNION_H
-
-#include "wpi/DenseMapInfo.h"
-#include "wpi/PointerIntPair.h"
-#include "wpi/PointerLikeTypeTraits.h"
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-
-namespace wpi {
-
-template <typename T> struct PointerUnionTypeSelectorReturn {
-  using Return = T;
-};
-
-/// Get a type based on whether two types are the same or not.
-///
-/// For:
-///
-/// \code
-///   using Ret = typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return;
-/// \endcode
-///
-/// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
-template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
-struct PointerUnionTypeSelector {
-  using Return = typename PointerUnionTypeSelectorReturn<RET_NE>::Return;
-};
-
-template <typename T, typename RET_EQ, typename RET_NE>
-struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
-  using Return = typename PointerUnionTypeSelectorReturn<RET_EQ>::Return;
-};
-
-template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
-struct PointerUnionTypeSelectorReturn<
-    PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>> {
-  using Return =
-      typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return;
-};
-
-/// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
-/// for the two template arguments.
-template <typename PT1, typename PT2> class PointerUnionUIntTraits {
-public:
-  static inline void *getAsVoidPointer(void *P) { return P; }
-  static inline void *getFromVoidPointer(void *P) { return P; }
-
-  enum {
-    PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
-    PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable),
-    NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
-  };
-};
-
-/// A discriminated union of two pointer types, with the discriminator in the
-/// low bit of the pointer.
-///
-/// This implementation is extremely efficient in space due to leveraging the
-/// low bits of the pointer, while exposing a natural and type-safe API.
-///
-/// Common use patterns would be something like this:
-///    PointerUnion<int*, float*> P;
-///    P = (int*)0;
-///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
-///    X = P.get<int*>();     // ok.
-///    Y = P.get<float*>();   // runtime assertion failure.
-///    Z = P.get<double*>();  // compile time failure.
-///    P = (float*)0;
-///    Y = P.get<float*>();   // ok.
-///    X = P.get<int*>();     // runtime assertion failure.
-template <typename PT1, typename PT2> class PointerUnion {
-public:
-  using ValTy =
-      PointerIntPair<void *, 1, bool, PointerUnionUIntTraits<PT1, PT2>>;
-
-private:
-  ValTy Val;
-
-  struct IsPT1 {
-    static const int Num = 0;
-  };
-  struct IsPT2 {
-    static const int Num = 1;
-  };
-  template <typename T> struct UNION_DOESNT_CONTAIN_TYPE {};
-
-public:
-  PointerUnion() = default;
-  PointerUnion(PT1 V)
-      : Val(const_cast<void *>(
-            PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {}
-  PointerUnion(PT2 V)
-      : Val(const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)),
-            1) {}
-
-  /// Test if the pointer held in the union is null, regardless of
-  /// which type it is.
-  bool isNull() const {
-    // Convert from the void* to one of the pointer types, to make sure that
-    // we recursively strip off low bits if we have a nested PointerUnion.
-    return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
-  }
-
-  explicit operator bool() const { return !isNull(); }
-
-  /// Test if the Union currently holds the type matching T.
-  template <typename T> int is() const {
-    using Ty = typename ::wpi::PointerUnionTypeSelector<
-        PT1, T, IsPT1,
-        ::wpi::PointerUnionTypeSelector<PT2, T, IsPT2,
-                                        UNION_DOESNT_CONTAIN_TYPE<T>>>::Return;
-    int TyNo = Ty::Num;
-    return static_cast<int>(Val.getInt()) == TyNo;
-  }
-
-  /// Returns the value of the specified pointer type.
-  ///
-  /// If the specified pointer type is incorrect, assert.
-  template <typename T> T get() const {
-    assert(is<T>() && "Invalid accessor called");
-    return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
-  }
-
-  /// Returns the current pointer if it is of the specified pointer type,
-  /// otherwises returns null.
-  template <typename T> T dyn_cast() const {
-    if (is<T>())
-      return get<T>();
-    return T();
-  }
-
-  /// If the union is set to the first pointer type get an address pointing to
-  /// it.
-  PT1 const *getAddrOfPtr1() const {
-    return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
-  }
-
-  /// If the union is set to the first pointer type get an address pointing to
-  /// it.
-  PT1 *getAddrOfPtr1() {
-    assert(is<PT1>() && "Val is not the first pointer");
-    assert(
-        get<PT1>() == Val.getPointer() &&
-        "Can't get the address because PointerLikeTypeTraits changes the ptr");
-    return const_cast<PT1 *>(
-        reinterpret_cast<const PT1 *>(Val.getAddrOfPointer()));
-  }
-
-  /// Assignment from nullptr which just clears the union.
-  const PointerUnion &operator=(std::nullptr_t) {
-    Val.initWithPointer(nullptr);
-    return *this;
-  }
-
-  /// Assignment operators - Allow assigning into this union from either
-  /// pointer type, setting the discriminator to remember what it came from.
-  const PointerUnion &operator=(const PT1 &RHS) {
-    Val.initWithPointer(
-        const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
-    return *this;
-  }
-  const PointerUnion &operator=(const PT2 &RHS) {
-    Val.setPointerAndInt(
-        const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
-        1);
-    return *this;
-  }
-
-  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
-  static inline PointerUnion getFromOpaqueValue(void *VP) {
-    PointerUnion V;
-    V.Val = ValTy::getFromOpaqueValue(VP);
-    return V;
-  }
-};
-
-template <typename PT1, typename PT2>
-bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
-  return lhs.getOpaqueValue() == rhs.getOpaqueValue();
-}
-
-template <typename PT1, typename PT2>
-bool operator!=(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
-  return lhs.getOpaqueValue() != rhs.getOpaqueValue();
-}
-
-template <typename PT1, typename PT2>
-bool operator<(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) {
-  return lhs.getOpaqueValue() < rhs.getOpaqueValue();
-}
-
-// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
-// # low bits available = min(PT1bits,PT2bits)-1.
-template <typename PT1, typename PT2>
-struct PointerLikeTypeTraits<PointerUnion<PT1, PT2>> {
-  static inline void *getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
-    return P.getOpaqueValue();
-  }
-
-  static inline PointerUnion<PT1, PT2> getFromVoidPointer(void *P) {
-    return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
-  }
-
-  // The number of bits available are the min of the two pointer types.
-  enum {
-    NumLowBitsAvailable = PointerLikeTypeTraits<
-        typename PointerUnion<PT1, PT2>::ValTy>::NumLowBitsAvailable
-  };
-};
-
-/// A pointer union of three pointer types. See documentation for PointerUnion
-/// for usage.
-template <typename PT1, typename PT2, typename PT3> class PointerUnion3 {
-public:
-  using InnerUnion = PointerUnion<PT1, PT2>;
-  using ValTy = PointerUnion<InnerUnion, PT3>;
-
-private:
-  ValTy Val;
-
-  struct IsInnerUnion {
-    ValTy Val;
-
-    IsInnerUnion(ValTy val) : Val(val) {}
-
-    template <typename T> int is() const {
-      return Val.template is<InnerUnion>() &&
-             Val.template get<InnerUnion>().template is<T>();
-    }
-
-    template <typename T> T get() const {
-      return Val.template get<InnerUnion>().template get<T>();
-    }
-  };
-
-  struct IsPT3 {
-    ValTy Val;
-
-    IsPT3(ValTy val) : Val(val) {}
-
-    template <typename T> int is() const { return Val.template is<T>(); }
-    template <typename T> T get() const { return Val.template get<T>(); }
-  };
-
-public:
-  PointerUnion3() = default;
-  PointerUnion3(PT1 V) { Val = InnerUnion(V); }
-  PointerUnion3(PT2 V) { Val = InnerUnion(V); }
-  PointerUnion3(PT3 V) { Val = V; }
-
-  /// Test if the pointer held in the union is null, regardless of
-  /// which type it is.
-  bool isNull() const { return Val.isNull(); }
-  explicit operator bool() const { return !isNull(); }
-
-  /// Test if the Union currently holds the type matching T.
-  template <typename T> int is() const {
-    // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
-    using Ty = typename ::wpi::PointerUnionTypeSelector<
-        PT1, T, IsInnerUnion,
-        ::wpi::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3>>::Return;
-    return Ty(Val).template is<T>();
-  }
-
-  /// Returns the value of the specified pointer type.
-  ///
-  /// If the specified pointer type is incorrect, assert.
-  template <typename T> T get() const {
-    assert(is<T>() && "Invalid accessor called");
-    // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
-    using Ty = typename ::wpi::PointerUnionTypeSelector<
-        PT1, T, IsInnerUnion,
-        ::wpi::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3>>::Return;
-    return Ty(Val).template get<T>();
-  }
-
-  /// Returns the current pointer if it is of the specified pointer type,
-  /// otherwises returns null.
-  template <typename T> T dyn_cast() const {
-    if (is<T>())
-      return get<T>();
-    return T();
-  }
-
-  /// Assignment from nullptr which just clears the union.
-  const PointerUnion3 &operator=(std::nullptr_t) {
-    Val = nullptr;
-    return *this;
-  }
-
-  /// Assignment operators - Allow assigning into this union from either
-  /// pointer type, setting the discriminator to remember what it came from.
-  const PointerUnion3 &operator=(const PT1 &RHS) {
-    Val = InnerUnion(RHS);
-    return *this;
-  }
-  const PointerUnion3 &operator=(const PT2 &RHS) {
-    Val = InnerUnion(RHS);
-    return *this;
-  }
-  const PointerUnion3 &operator=(const PT3 &RHS) {
-    Val = RHS;
-    return *this;
-  }
-
-  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
-  static inline PointerUnion3 getFromOpaqueValue(void *VP) {
-    PointerUnion3 V;
-    V.Val = ValTy::getFromOpaqueValue(VP);
-    return V;
-  }
-};
-
-// Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
-// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
-template <typename PT1, typename PT2, typename PT3>
-struct PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3>> {
-  static inline void *getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
-    return P.getOpaqueValue();
-  }
-
-  static inline PointerUnion3<PT1, PT2, PT3> getFromVoidPointer(void *P) {
-    return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
-  }
-
-  // The number of bits available are the min of the two pointer types.
-  enum {
-    NumLowBitsAvailable = PointerLikeTypeTraits<
-        typename PointerUnion3<PT1, PT2, PT3>::ValTy>::NumLowBitsAvailable
-  };
-};
-
-template <typename PT1, typename PT2, typename PT3>
-bool operator<(PointerUnion3<PT1, PT2, PT3> lhs,
-               PointerUnion3<PT1, PT2, PT3> rhs) {
-  return lhs.getOpaqueValue() < rhs.getOpaqueValue();
-}
-
-/// A pointer union of four pointer types. See documentation for PointerUnion
-/// for usage.
-template <typename PT1, typename PT2, typename PT3, typename PT4>
-class PointerUnion4 {
-public:
-  using InnerUnion1 = PointerUnion<PT1, PT2>;
-  using InnerUnion2 = PointerUnion<PT3, PT4>;
-  using ValTy = PointerUnion<InnerUnion1, InnerUnion2>;
-
-private:
-  ValTy Val;
-
-public:
-  PointerUnion4() = default;
-  PointerUnion4(PT1 V) { Val = InnerUnion1(V); }
-  PointerUnion4(PT2 V) { Val = InnerUnion1(V); }
-  PointerUnion4(PT3 V) { Val = InnerUnion2(V); }
-  PointerUnion4(PT4 V) { Val = InnerUnion2(V); }
-
-  /// Test if the pointer held in the union is null, regardless of
-  /// which type it is.
-  bool isNull() const { return Val.isNull(); }
-  explicit operator bool() const { return !isNull(); }
-
-  /// Test if the Union currently holds the type matching T.
-  template <typename T> int is() const {
-    // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
-    using Ty = typename ::wpi::PointerUnionTypeSelector<
-        PT1, T, InnerUnion1,
-        ::wpi::PointerUnionTypeSelector<PT2, T, InnerUnion1,
-                                        InnerUnion2>>::Return;
-    return Val.template is<Ty>() && Val.template get<Ty>().template is<T>();
-  }
-
-  /// Returns the value of the specified pointer type.
-  ///
-  /// If the specified pointer type is incorrect, assert.
-  template <typename T> T get() const {
-    assert(is<T>() && "Invalid accessor called");
-    // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
-    using Ty = typename ::wpi::PointerUnionTypeSelector<
-        PT1, T, InnerUnion1,
-        ::wpi::PointerUnionTypeSelector<PT2, T, InnerUnion1,
-                                        InnerUnion2>>::Return;
-    return Val.template get<Ty>().template get<T>();
-  }
-
-  /// Returns the current pointer if it is of the specified pointer type,
-  /// otherwises returns null.
-  template <typename T> T dyn_cast() const {
-    if (is<T>())
-      return get<T>();
-    return T();
-  }
-
-  /// Assignment from nullptr which just clears the union.
-  const PointerUnion4 &operator=(std::nullptr_t) {
-    Val = nullptr;
-    return *this;
-  }
-
-  /// Assignment operators - Allow assigning into this union from either
-  /// pointer type, setting the discriminator to remember what it came from.
-  const PointerUnion4 &operator=(const PT1 &RHS) {
-    Val = InnerUnion1(RHS);
-    return *this;
-  }
-  const PointerUnion4 &operator=(const PT2 &RHS) {
-    Val = InnerUnion1(RHS);
-    return *this;
-  }
-  const PointerUnion4 &operator=(const PT3 &RHS) {
-    Val = InnerUnion2(RHS);
-    return *this;
-  }
-  const PointerUnion4 &operator=(const PT4 &RHS) {
-    Val = InnerUnion2(RHS);
-    return *this;
-  }
-
-  void *getOpaqueValue() const { return Val.getOpaqueValue(); }
-  static inline PointerUnion4 getFromOpaqueValue(void *VP) {
-    PointerUnion4 V;
-    V.Val = ValTy::getFromOpaqueValue(VP);
-    return V;
-  }
-};
-
-// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
-// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
-template <typename PT1, typename PT2, typename PT3, typename PT4>
-struct PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4>> {
-  static inline void *
-  getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
-    return P.getOpaqueValue();
-  }
-
-  static inline PointerUnion4<PT1, PT2, PT3, PT4> getFromVoidPointer(void *P) {
-    return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
-  }
-
-  // The number of bits available are the min of the two pointer types.
-  enum {
-    NumLowBitsAvailable = PointerLikeTypeTraits<
-        typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>::NumLowBitsAvailable
-  };
-};
-
-// Teach DenseMap how to use PointerUnions as keys.
-template <typename T, typename U> struct DenseMapInfo<PointerUnion<T, U>> {
-  using Pair = PointerUnion<T, U>;
-  using FirstInfo = DenseMapInfo<T>;
-  using SecondInfo = DenseMapInfo<U>;
-
-  static inline Pair getEmptyKey() { return Pair(FirstInfo::getEmptyKey()); }
-
-  static inline Pair getTombstoneKey() {
-    return Pair(FirstInfo::getTombstoneKey());
-  }
-
-  static unsigned getHashValue(const Pair &PairVal) {
-    intptr_t key = (intptr_t)PairVal.getOpaqueValue();
-    return DenseMapInfo<intptr_t>::getHashValue(key);
-  }
-
-  static bool isEqual(const Pair &LHS, const Pair &RHS) {
-    return LHS.template is<T>() == RHS.template is<T>() &&
-           (LHS.template is<T>() ? FirstInfo::isEqual(LHS.template get<T>(),
-                                                      RHS.template get<T>())
-                                 : SecondInfo::isEqual(LHS.template get<U>(),
-                                                       RHS.template get<U>()));
-  }
-};
-
-} // end namespace wpi
-
-#endif // WPIUTIL_WPI_POINTERUNION_H
diff --git a/wpiutil/src/main/native/include/wpi/PortForwarder.h b/wpiutil/src/main/native/include/wpi/PortForwarder.h
deleted file mode 100644
index 9e445a0..0000000
--- a/wpiutil/src/main/native/include/wpi/PortForwarder.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_PORTFORWARDER_H_
-#define WPIUTIL_WPI_PORTFORWARDER_H_
-
-#pragma once
-
-#include <memory>
-#include <string_view>
-
-namespace wpi {
-
-/**
- * Forward ports to another host.  This is primarily useful for accessing
- * Ethernet-connected devices from a computer tethered to the RoboRIO USB port.
- */
-class PortForwarder {
- public:
-  PortForwarder(const PortForwarder&) = delete;
-  PortForwarder& operator=(const PortForwarder&) = delete;
-
-  /**
-   * Get an instance of the PortForwarder class.
-   *
-   * This is a singleton to guarantee that there is only a single instance
-   * regardless of how many times GetInstance is called.
-   */
-  static PortForwarder& GetInstance();
-
-  /**
-   * Forward a local TCP port to a remote host and port.
-   * Note that local ports less than 1024 won't work as a normal user.
-   *
-   * @param port       local port number
-   * @param remoteHost remote IP address / DNS name
-   * @param remotePort remote port number
-   */
-  void Add(unsigned int port, std::string_view remoteHost,
-           unsigned int remotePort);
-
-  /**
-   * Stop TCP forwarding on a port.
-   *
-   * @param port local port number
-   */
-  void Remove(unsigned int port);
-
- private:
-  PortForwarder();
-
-  struct Impl;
-  std::unique_ptr<Impl> m_impl;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_PORTFORWARDER_H_
diff --git a/wpiutil/src/main/native/include/wpi/SafeThread.h b/wpiutil/src/main/native/include/wpi/SafeThread.h
index bf37732..753dc6c 100644
--- a/wpiutil/src/main/native/include/wpi/SafeThread.h
+++ b/wpiutil/src/main/native/include/wpi/SafeThread.h
@@ -10,6 +10,7 @@
 #include <thread>
 #include <utility>
 
+#include "wpi/Synchronization.h"
 #include "wpi/condition_variable.h"
 #include "wpi/mutex.h"
 
@@ -18,17 +19,33 @@
 /**
  * Base class for SafeThreadOwner threads.
  */
-class SafeThread {
+class SafeThreadBase {
  public:
-  virtual ~SafeThread() = default;
+  virtual ~SafeThreadBase() = default;
   virtual void Main() = 0;
+  virtual void Stop() = 0;
 
   mutable wpi::mutex m_mutex;
   std::atomic_bool m_active{true};
-  wpi::condition_variable m_cond;
   std::thread::id m_threadId;
 };
 
+class SafeThread : public SafeThreadBase {
+ public:
+  void Stop() override;
+
+  wpi::condition_variable m_cond;
+};
+
+class SafeThreadEvent : public SafeThreadBase {
+ public:
+  SafeThreadEvent() : m_stopEvent{true} {}
+
+  void Stop() override;
+
+  Event m_stopEvent;
+};
+
 namespace detail {
 
 /**
@@ -36,12 +53,12 @@
  */
 class SafeThreadProxyBase {
  public:
-  explicit SafeThreadProxyBase(std::shared_ptr<SafeThread> thr);
+  explicit SafeThreadProxyBase(std::shared_ptr<SafeThreadBase> thr);
   explicit operator bool() const { return m_thread != nullptr; }
   std::unique_lock<wpi::mutex>& GetLock() { return m_lock; }
 
  protected:
-  std::shared_ptr<SafeThread> m_thread;
+  std::shared_ptr<SafeThreadBase> m_thread;
   std::unique_lock<wpi::mutex> m_lock;
 };
 
@@ -53,7 +70,7 @@
 template <typename T>
 class SafeThreadProxy : public SafeThreadProxyBase {
  public:
-  explicit SafeThreadProxy(std::shared_ptr<SafeThread> thr)
+  explicit SafeThreadProxy(std::shared_ptr<SafeThreadBase> thr)
       : SafeThreadProxyBase(std::move(thr)) {}
   T& operator*() const { return *static_cast<T*>(m_thread.get()); }
   T* operator->() const { return static_cast<T*>(m_thread.get()); }
@@ -89,13 +106,13 @@
   void SetJoinAtExit(bool joinAtExit) { m_joinAtExit = joinAtExit; }
 
  protected:
-  void Start(std::shared_ptr<SafeThread> thr);
-  std::shared_ptr<SafeThread> GetThreadSharedPtr() const;
+  void Start(std::shared_ptr<SafeThreadBase> thr);
+  std::shared_ptr<SafeThreadBase> GetThreadSharedPtr() const;
 
  private:
   mutable wpi::mutex m_mutex;
   std::thread m_stdThread;
-  std::weak_ptr<SafeThread> m_thread;
+  std::weak_ptr<SafeThreadBase> m_thread;
   std::atomic_bool m_joinAtExit{true};
 };
 
diff --git a/wpiutil/src/main/native/include/wpi/SmallVector.h b/wpiutil/src/main/native/include/wpi/SmallVector.h
deleted file mode 100644
index 430f85a..0000000
--- a/wpiutil/src/main/native/include/wpi/SmallVector.h
+++ /dev/null
@@ -1,949 +0,0 @@
-//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the SmallVector class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_SMALLVECTOR_H
-#define WPIUTIL_WPI_SMALLVECTOR_H
-
-// This file uses std::memcpy() to copy std::pair<unsigned int, unsigned int>.
-// That type is POD, but the standard doesn't guarantee that. GCC doesn't treat
-// the type as POD so it throws a warning. We want to consider this a warning
-// instead of an error.
-#if __GNUC__ >= 8
-#pragma GCC diagnostic warning "-Wclass-memaccess"
-#endif
-
-#include "wpi/iterator_range.h"
-#include "wpi/AlignOf.h"
-#include "wpi/Compiler.h"
-#include "wpi/MathExtras.h"
-#include "wpi/MemAlloc.h"
-#include "wpi/type_traits.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstdlib>
-#include <cstring>
-#include <initializer_list>
-#include <iterator>
-#include <memory>
-#include <new>
-#include <type_traits>
-#include <utility>
-
-namespace wpi {
-
-/// This is all the non-templated stuff common to all SmallVectors.
-class SmallVectorBase {
-protected:
-  void *BeginX;
-  unsigned Size = 0, Capacity;
-
-  SmallVectorBase() = delete;
-  SmallVectorBase(void *FirstEl, size_t Capacity)
-      : BeginX(FirstEl), Capacity(static_cast<unsigned>(Capacity)) {}
-
-  /// This is an implementation of the grow() method which only works
-  /// on POD-like data types and is out of line to reduce code duplication.
-  void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize);
-
-public:
-  LLVM_ATTRIBUTE_ALWAYS_INLINE
-  size_t size() const { return Size; }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE
-  size_t capacity() const { return Capacity; }
-
-  LLVM_NODISCARD bool empty() const { return !Size; }
-
-  /// Set the array size to \p N, which the current array must have enough
-  /// capacity for.
-  ///
-  /// This does not construct or destroy any elements in the vector.
-  ///
-  /// Clients can use this in conjunction with capacity() to write past the end
-  /// of the buffer when they know that more elements are available, and only
-  /// update the size later. This avoids the cost of value initializing elements
-  /// which will only be overwritten.
-  void set_size(size_t Size) {
-    assert(Size <= capacity());
-    this->Size = static_cast<unsigned>(Size);
-  }
-};
-
-/// Figure out the offset of the first element.
-template <class T, typename = void> struct SmallVectorAlignmentAndSize {
-  AlignedCharArrayUnion<SmallVectorBase> Base;
-  AlignedCharArrayUnion<T> FirstEl;
-};
-
-/// This is the part of SmallVectorTemplateBase which does not depend on whether
-/// the type T is a POD. The extra dummy template argument is used by ArrayRef
-/// to avoid unnecessarily requiring T to be complete.
-template <typename T, typename = void>
-class SmallVectorTemplateCommon : public SmallVectorBase {
-  /// Find the address of the first element.  For this pointer math to be valid
-  /// with small-size of 0 for T with lots of alignment, it's important that
-  /// SmallVectorStorage is properly-aligned even for small-size of 0.
-  void *getFirstEl() const {
-    return const_cast<void *>(reinterpret_cast<const void *>(
-        reinterpret_cast<const char *>(this) +
-        offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)));
-  }
-  // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
-
-protected:
-  SmallVectorTemplateCommon(size_t Size)
-      : SmallVectorBase(getFirstEl(), Size) {}
-
-  void grow_pod(size_t MinCapacity, size_t TSize) {
-    SmallVectorBase::grow_pod(getFirstEl(), MinCapacity, TSize);
-  }
-
-  /// Return true if this is a smallvector which has not had dynamic
-  /// memory allocated for it.
-  bool isSmall() const { return BeginX == getFirstEl(); }
-
-  /// Put this vector in a state of being small.
-  void resetToSmall() {
-    BeginX = getFirstEl();
-    Size = Capacity = 0; // FIXME: Setting Capacity to 0 is suspect.
-  }
-
-public:
-  using size_type = size_t;
-  using difference_type = ptrdiff_t;
-  using value_type = T;
-  using iterator = T *;
-  using const_iterator = const T *;
-
-  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
-  using reverse_iterator = std::reverse_iterator<iterator>;
-
-  using reference = T &;
-  using const_reference = const T &;
-  using pointer = T *;
-  using const_pointer = const T *;
-
-  // forward iterator creation methods.
-  LLVM_ATTRIBUTE_ALWAYS_INLINE
-  iterator begin() { return (iterator)this->BeginX; }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE
-  const_iterator begin() const { return (const_iterator)this->BeginX; }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE
-  iterator end() { return begin() + size(); }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE
-  const_iterator end() const { return begin() + size(); }
-
-  // reverse iterator creation methods.
-  reverse_iterator rbegin()            { return reverse_iterator(end()); }
-  const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
-  reverse_iterator rend()              { return reverse_iterator(begin()); }
-  const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
-
-  size_type size_in_bytes() const { return size() * sizeof(T); }
-  size_type max_size() const { return size_type(-1) / sizeof(T); }
-
-  size_t capacity_in_bytes() const { return capacity() * sizeof(T); }
-
-  /// Return a pointer to the vector's buffer, even if empty().
-  pointer data() { return pointer(begin()); }
-  /// Return a pointer to the vector's buffer, even if empty().
-  const_pointer data() const { return const_pointer(begin()); }
-
-  LLVM_ATTRIBUTE_ALWAYS_INLINE
-  reference operator[](size_type idx) {
-    assert(idx < size());
-    return begin()[idx];
-  }
-  LLVM_ATTRIBUTE_ALWAYS_INLINE
-  const_reference operator[](size_type idx) const {
-    assert(idx < size());
-    return begin()[idx];
-  }
-
-  reference front() {
-    assert(!empty());
-    return begin()[0];
-  }
-  const_reference front() const {
-    assert(!empty());
-    return begin()[0];
-  }
-
-  reference back() {
-    assert(!empty());
-    return end()[-1];
-  }
-  const_reference back() const {
-    assert(!empty());
-    return end()[-1];
-  }
-};
-
-/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
-/// implementations that are designed to work with non-POD-like T's.
-template <typename T, bool = isPodLike<T>::value>
-class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
-protected:
-  SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
-
-  static void destroy_range(T *S, T *E) {
-    while (S != E) {
-      --E;
-      E->~T();
-    }
-  }
-
-  /// Move the range [I, E) into the uninitialized memory starting with "Dest",
-  /// constructing elements as needed.
-  template<typename It1, typename It2>
-  static void uninitialized_move(It1 I, It1 E, It2 Dest) {
-    std::uninitialized_copy(std::make_move_iterator(I),
-                            std::make_move_iterator(E), Dest);
-  }
-
-  /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
-  /// constructing elements as needed.
-  template<typename It1, typename It2>
-  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
-    std::uninitialized_copy(I, E, Dest);
-  }
-
-  /// Grow the allocated memory (without initializing new elements), doubling
-  /// the size of the allocated memory. Guarantees space for at least one more
-  /// element, or MinSize more elements if specified.
-  void grow(size_t MinSize = 0);
-
-public:
-  void push_back(const T &Elt) {
-    if (LLVM_UNLIKELY(this->size() >= this->capacity()))
-      this->grow();
-    ::new ((void*) this->end()) T(Elt);
-    this->set_size(this->size() + 1);
-  }
-
-  void push_back(T &&Elt) {
-    if (LLVM_UNLIKELY(this->size() >= this->capacity()))
-      this->grow();
-    ::new ((void*) this->end()) T(::std::move(Elt));
-    this->set_size(this->size() + 1);
-  }
-
-  void pop_back() {
-    this->set_size(this->size() - 1);
-    this->end()->~T();
-  }
-};
-
-// Define this out-of-line to dissuade the C++ compiler from inlining it.
-template <typename T, bool isPodLike>
-void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
-  if (MinSize > UINT32_MAX)
-    report_bad_alloc_error("SmallVector capacity overflow during allocation");
-
-  // Always grow, even from zero.
-  size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2));
-  NewCapacity = (std::min)((std::max)(NewCapacity, MinSize), size_t(UINT32_MAX));
-  T *NewElts = static_cast<T*>(wpi::safe_malloc(NewCapacity*sizeof(T)));
-
-  // Move the elements over.
-  this->uninitialized_move(this->begin(), this->end(), NewElts);
-
-  // Destroy the original elements.
-  destroy_range(this->begin(), this->end());
-
-  // If this wasn't grown from the inline copy, deallocate the old space.
-  if (!this->isSmall())
-    free(this->begin());
-
-  this->BeginX = NewElts;
-  this->Capacity = static_cast<unsigned>(NewCapacity);
-}
-
-
-/// SmallVectorTemplateBase<isPodLike = true> - This is where we put method
-/// implementations that are designed to work with POD-like T's.
-template <typename T>
-class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
-protected:
-  SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
-
-  // No need to do a destroy loop for POD's.
-  static void destroy_range(T *, T *) {}
-
-  /// Move the range [I, E) onto the uninitialized memory
-  /// starting with "Dest", constructing elements into it as needed.
-  template<typename It1, typename It2>
-  static void uninitialized_move(It1 I, It1 E, It2 Dest) {
-    // Just do a copy.
-    uninitialized_copy(I, E, Dest);
-  }
-
-  /// Copy the range [I, E) onto the uninitialized memory
-  /// starting with "Dest", constructing elements into it as needed.
-  template<typename It1, typename It2>
-  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
-    // Arbitrary iterator types; just use the basic implementation.
-    std::uninitialized_copy(I, E, Dest);
-  }
-
-  /// Copy the range [I, E) onto the uninitialized memory
-  /// starting with "Dest", constructing elements into it as needed.
-  template <typename T1, typename T2>
-  static void uninitialized_copy(
-      T1 *I, T1 *E, T2 *Dest,
-      typename std::enable_if<std::is_same<typename std::remove_const<T1>::type,
-                                           T2>::value>::type * = nullptr) {
-    // Use memcpy for PODs iterated by pointers (which includes SmallVector
-    // iterators): std::uninitialized_copy optimizes to memmove, but we can
-    // use memcpy here. Note that I and E are iterators and thus might be
-    // invalid for memcpy if they are equal.
-    if (I != E)
-      memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T));
-  }
-
-  /// Double the size of the allocated memory, guaranteeing space for at
-  /// least one more element or MinSize if specified.
-  void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); }
-
-public:
-  void push_back(const T &Elt) {
-    if (LLVM_UNLIKELY(this->size() >= this->capacity()))
-      this->grow();
-    memcpy(reinterpret_cast<void *>(this->end()), &Elt, sizeof(T));
-    this->set_size(this->size() + 1);
-  }
-
-  void pop_back() { this->set_size(this->size() - 1); }
-};
-
-/// This class consists of common code factored out of the SmallVector class to
-/// reduce code duplication based on the SmallVector 'N' template parameter.
-template <typename T>
-class SmallVectorImpl : public SmallVectorTemplateBase<T> {
-  using SuperClass = SmallVectorTemplateBase<T>;
-
-public:
-  using iterator = typename SuperClass::iterator;
-  using const_iterator = typename SuperClass::const_iterator;
-  using size_type = typename SuperClass::size_type;
-
-protected:
-  // Default ctor - Initialize to empty.
-  explicit SmallVectorImpl(unsigned N)
-      : SmallVectorTemplateBase<T, isPodLike<T>::value>(N) {}
-
-public:
-  SmallVectorImpl(const SmallVectorImpl &) = delete;
-
-  ~SmallVectorImpl() {
-    // Subclass has already destructed this vector's elements.
-    // If this wasn't grown from the inline copy, deallocate the old space.
-    if (!this->isSmall())
-      free(this->begin());
-  }
-
-  void clear() {
-    this->destroy_range(this->begin(), this->end());
-    this->Size = 0;
-  }
-
-  void resize(size_type N) {
-    if (N < this->size()) {
-      this->destroy_range(this->begin()+N, this->end());
-      this->set_size(N);
-    } else if (N > this->size()) {
-      if (this->capacity() < N)
-        this->grow(N);
-      for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
-        new (&*I) T();
-      this->set_size(N);
-    }
-  }
-
-  void resize(size_type N, const T &NV) {
-    if (N < this->size()) {
-      this->destroy_range(this->begin()+N, this->end());
-      this->set_size(N);
-    } else if (N > this->size()) {
-      if (this->capacity() < N)
-        this->grow(N);
-      std::uninitialized_fill(this->end(), this->begin()+N, NV);
-      this->set_size(N);
-    }
-  }
-
-  void reserve(size_type N) {
-    if (this->capacity() < N)
-      this->grow(N);
-  }
-
-  LLVM_NODISCARD T pop_back_val() {
-    T Result = ::std::move(this->back());
-    this->pop_back();
-    return Result;
-  }
-
-  void swap(SmallVectorImpl &RHS);
-
-  /// Add the specified range to the end of the SmallVector.
-  template <typename in_iter,
-            typename = typename std::enable_if<std::is_convertible<
-                typename std::iterator_traits<in_iter>::iterator_category,
-                std::input_iterator_tag>::value>::type>
-  void append(in_iter in_start, in_iter in_end) {
-    size_type NumInputs = std::distance(in_start, in_end);
-    // Grow allocated space if needed.
-    if (NumInputs > this->capacity() - this->size())
-      this->grow(this->size()+NumInputs);
-
-    // Copy the new elements over.
-    this->uninitialized_copy(in_start, in_end, this->end());
-    this->set_size(this->size() + NumInputs);
-  }
-
-  /// Add the specified range to the end of the SmallVector.
-  void append(size_type NumInputs, const T &Elt) {
-    // Grow allocated space if needed.
-    if (NumInputs > this->capacity() - this->size())
-      this->grow(this->size()+NumInputs);
-
-    // Copy the new elements over.
-    std::uninitialized_fill_n(this->end(), NumInputs, Elt);
-    this->set_size(this->size() + NumInputs);
-  }
-
-  void append(std::initializer_list<T> IL) {
-    append(IL.begin(), IL.end());
-  }
-
-  // FIXME: Consider assigning over existing elements, rather than clearing &
-  // re-initializing them - for all assign(...) variants.
-
-  void assign(size_type NumElts, const T &Elt) {
-    clear();
-    if (this->capacity() < NumElts)
-      this->grow(NumElts);
-    this->set_size(NumElts);
-    std::uninitialized_fill(this->begin(), this->end(), Elt);
-  }
-
-  template <typename in_iter,
-            typename = typename std::enable_if<std::is_convertible<
-                typename std::iterator_traits<in_iter>::iterator_category,
-                std::input_iterator_tag>::value>::type>
-  void assign(in_iter in_start, in_iter in_end) {
-    clear();
-    append(in_start, in_end);
-  }
-
-  void assign(std::initializer_list<T> IL) {
-    clear();
-    append(IL);
-  }
-
-  iterator erase(const_iterator CI) {
-    // Just cast away constness because this is a non-const member function.
-    iterator I = const_cast<iterator>(CI);
-
-    assert(I >= this->begin() && "Iterator to erase is out of bounds.");
-    assert(I < this->end() && "Erasing at past-the-end iterator.");
-
-    iterator N = I;
-    // Shift all elts down one.
-    std::move(I+1, this->end(), I);
-    // Drop the last elt.
-    this->pop_back();
-    return(N);
-  }
-
-  iterator erase(const_iterator CS, const_iterator CE) {
-    // Just cast away constness because this is a non-const member function.
-    iterator S = const_cast<iterator>(CS);
-    iterator E = const_cast<iterator>(CE);
-
-    assert(S >= this->begin() && "Range to erase is out of bounds.");
-    assert(S <= E && "Trying to erase invalid range.");
-    assert(E <= this->end() && "Trying to erase past the end.");
-
-    iterator N = S;
-    // Shift all elts down.
-    iterator I = std::move(E, this->end(), S);
-    // Drop the last elts.
-    this->destroy_range(I, this->end());
-    this->set_size(I - this->begin());
-    return(N);
-  }
-
-  iterator insert(iterator I, T &&Elt) {
-    if (I == this->end()) {  // Important special case for empty vector.
-      this->push_back(::std::move(Elt));
-      return this->end()-1;
-    }
-
-    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
-    assert(I <= this->end() && "Inserting past the end of the vector.");
-
-    if (this->size() >= this->capacity()) {
-      size_t EltNo = I-this->begin();
-      this->grow();
-      I = this->begin()+EltNo;
-    }
-
-    ::new ((void*) this->end()) T(::std::move(this->back()));
-    // Push everything else over.
-    std::move_backward(I, this->end()-1, this->end());
-    this->set_size(this->size() + 1);
-
-    // If we just moved the element we're inserting, be sure to update
-    // the reference.
-    T *EltPtr = &Elt;
-    if (I <= EltPtr && EltPtr < this->end())
-      ++EltPtr;
-
-    *I = ::std::move(*EltPtr);
-    return I;
-  }
-
-  iterator insert(iterator I, const T &Elt) {
-    if (I == this->end()) {  // Important special case for empty vector.
-      this->push_back(Elt);
-      return this->end()-1;
-    }
-
-    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
-    assert(I <= this->end() && "Inserting past the end of the vector.");
-
-    if (this->size() >= this->capacity()) {
-      size_t EltNo = I-this->begin();
-      this->grow();
-      I = this->begin()+EltNo;
-    }
-    ::new ((void*) this->end()) T(std::move(this->back()));
-    // Push everything else over.
-    std::move_backward(I, this->end()-1, this->end());
-    this->set_size(this->size() + 1);
-
-    // If we just moved the element we're inserting, be sure to update
-    // the reference.
-    const T *EltPtr = &Elt;
-    if (I <= EltPtr && EltPtr < this->end())
-      ++EltPtr;
-
-    *I = *EltPtr;
-    return I;
-  }
-
-  iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
-    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
-    size_t InsertElt = I - this->begin();
-
-    if (I == this->end()) {  // Important special case for empty vector.
-      append(NumToInsert, Elt);
-      return this->begin()+InsertElt;
-    }
-
-    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
-    assert(I <= this->end() && "Inserting past the end of the vector.");
-
-    // Ensure there is enough space.
-    reserve(this->size() + NumToInsert);
-
-    // Uninvalidate the iterator.
-    I = this->begin()+InsertElt;
-
-    // If there are more elements between the insertion point and the end of the
-    // range than there are being inserted, we can use a simple approach to
-    // insertion.  Since we already reserved space, we know that this won't
-    // reallocate the vector.
-    if (size_t(this->end()-I) >= NumToInsert) {
-      T *OldEnd = this->end();
-      append(std::move_iterator<iterator>(this->end() - NumToInsert),
-             std::move_iterator<iterator>(this->end()));
-
-      // Copy the existing elements that get replaced.
-      std::move_backward(I, OldEnd-NumToInsert, OldEnd);
-
-      std::fill_n(I, NumToInsert, Elt);
-      return I;
-    }
-
-    // Otherwise, we're inserting more elements than exist already, and we're
-    // not inserting at the end.
-
-    // Move over the elements that we're about to overwrite.
-    T *OldEnd = this->end();
-    this->set_size(this->size() + NumToInsert);
-    size_t NumOverwritten = OldEnd-I;
-    this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
-
-    // Replace the overwritten part.
-    std::fill_n(I, NumOverwritten, Elt);
-
-    // Insert the non-overwritten middle part.
-    std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
-    return I;
-  }
-
-  template <typename ItTy,
-            typename = typename std::enable_if<std::is_convertible<
-                typename std::iterator_traits<ItTy>::iterator_category,
-                std::input_iterator_tag>::value>::type>
-  iterator insert(iterator I, ItTy From, ItTy To) {
-    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
-    size_t InsertElt = I - this->begin();
-
-    if (I == this->end()) {  // Important special case for empty vector.
-      append(From, To);
-      return this->begin()+InsertElt;
-    }
-
-    assert(I >= this->begin() && "Insertion iterator is out of bounds.");
-    assert(I <= this->end() && "Inserting past the end of the vector.");
-
-    size_t NumToInsert = std::distance(From, To);
-
-    // Ensure there is enough space.
-    reserve(this->size() + NumToInsert);
-
-    // Uninvalidate the iterator.
-    I = this->begin()+InsertElt;
-
-    // If there are more elements between the insertion point and the end of the
-    // range than there are being inserted, we can use a simple approach to
-    // insertion.  Since we already reserved space, we know that this won't
-    // reallocate the vector.
-    if (size_t(this->end()-I) >= NumToInsert) {
-      T *OldEnd = this->end();
-      append(std::move_iterator<iterator>(this->end() - NumToInsert),
-             std::move_iterator<iterator>(this->end()));
-
-      // Copy the existing elements that get replaced.
-      std::move_backward(I, OldEnd-NumToInsert, OldEnd);
-
-      std::copy(From, To, I);
-      return I;
-    }
-
-    // Otherwise, we're inserting more elements than exist already, and we're
-    // not inserting at the end.
-
-    // Move over the elements that we're about to overwrite.
-    T *OldEnd = this->end();
-    this->set_size(this->size() + NumToInsert);
-    size_t NumOverwritten = OldEnd-I;
-    this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
-
-    // Replace the overwritten part.
-    for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
-      *J = *From;
-      ++J; ++From;
-    }
-
-    // Insert the non-overwritten middle part.
-    this->uninitialized_copy(From, To, OldEnd);
-    return I;
-  }
-
-  void insert(iterator I, std::initializer_list<T> IL) {
-    insert(I, IL.begin(), IL.end());
-  }
-
-  template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) {
-    if (LLVM_UNLIKELY(this->size() >= this->capacity()))
-      this->grow();
-    ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
-    this->set_size(this->size() + 1);
-  }
-
-  SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
-
-  SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
-
-  bool operator==(const SmallVectorImpl &RHS) const {
-    if (this->size() != RHS.size()) return false;
-    return std::equal(this->begin(), this->end(), RHS.begin());
-  }
-  bool operator!=(const SmallVectorImpl &RHS) const {
-    return !(*this == RHS);
-  }
-
-  bool operator<(const SmallVectorImpl &RHS) const {
-    return std::lexicographical_compare(this->begin(), this->end(),
-                                        RHS.begin(), RHS.end());
-  }
-};
-
-template <typename T>
-void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
-  if (this == &RHS) return;
-
-  // We can only avoid copying elements if neither vector is small.
-  if (!this->isSmall() && !RHS.isSmall()) {
-    std::swap(this->BeginX, RHS.BeginX);
-    std::swap(this->Size, RHS.Size);
-    std::swap(this->Capacity, RHS.Capacity);
-    return;
-  }
-  if (RHS.size() > this->capacity())
-    this->grow(RHS.size());
-  if (this->size() > RHS.capacity())
-    RHS.grow(this->size());
-
-  // Swap the shared elements.
-  size_t NumShared = this->size();
-  if (NumShared > RHS.size()) NumShared = RHS.size();
-  for (size_type i = 0; i != NumShared; ++i)
-    std::swap((*this)[i], RHS[i]);
-
-  // Copy over the extra elts.
-  if (this->size() > RHS.size()) {
-    size_t EltDiff = this->size() - RHS.size();
-    this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
-    RHS.set_size(RHS.size() + EltDiff);
-    this->destroy_range(this->begin()+NumShared, this->end());
-    this->set_size(NumShared);
-  } else if (RHS.size() > this->size()) {
-    size_t EltDiff = RHS.size() - this->size();
-    this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
-    this->set_size(this->size() + EltDiff);
-    this->destroy_range(RHS.begin()+NumShared, RHS.end());
-    RHS.set_size(NumShared);
-  }
-}
-
-template <typename T>
-SmallVectorImpl<T> &SmallVectorImpl<T>::
-  operator=(const SmallVectorImpl<T> &RHS) {
-  // Avoid self-assignment.
-  if (this == &RHS) return *this;
-
-  // If we already have sufficient space, assign the common elements, then
-  // destroy any excess.
-  size_t RHSSize = RHS.size();
-  size_t CurSize = this->size();
-  if (CurSize >= RHSSize) {
-    // Assign common elements.
-    iterator NewEnd;
-    if (RHSSize)
-      NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
-    else
-      NewEnd = this->begin();
-
-    // Destroy excess elements.
-    this->destroy_range(NewEnd, this->end());
-
-    // Trim.
-    this->set_size(RHSSize);
-    return *this;
-  }
-
-  // If we have to grow to have enough elements, destroy the current elements.
-  // This allows us to avoid copying them during the grow.
-  // FIXME: don't do this if they're efficiently moveable.
-  if (this->capacity() < RHSSize) {
-    // Destroy current elements.
-    this->destroy_range(this->begin(), this->end());
-    this->set_size(0);
-    CurSize = 0;
-    this->grow(RHSSize);
-  } else if (CurSize) {
-    // Otherwise, use assignment for the already-constructed elements.
-    std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
-  }
-
-  // Copy construct the new elements in place.
-  this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
-                           this->begin()+CurSize);
-
-  // Set end.
-  this->set_size(RHSSize);
-  return *this;
-}
-
-template <typename T>
-SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
-  // Avoid self-assignment.
-  if (this == &RHS) return *this;
-
-  // If the RHS isn't small, clear this vector and then steal its buffer.
-  if (!RHS.isSmall()) {
-    this->destroy_range(this->begin(), this->end());
-    if (!this->isSmall()) free(this->begin());
-    this->BeginX = RHS.BeginX;
-    this->Size = RHS.Size;
-    this->Capacity = RHS.Capacity;
-    RHS.resetToSmall();
-    return *this;
-  }
-
-  // If we already have sufficient space, assign the common elements, then
-  // destroy any excess.
-  size_t RHSSize = RHS.size();
-  size_t CurSize = this->size();
-  if (CurSize >= RHSSize) {
-    // Assign common elements.
-    iterator NewEnd = this->begin();
-    if (RHSSize)
-      NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
-
-    // Destroy excess elements and trim the bounds.
-    this->destroy_range(NewEnd, this->end());
-    this->set_size(RHSSize);
-
-    // Clear the RHS.
-    RHS.clear();
-
-    return *this;
-  }
-
-  // If we have to grow to have enough elements, destroy the current elements.
-  // This allows us to avoid copying them during the grow.
-  // FIXME: this may not actually make any sense if we can efficiently move
-  // elements.
-  if (this->capacity() < RHSSize) {
-    // Destroy current elements.
-    this->destroy_range(this->begin(), this->end());
-    this->set_size(0);
-    CurSize = 0;
-    this->grow(RHSSize);
-  } else if (CurSize) {
-    // Otherwise, use assignment for the already-constructed elements.
-    std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
-  }
-
-  // Move-construct the new elements in place.
-  this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
-                           this->begin()+CurSize);
-
-  // Set end.
-  this->set_size(RHSSize);
-
-  RHS.clear();
-  return *this;
-}
-
-/// Storage for the SmallVector elements.  This is specialized for the N=0 case
-/// to avoid allocating unnecessary storage.
-template <typename T, unsigned N>
-struct SmallVectorStorage {
-  AlignedCharArrayUnion<T> InlineElts[N];
-};
-
-/// We need the storage to be properly aligned even for small-size of 0 so that
-/// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is
-/// well-defined.
-template <typename T> struct alignas(alignof(T)) SmallVectorStorage<T, 0> {};
-
-/// This is a 'vector' (really, a variable-sized array), optimized
-/// for the case when the array is small.  It contains some number of elements
-/// in-place, which allows it to avoid heap allocation when the actual number of
-/// elements is below that threshold.  This allows normal "small" cases to be
-/// fast without losing generality for large inputs.
-///
-/// Note that this does not attempt to be exception safe.
-///
-template <typename T, unsigned N>
-class SmallVector : public SmallVectorImpl<T>, SmallVectorStorage<T, N> {
-public:
-  SmallVector() : SmallVectorImpl<T>(N) {}
-
-  ~SmallVector() {
-    // Destroy the constructed elements in the vector.
-    this->destroy_range(this->begin(), this->end());
-  }
-
-  explicit SmallVector(size_t Size, const T &Value = T())
-    : SmallVectorImpl<T>(N) {
-    this->assign(Size, Value);
-  }
-
-  template <typename ItTy,
-            typename = typename std::enable_if<std::is_convertible<
-                typename std::iterator_traits<ItTy>::iterator_category,
-                std::input_iterator_tag>::value>::type>
-  SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
-    this->append(S, E);
-  }
-
-  template <typename RangeTy>
-  explicit SmallVector(const iterator_range<RangeTy> &R)
-      : SmallVectorImpl<T>(N) {
-    this->append(R.begin(), R.end());
-  }
-
-  SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
-    this->assign(IL);
-  }
-
-  SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
-    if (!RHS.empty())
-      SmallVectorImpl<T>::operator=(RHS);
-  }
-
-  const SmallVector &operator=(const SmallVector &RHS) {
-    SmallVectorImpl<T>::operator=(RHS);
-    return *this;
-  }
-
-  SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) {
-    if (!RHS.empty())
-      SmallVectorImpl<T>::operator=(::std::move(RHS));
-  }
-
-  SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
-    if (!RHS.empty())
-      SmallVectorImpl<T>::operator=(::std::move(RHS));
-  }
-
-  const SmallVector &operator=(SmallVector &&RHS) {
-    SmallVectorImpl<T>::operator=(::std::move(RHS));
-    return *this;
-  }
-
-  const SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
-    SmallVectorImpl<T>::operator=(::std::move(RHS));
-    return *this;
-  }
-
-  const SmallVector &operator=(std::initializer_list<T> IL) {
-    this->assign(IL);
-    return *this;
-  }
-};
-
-template <typename T, unsigned N>
-inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
-  return X.capacity_in_bytes();
-}
-
-} // end namespace wpi
-
-namespace std {
-
-  /// Implement std::swap in terms of SmallVector swap.
-  template<typename T>
-  inline void
-  swap(wpi::SmallVectorImpl<T> &LHS, wpi::SmallVectorImpl<T> &RHS) {
-    LHS.swap(RHS);
-  }
-
-  /// Implement std::swap in terms of SmallVector swap.
-  template<typename T, unsigned N>
-  inline void
-  swap(wpi::SmallVector<T, N> &LHS, wpi::SmallVector<T, N> &RHS) {
-    LHS.swap(RHS);
-  }
-
-} // end namespace std
-
-#endif // LLVM_ADT_SMALLVECTOR_H
diff --git a/wpiutil/src/main/native/include/wpi/SocketError.h b/wpiutil/src/main/native/include/wpi/SocketError.h
deleted file mode 100644
index b893ac6..0000000
--- a/wpiutil/src/main/native/include/wpi/SocketError.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_SOCKETERROR_H_
-#define WPIUTIL_WPI_SOCKETERROR_H_
-
-#include <string>
-
-namespace wpi {
-
-int SocketErrno();
-
-std::string SocketStrerror(int code);
-
-inline std::string SocketStrerror() {
-  return SocketStrerror(SocketErrno());
-}
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_SOCKETERROR_H_
diff --git a/wpiutil/src/main/native/include/wpi/SpanExtras.h b/wpiutil/src/main/native/include/wpi/SpanExtras.h
index 41e4014..aa7b9ab 100644
--- a/wpiutil/src/main/native/include/wpi/SpanExtras.h
+++ b/wpiutil/src/main/native/include/wpi/SpanExtras.h
@@ -5,21 +5,22 @@
 #pragma once
 
 #include <cassert>
-
-#include "wpi/span.h"
+#include <span>
 
 namespace wpi {
 
 /// Drop the first \p N elements of the array.
 template <typename T>
-constexpr span<T> drop_front(span<T> in, typename span<T>::size_type n = 1) {
+constexpr std::span<T> drop_front(std::span<T> in,
+                                  typename std::span<T>::size_type n = 1) {
   assert(in.size() >= n && "Dropping more elements than exist");
   return in.subspan(n, in.size() - n);
 }
 
 /// Drop the last \p N elements of the array.
 template <typename T>
-constexpr span<T> drop_back(span<T> in, typename span<T>::size_type n = 1) {
+constexpr std::span<T> drop_back(std::span<T> in,
+                                 typename std::span<T>::size_type n = 1) {
   assert(in.size() >= n && "Dropping more elements than exist");
   return in.subspan(0, in.size() - n);
 }
diff --git a/wpiutil/src/main/native/include/wpi/SwapByteOrder.h b/wpiutil/src/main/native/include/wpi/SwapByteOrder.h
deleted file mode 100644
index 50ad832..0000000
--- a/wpiutil/src/main/native/include/wpi/SwapByteOrder.h
+++ /dev/null
@@ -1,127 +0,0 @@
-//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares generic and optimized functions to swap the byte order of
-// an integral type.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_SWAPBYTEORDER_H
-#define WPIUTIL_WPI_SWAPBYTEORDER_H
-
-#include "wpi/Compiler.h"
-#include <cstddef>
-#include <stdint.h>
-#if defined(_MSC_VER) && !defined(_DEBUG)
-#include <stdlib.h>
-#endif
-
-namespace wpi {
-namespace sys {
-
-/// SwapByteOrder_16 - This function returns a byte-swapped representation of
-/// the 16-bit argument.
-inline uint16_t SwapByteOrder_16(uint16_t value) {
-#if defined(_MSC_VER) && !defined(_DEBUG)
-  // The DLL version of the runtime lacks these functions (bug!?), but in a
-  // release build they're replaced with BSWAP instructions anyway.
-  return _byteswap_ushort(value);
-#else
-  uint16_t Hi = value << 8;
-  uint16_t Lo = value >> 8;
-  return Hi | Lo;
-#endif
-}
-
-/// SwapByteOrder_32 - This function returns a byte-swapped representation of
-/// the 32-bit argument.
-inline uint32_t SwapByteOrder_32(uint32_t value) {
-#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
-  return __builtin_bswap32(value);
-#elif defined(_MSC_VER) && !defined(_DEBUG)
-  return _byteswap_ulong(value);
-#else
-  uint32_t Byte0 = value & 0x000000FF;
-  uint32_t Byte1 = value & 0x0000FF00;
-  uint32_t Byte2 = value & 0x00FF0000;
-  uint32_t Byte3 = value & 0xFF000000;
-  return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
-#endif
-}
-
-/// SwapByteOrder_64 - This function returns a byte-swapped representation of
-/// the 64-bit argument.
-inline uint64_t SwapByteOrder_64(uint64_t value) {
-#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
-  return __builtin_bswap64(value);
-#elif defined(_MSC_VER) && !defined(_DEBUG)
-  return _byteswap_uint64(value);
-#else
-  uint64_t Hi = SwapByteOrder_32(uint32_t(value));
-  uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32));
-  return (Hi << 32) | Lo;
-#endif
-}
-
-inline unsigned char  getSwappedBytes(unsigned char C) { return C; }
-inline   signed char  getSwappedBytes(signed char C) { return C; }
-inline          char  getSwappedBytes(char C) { return C; }
-
-inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); }
-inline   signed short getSwappedBytes(  signed short C) { return SwapByteOrder_16(C); }
-
-inline unsigned int   getSwappedBytes(unsigned int   C) { return SwapByteOrder_32(C); }
-inline   signed int   getSwappedBytes(  signed int   C) { return SwapByteOrder_32(C); }
-
-#if __LONG_MAX__ == __INT_MAX__
-inline unsigned long  getSwappedBytes(unsigned long  C) { return SwapByteOrder_32(C); }
-inline   signed long  getSwappedBytes(  signed long  C) { return SwapByteOrder_32(C); }
-#elif __LONG_MAX__ == __LONG_LONG_MAX__
-inline unsigned long  getSwappedBytes(unsigned long  C) { return SwapByteOrder_64(C); }
-inline   signed long  getSwappedBytes(  signed long  C) { return SwapByteOrder_64(C); }
-#else
-#error "Unknown long size!"
-#endif
-
-inline unsigned long long getSwappedBytes(unsigned long long C) {
-  return SwapByteOrder_64(C);
-}
-inline signed long long getSwappedBytes(signed long long C) {
-  return SwapByteOrder_64(C);
-}
-
-inline float getSwappedBytes(float C) {
-  union {
-    uint32_t i;
-    float f;
-  } in, out;
-  in.f = C;
-  out.i = SwapByteOrder_32(in.i);
-  return out.f;
-}
-
-inline double getSwappedBytes(double C) {
-  union {
-    uint64_t i;
-    double d;
-  } in, out;
-  in.d = C;
-  out.i = SwapByteOrder_64(in.i);
-  return out.d;
-}
-
-template<typename T>
-inline void swapByteOrder(T &Value) {
-  Value = getSwappedBytes(Value);
-}
-
-} // end namespace sys
-} // end namespace wpi
-
-#endif
diff --git a/wpiutil/src/main/native/include/wpi/SymbolExports.h b/wpiutil/src/main/native/include/wpi/SymbolExports.h
index 4e84825..9ffc936 100644
--- a/wpiutil/src/main/native/include/wpi/SymbolExports.h
+++ b/wpiutil/src/main/native/include/wpi/SymbolExports.h
@@ -14,10 +14,179 @@
 #define WPILIB_DLLEXPORT __declspec(dllexport)
 #endif
 
+#elif defined(WPILIB_IMPORTS)
+
+#ifdef __GNUC__
+#define WPILIB_DLLEXPORT __attribute__((dllimport))
+#else
+#define WPILIB_DLLEXPORT __declspec(dllimport)
+#endif
+
 #else
 #define WPILIB_DLLEXPORT
 #endif
 
-#else
+#else  // _WIN32
+
+#ifdef WPILIB_EXPORTS
 #define WPILIB_DLLEXPORT __attribute__((visibility("default")))
+#else
+#define WPILIB_DLLEXPORT
 #endif
+
+#endif  // _WIN32
+
+// Synopsis
+//
+// This header provides macros for using FOO_EXPORT macros with explicit
+// template instantiation declarations and definitions.
+// Generally, the FOO_EXPORT macros are used at declarations,
+// and GCC requires them to be used at explicit instantiation declarations,
+// but MSVC requires __declspec(dllexport) to be used at the explicit
+// instantiation definitions instead.
+
+// Usage
+//
+// In a header file, write:
+//
+//   extern template class EXPORT_TEMPLATE_DECLARE(FOO_EXPORT) foo<bar>;
+//
+// In a source file, write:
+//
+//   template class EXPORT_TEMPLATE_DEFINE(FOO_EXPORT) foo<bar>;
+
+// Implementation notes
+//
+// The implementation of this header uses some subtle macro semantics to
+// detect what the provided FOO_EXPORT value was defined as and then
+// to dispatch to appropriate macro definitions.  Unfortunately,
+// MSVC's C preprocessor is rather non-compliant and requires special
+// care to make it work.
+//
+// Issue 1.
+//
+//   #define F(x)
+//   F()
+//
+// MSVC emits warning C4003 ("not enough actual parameters for macro
+// 'F'), even though it's a valid macro invocation.  This affects the
+// macros below that take just an "export" parameter, because export
+// may be empty.
+//
+// As a workaround, we can add a dummy parameter and arguments:
+//
+//   #define F(x,_)
+//   F(,)
+//
+// Issue 2.
+//
+//   #define F(x) G##x
+//   #define Gj() ok
+//   F(j())
+//
+// The correct replacement for "F(j())" is "ok", but MSVC replaces it
+// with "Gj()".  As a workaround, we can pass the result to an
+// identity macro to force MSVC to look for replacements again.  (This
+// is why EXPORT_TEMPLATE_STYLE_3 exists.)
+
+#define EXPORT_TEMPLATE_DECLARE(export) \
+  EXPORT_TEMPLATE_INVOKE(DECLARE, EXPORT_TEMPLATE_STYLE(export, ), export)
+#define EXPORT_TEMPLATE_DEFINE(export) \
+  EXPORT_TEMPLATE_INVOKE(DEFINE, EXPORT_TEMPLATE_STYLE(export, ), export)
+
+// INVOKE is an internal helper macro to perform parameter replacements
+// and token pasting to chain invoke another macro.  E.g.,
+//     EXPORT_TEMPLATE_INVOKE(DECLARE, DEFAULT, FOO_EXPORT)
+// will export to call
+//     EXPORT_TEMPLATE_DECLARE_DEFAULT(FOO_EXPORT, )
+// (but with FOO_EXPORT expanded too).
+#define EXPORT_TEMPLATE_INVOKE(which, style, export) \
+  EXPORT_TEMPLATE_INVOKE_2(which, style, export)
+#define EXPORT_TEMPLATE_INVOKE_2(which, style, export) \
+  EXPORT_TEMPLATE_##which##_##style(export, )
+
+// Default style is to apply the FOO_EXPORT macro at declaration sites.
+#define EXPORT_TEMPLATE_DECLARE_DEFAULT(export, _) export
+#define EXPORT_TEMPLATE_DEFINE_DEFAULT(export, _)
+
+// The "MSVC hack" style is used when FOO_EXPORT is defined
+// as __declspec(dllexport), which MSVC requires to be used at
+// definition sites instead.
+#define EXPORT_TEMPLATE_DECLARE_MSVC_HACK(export, _)
+#define EXPORT_TEMPLATE_DEFINE_MSVC_HACK(export, _) export
+
+// EXPORT_TEMPLATE_STYLE is an internal helper macro that identifies which
+// export style needs to be used for the provided FOO_EXPORT macro definition.
+// "", "__attribute__(...)", and "__declspec(dllimport)" are mapped
+// to "DEFAULT"; while "__declspec(dllexport)" is mapped to "MSVC_HACK".
+//
+// It's implemented with token pasting to transform the __attribute__ and
+// __declspec annotations into macro invocations.  E.g., if FOO_EXPORT is
+// defined as "__declspec(dllimport)", it undergoes the following sequence of
+// macro substitutions:
+//     EXPORT_TEMPLATE_STYLE(FOO_EXPORT, )
+//     EXPORT_TEMPLATE_STYLE_2(__declspec(dllimport), )
+//     EXPORT_TEMPLATE_STYLE_3(EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport))
+//     EXPORT_TEMPLATE_STYLE_MATCH__declspec(dllimport)
+//     EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport
+//     DEFAULT
+#define EXPORT_TEMPLATE_STYLE(export, _) EXPORT_TEMPLATE_STYLE_2(export, )
+#define EXPORT_TEMPLATE_STYLE_2(export, _) \
+  EXPORT_TEMPLATE_STYLE_3(                 \
+      EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA##export)
+#define EXPORT_TEMPLATE_STYLE_3(style) style
+
+// Internal helper macros for EXPORT_TEMPLATE_STYLE.
+//
+// XXX: C++ reserves all identifiers containing "__" for the implementation,
+// but "__attribute__" and "__declspec" already contain "__" and the token-paste
+// operator can only add characters; not remove them.  To minimize the risk of
+// conflict with implementations, we include "foj3FJo5StF0OvIzl7oMxA" (a random
+// 128-bit string, encoded in Base64) in the macro name.
+#define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA DEFAULT
+#define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__attribute__(...) \
+  DEFAULT
+#define EXPORT_TEMPLATE_STYLE_MATCH_foj3FJo5StF0OvIzl7oMxA__declspec(arg) \
+  EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_##arg
+
+// Internal helper macros for EXPORT_TEMPLATE_STYLE.
+#define EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport MSVC_HACK
+#define EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport DEFAULT
+
+// Sanity checks.
+//
+// EXPORT_TEMPLATE_TEST uses the same macro invocation pattern as
+// EXPORT_TEMPLATE_DECLARE and EXPORT_TEMPLATE_DEFINE do to check that they're
+// working correctly.  When they're working correctly, the sequence of macro
+// replacements should go something like:
+//
+//     EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
+//
+//     static_assert(EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT,
+//         EXPORT_TEMPLATE_STYLE(__declspec(dllimport), ),
+//         __declspec(dllimport)), "__declspec(dllimport)");
+//
+//     static_assert(EXPORT_TEMPLATE_INVOKE(TEST_DEFAULT,
+//         DEFAULT, __declspec(dllimport)), "__declspec(dllimport)");
+//
+//     static_assert(EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(
+//         __declspec(dllimport)), "__declspec(dllimport)");
+//
+//     static_assert(true, "__declspec(dllimport)");
+//
+// When they're not working correctly, a syntax error should occur instead.
+#define EXPORT_TEMPLATE_TEST(want, export)                                 \
+  static_assert(EXPORT_TEMPLATE_INVOKE(                                    \
+                    TEST_##want, EXPORT_TEMPLATE_STYLE(export, ), export), \
+                #export)
+#define EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT(...) true
+#define EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK(...) true
+
+EXPORT_TEMPLATE_TEST(DEFAULT, );
+EXPORT_TEMPLATE_TEST(DEFAULT, __attribute__((visibility("default"))));
+EXPORT_TEMPLATE_TEST(MSVC_HACK, __declspec(dllexport));
+EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
+
+#undef EXPORT_TEMPLATE_TEST
+#undef EXPORT_TEMPLATE_TEST_DEFAULT_DEFAULT
+#undef EXPORT_TEMPLATE_TEST_MSVC_HACK_MSVC_HACK
diff --git a/wpiutil/src/main/native/include/wpi/Synchronization.h b/wpiutil/src/main/native/include/wpi/Synchronization.h
index 57fc4ee..4ac3c8c 100644
--- a/wpiutil/src/main/native/include/wpi/Synchronization.h
+++ b/wpiutil/src/main/native/include/wpi/Synchronization.h
@@ -4,12 +4,11 @@
 
 #pragma once
 
+#ifdef __cplusplus
 #include <climits>  // NOLINT
 
-#ifdef __cplusplus
 #include <initializer_list>
-
-#include "wpi/span.h"
+#include <span>
 #endif
 
 /**
@@ -43,8 +42,8 @@
 constexpr int kHandleTypeSemaphore = 2;
 constexpr int kHandleTypeCSBase = 3;
 constexpr int kHandleTypeNTBase = 16;
-constexpr int kHandleTypeHALBase = 32;
-constexpr int kHandleTypeUserBase = 64;
+constexpr int kHandleTypeHALBase = 48;
+constexpr int kHandleTypeUserBase = 80;
 /** @} */
 
 /**
@@ -149,8 +148,8 @@
  *        least the size of the handles input array
  * @return array of signaled handles (points into signaled array)
  */
-wpi::span<WPI_Handle> WaitForObjects(wpi::span<const WPI_Handle> handles,
-                                     wpi::span<WPI_Handle> signaled);
+std::span<WPI_Handle> WaitForObjects(std::span<const WPI_Handle> handles,
+                                     std::span<WPI_Handle> signaled);
 
 /**
  * Waits for one or more handles to be signaled.
@@ -163,9 +162,9 @@
  *        least the size of the handles input array
  * @return array of signaled handles (points into signaled array)
  */
-inline wpi::span<WPI_Handle> WaitForObjects(
-    std::initializer_list<WPI_Handle> handles, wpi::span<WPI_Handle> signaled) {
-  return WaitForObjects(wpi::span{handles.begin(), handles.size()}, signaled);
+inline std::span<WPI_Handle> WaitForObjects(
+    std::initializer_list<WPI_Handle> handles, std::span<WPI_Handle> signaled) {
+  return WaitForObjects(std::span{handles.begin(), handles.size()}, signaled);
 }
 
 /**
@@ -182,8 +181,8 @@
  *        handle being signaled; set to false otherwise (output)
  * @return array of signaled handles (points into signaled array)
  */
-wpi::span<WPI_Handle> WaitForObjects(wpi::span<const WPI_Handle> handles,
-                                     wpi::span<WPI_Handle> signaled,
+std::span<WPI_Handle> WaitForObjects(std::span<const WPI_Handle> handles,
+                                     std::span<WPI_Handle> signaled,
                                      double timeout, bool* timedOut);
 /**
  * Waits for one or more handles to be signaled, with timeout.
@@ -199,10 +198,10 @@
  *        handle being signaled; set to false otherwise (output)
  * @return array of signaled handles (points into signaled array)
  */
-inline wpi::span<WPI_Handle> WaitForObjects(
-    std::initializer_list<WPI_Handle> handles, wpi::span<WPI_Handle> signaled,
+inline std::span<WPI_Handle> WaitForObjects(
+    std::initializer_list<WPI_Handle> handles, std::span<WPI_Handle> signaled,
     double timeout, bool* timedOut) {
-  return WaitForObjects(wpi::span{handles.begin(), handles.size()}, signaled,
+  return WaitForObjects(std::span{handles.begin(), handles.size()}, signaled,
                         timeout, timedOut);
 }
 
diff --git a/wpiutil/src/main/native/include/wpi/TCPAcceptor.h b/wpiutil/src/main/native/include/wpi/TCPAcceptor.h
deleted file mode 100644
index 083897a..0000000
--- a/wpiutil/src/main/native/include/wpi/TCPAcceptor.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-   TCPAcceptor.h
-
-   TCPAcceptor class interface. TCPAcceptor provides methods to passively
-   establish TCP/IP connections with clients.
-
-   ------------------------------------------
-
-   Copyright (c) 2013 [Vic Hargrave - http://vichargrave.com]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-#ifndef WPIUTIL_WPI_TCPACCEPTOR_H_
-#define WPIUTIL_WPI_TCPACCEPTOR_H_
-
-#include <atomic>
-#include <memory>
-#include <string>
-#include <string_view>
-
-#include "wpi/NetworkAcceptor.h"
-#include "wpi/TCPStream.h"
-
-namespace wpi {
-
-class Logger;
-
-class TCPAcceptor : public NetworkAcceptor {
-  int m_lsd;
-  int m_port;
-  std::string m_address;
-  bool m_listening;
-  std::atomic_bool m_shutdown;
-  Logger& m_logger;
-
- public:
-  TCPAcceptor(int port, std::string_view address, Logger& logger);
-  ~TCPAcceptor() override;
-
-  int start() override;
-  void shutdown() final;
-  std::unique_ptr<NetworkStream> accept() override;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_TCPACCEPTOR_H_
diff --git a/wpiutil/src/main/native/include/wpi/TCPConnector.h b/wpiutil/src/main/native/include/wpi/TCPConnector.h
deleted file mode 100644
index 63e8906..0000000
--- a/wpiutil/src/main/native/include/wpi/TCPConnector.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-   TCPConnector.h
-
-   TCPConnector class interface. TCPConnector provides methods to actively
-   establish TCP/IP connections with a server.
-
-   ------------------------------------------
-
-   Copyright (c) 2013 [Vic Hargrave - http://vichargrave.com]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License
-*/
-
-#ifndef WPIUTIL_WPI_TCPCONNECTOR_H_
-#define WPIUTIL_WPI_TCPCONNECTOR_H_
-
-#include <memory>
-#include <utility>
-
-#include "wpi/NetworkStream.h"
-#include "wpi/span.h"
-
-namespace wpi {
-
-class Logger;
-
-class TCPConnector {
- public:
-  static std::unique_ptr<NetworkStream> connect(const char* server, int port,
-                                                Logger& logger,
-                                                int timeout = 0);
-  static std::unique_ptr<NetworkStream> connect_parallel(
-      span<const std::pair<const char*, int>> servers, Logger& logger,
-      int timeout = 0);
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_TCPCONNECTOR_H_
diff --git a/wpiutil/src/main/native/include/wpi/TCPStream.h b/wpiutil/src/main/native/include/wpi/TCPStream.h
deleted file mode 100644
index 2d54300..0000000
--- a/wpiutil/src/main/native/include/wpi/TCPStream.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-   TCPStream.h
-
-   TCPStream class interface. TCPStream provides methods to transfer
-   data between peers over a TCP/IP connection.
-
-   ------------------------------------------
-
-   Copyright (c) 2013 [Vic Hargrave - http://vichargrave.com]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-#ifndef WPIUTIL_WPI_TCPSTREAM_H_
-#define WPIUTIL_WPI_TCPSTREAM_H_
-
-#include <cstddef>
-#include <string>
-#include <string_view>
-
-#include "wpi/NetworkStream.h"
-
-struct sockaddr_in;
-
-namespace wpi {
-
-class TCPStream : public NetworkStream {
-  int m_sd;
-  std::string m_peerIP;
-  int m_peerPort;
-  bool m_blocking;
-
- public:
-  friend class TCPAcceptor;
-  friend class TCPConnector;
-
-  ~TCPStream() override;
-
-  size_t send(const char* buffer, size_t len, Error* err) override;
-  size_t receive(char* buffer, size_t len, Error* err,
-                 int timeout = 0) override;
-  void close() final;
-
-  std::string_view getPeerIP() const override;
-  int getPeerPort() const override;
-  void setNoDelay() override;
-  bool setBlocking(bool enabled) override;
-  int getNativeHandle() const override;
-
-  TCPStream(const TCPStream& stream) = delete;
-  TCPStream& operator=(const TCPStream&) = delete;
-
- private:
-  bool WaitForReadEvent(int timeout);
-
-  TCPStream(int sd, sockaddr_in* address);
-  TCPStream() = delete;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_TCPSTREAM_H_
diff --git a/wpiutil/src/main/native/include/wpi/UDPClient.h b/wpiutil/src/main/native/include/wpi/UDPClient.h
deleted file mode 100644
index fd2e30b..0000000
--- a/wpiutil/src/main/native/include/wpi/UDPClient.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UDPCLIENT_H_
-#define WPIUTIL_WPI_UDPCLIENT_H_
-
-#include <string>
-#include <string_view>
-
-#include "wpi/SmallVector.h"
-#include "wpi/mutex.h"
-#include "wpi/span.h"
-
-namespace wpi {
-
-class Logger;
-
-class UDPClient {
-  int m_lsd;
-  int m_port;
-  std::string m_address;
-  Logger& m_logger;
-
- public:
-  explicit UDPClient(Logger& logger);
-  UDPClient(std::string_view address, Logger& logger);
-  UDPClient(const UDPClient& other) = delete;
-  UDPClient(UDPClient&& other);
-  ~UDPClient();
-
-  UDPClient& operator=(const UDPClient& other) = delete;
-  UDPClient& operator=(UDPClient&& other);
-
-  int start();
-  int start(int port);
-  void shutdown();
-  // The passed in address MUST be a resolved IP address.
-  int send(span<const uint8_t> data, std::string_view server, int port);
-  int send(std::string_view data, std::string_view server, int port);
-  int receive(uint8_t* data_received, int receive_len);
-  int receive(uint8_t* data_received, int receive_len,
-              SmallVectorImpl<char>* addr_received, int* port_received);
-  int set_timeout(double timeout);
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_UDPCLIENT_H_
diff --git a/wpiutil/src/main/native/include/wpi/UrlParser.h b/wpiutil/src/main/native/include/wpi/UrlParser.h
deleted file mode 100644
index 1932c3e..0000000
--- a/wpiutil/src/main/native/include/wpi/UrlParser.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_URLPARSER_H_
-#define WPIUTIL_WPI_URLPARSER_H_
-
-#include <string_view>
-
-#include "wpi/StringExtras.h"
-#include "wpi/http_parser.h"
-
-namespace wpi {
-
-/**
- * Parses a URL into its constiuent components.
- * `schema://userinfo@host:port/the/path?query#fragment`
- */
-class UrlParser {
- public:
-  /**
-   * Parse a URL.
-   * @param in input
-   * @param isConnect
-   */
-  UrlParser(std::string_view in, bool isConnect) {
-    m_data = in;
-    http_parser_url_init(&m_url);
-    m_error = http_parser_parse_url(in.data(), in.size(), isConnect, &m_url);
-  }
-
-  /**
-   * Determine if the URL is valid (e.g. the parse was successful).
-   */
-  bool IsValid() const { return !m_error; }
-
-  bool HasSchema() const { return (m_url.field_set & (1 << UF_SCHEMA)) != 0; }
-
-  bool HasHost() const { return (m_url.field_set & (1 << UF_HOST)) != 0; }
-
-  bool HasPort() const { return (m_url.field_set & (1 << UF_PORT)) != 0; }
-
-  bool HasPath() const { return (m_url.field_set & (1 << UF_PATH)) != 0; }
-
-  bool HasQuery() const { return (m_url.field_set & (1 << UF_QUERY)) != 0; }
-
-  bool HasFragment() const {
-    return (m_url.field_set & (1 << UF_FRAGMENT)) != 0;
-  }
-
-  bool HasUserInfo() const {
-    return (m_url.field_set & (1 << UF_USERINFO)) != 0;
-  }
-
-  std::string_view GetSchema() const {
-    return wpi::substr(m_data, m_url.field_data[UF_SCHEMA].off,
-                       m_url.field_data[UF_SCHEMA].len);
-  }
-
-  std::string_view GetHost() const {
-    return wpi::substr(m_data, m_url.field_data[UF_HOST].off,
-                       m_url.field_data[UF_HOST].len);
-  }
-
-  unsigned int GetPort() const { return m_url.port; }
-
-  std::string_view GetPath() const {
-    return wpi::substr(m_data, m_url.field_data[UF_PATH].off,
-                       m_url.field_data[UF_PATH].len);
-  }
-
-  std::string_view GetQuery() const {
-    return wpi::substr(m_data, m_url.field_data[UF_QUERY].off,
-                       m_url.field_data[UF_QUERY].len);
-  }
-
-  std::string_view GetFragment() const {
-    return wpi::substr(m_data, m_url.field_data[UF_FRAGMENT].off,
-                       m_url.field_data[UF_FRAGMENT].len);
-  }
-
-  std::string_view GetUserInfo() const {
-    return wpi::substr(m_data, m_url.field_data[UF_USERINFO].off,
-                       m_url.field_data[UF_USERINFO].len);
-  }
-
- private:
-  bool m_error;
-  std::string_view m_data;
-  http_parser_url m_url;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_URLPARSER_H_
diff --git a/wpiutil/src/main/native/include/wpi/WebSocket.h b/wpiutil/src/main/native/include/wpi/WebSocket.h
deleted file mode 100644
index fc2ae4a..0000000
--- a/wpiutil/src/main/native/include/wpi/WebSocket.h
+++ /dev/null
@@ -1,477 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_WEBSOCKET_H_
-#define WPIUTIL_WPI_WEBSOCKET_H_
-
-#include <stdint.h>
-
-#include <functional>
-#include <initializer_list>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/SmallVector.h"
-#include "wpi/span.h"
-#include "wpi/uv/Buffer.h"
-#include "wpi/uv/Error.h"
-#include "wpi/uv/Timer.h"
-
-namespace wpi {
-
-namespace uv {
-class Stream;
-}  // namespace uv
-
-/**
- * RFC 6455 compliant WebSocket client and server implementation.
- */
-class WebSocket : public std::enable_shared_from_this<WebSocket> {
-  struct private_init {};
-
-  static constexpr uint8_t kOpCont = 0x00;
-  static constexpr uint8_t kOpText = 0x01;
-  static constexpr uint8_t kOpBinary = 0x02;
-  static constexpr uint8_t kOpClose = 0x08;
-  static constexpr uint8_t kOpPing = 0x09;
-  static constexpr uint8_t kOpPong = 0x0A;
-  static constexpr uint8_t kOpMask = 0x0F;
-  static constexpr uint8_t kFlagFin = 0x80;
-  static constexpr uint8_t kFlagMasking = 0x80;
-  static constexpr uint8_t kLenMask = 0x7f;
-
- public:
-  WebSocket(uv::Stream& stream, bool server, const private_init&);
-  WebSocket(const WebSocket&) = delete;
-  WebSocket(WebSocket&&) = delete;
-  WebSocket& operator=(const WebSocket&) = delete;
-  WebSocket& operator=(WebSocket&&) = delete;
-  ~WebSocket();
-
-  /**
-   * Connection states.
-   */
-  enum State {
-    /** The connection is not yet open. */
-    CONNECTING = 0,
-    /** The connection is open and ready to communicate. */
-    OPEN,
-    /** The connection is in the process of closing. */
-    CLOSING,
-    /** The connection failed. */
-    FAILED,
-    /** The connection is closed. */
-    CLOSED
-  };
-
-  /**
-   * Client connection options.
-   */
-  struct ClientOptions {
-    ClientOptions() : handshakeTimeout{(uv::Timer::Time::max)()} {}
-
-    /** Timeout for the handshake request. */
-    uv::Timer::Time handshakeTimeout;  // NOLINT
-
-    /** Additional headers to include in handshake. */
-    span<const std::pair<std::string_view, std::string_view>> extraHeaders;
-  };
-
-  /**
-   * Starts a client connection by performing the initial client handshake.
-   * An open event is emitted when the handshake completes.
-   * This sets the stream user data to the websocket.
-   * @param stream Connection stream
-   * @param uri The Request-URI to send
-   * @param host The host or host:port to send
-   * @param protocols The list of subprotocols
-   * @param options Handshake options
-   */
-  static std::shared_ptr<WebSocket> CreateClient(
-      uv::Stream& stream, std::string_view uri, std::string_view host,
-      span<const std::string_view> protocols = {},
-      const ClientOptions& options = {});
-
-  /**
-   * Starts a client connection by performing the initial client handshake.
-   * An open event is emitted when the handshake completes.
-   * This sets the stream user data to the websocket.
-   * @param stream Connection stream
-   * @param uri The Request-URI to send
-   * @param host The host or host:port to send
-   * @param protocols The list of subprotocols
-   * @param options Handshake options
-   */
-  static std::shared_ptr<WebSocket> CreateClient(
-      uv::Stream& stream, std::string_view uri, std::string_view host,
-      std::initializer_list<std::string_view> protocols,
-      const ClientOptions& options = {}) {
-    return CreateClient(stream, uri, host, {protocols.begin(), protocols.end()},
-                        options);
-  }
-
-  /**
-   * Starts a server connection by performing the initial server side handshake.
-   * This should be called after the HTTP headers have been received.
-   * An open event is emitted when the handshake completes.
-   * This sets the stream user data to the websocket.
-   * @param stream Connection stream
-   * @param key The value of the Sec-WebSocket-Key header field in the client
-   *            request
-   * @param version The value of the Sec-WebSocket-Version header field in the
-   *                client request
-   * @param protocol The subprotocol to send to the client (in the
-   *                 Sec-WebSocket-Protocol header field).
-   */
-  static std::shared_ptr<WebSocket> CreateServer(
-      uv::Stream& stream, std::string_view key, std::string_view version,
-      std::string_view protocol = {});
-
-  /**
-   * Get connection state.
-   */
-  State GetState() const { return m_state; }
-
-  /**
-   * Return if the connection is open.  Messages can only be sent on open
-   * connections.
-   */
-  bool IsOpen() const { return m_state == OPEN; }
-
-  /**
-   * Get the underlying stream.
-   */
-  uv::Stream& GetStream() const { return m_stream; }
-
-  /**
-   * Get the selected sub-protocol.  Only valid in or after the open() event.
-   */
-  std::string_view GetProtocol() const { return m_protocol; }
-
-  /**
-   * Set the maximum message size.  Default is 128 KB.  If configured to combine
-   * fragments this maximum applies to the entire message (all combined
-   * fragments).
-   * @param size Maximum message size in bytes
-   */
-  void SetMaxMessageSize(size_t size) { m_maxMessageSize = size; }
-
-  /**
-   * Set whether or not fragmented frames should be combined.  Default is to
-   * combine.  If fragmented frames are combined, the text and binary callbacks
-   * will always have the second parameter (fin) set to true.
-   * @param combine True if fragmented frames should be combined.
-   */
-  void SetCombineFragments(bool combine) { m_combineFragments = combine; }
-
-  /**
-   * Initiate a closing handshake.
-   * @param code A numeric status code (defaults to 1005, no status code)
-   * @param reason A human-readable string explaining why the connection is
-   *               closing (optional).
-   */
-  void Close(uint16_t code = 1005, std::string_view reason = {});
-
-  /**
-   * Send a text message.
-   * @param data UTF-8 encoded data to send
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendText(span<const uv::Buffer> data,
-                std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    Send(kFlagFin | kOpText, data, std::move(callback));
-  }
-
-  /**
-   * Send a text message.
-   * @param data UTF-8 encoded data to send
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendText(std::initializer_list<uv::Buffer> data,
-                std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    SendText({data.begin(), data.end()}, std::move(callback));
-  }
-
-  /**
-   * Send a binary message.
-   * @param data Data to send
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendBinary(span<const uv::Buffer> data,
-                  std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    Send(kFlagFin | kOpBinary, data, std::move(callback));
-  }
-
-  /**
-   * Send a binary message.
-   * @param data Data to send
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendBinary(std::initializer_list<uv::Buffer> data,
-                  std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    SendBinary({data.begin(), data.end()}, std::move(callback));
-  }
-
-  /**
-   * Send a text message fragment.  This must be followed by one or more
-   * SendFragment() calls, where the last one has fin=True, to complete the
-   * message.
-   * @param data UTF-8 encoded data to send
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendTextFragment(
-      span<const uv::Buffer> data,
-      std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    Send(kOpText, data, std::move(callback));
-  }
-
-  /**
-   * Send a text message fragment.  This must be followed by one or more
-   * SendFragment() calls, where the last one has fin=True, to complete the
-   * message.
-   * @param data UTF-8 encoded data to send
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendTextFragment(
-      std::initializer_list<uv::Buffer> data,
-      std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    SendTextFragment({data.begin(), data.end()}, std::move(callback));
-  }
-
-  /**
-   * Send a text message fragment.  This must be followed by one or more
-   * SendFragment() calls, where the last one has fin=True, to complete the
-   * message.
-   * @param data Data to send
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendBinaryFragment(
-      span<const uv::Buffer> data,
-      std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    Send(kOpBinary, data, std::move(callback));
-  }
-
-  /**
-   * Send a text message fragment.  This must be followed by one or more
-   * SendFragment() calls, where the last one has fin=True, to complete the
-   * message.
-   * @param data Data to send
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendBinaryFragment(
-      std::initializer_list<uv::Buffer> data,
-      std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    SendBinaryFragment({data.begin(), data.end()}, std::move(callback));
-  }
-
-  /**
-   * Send a continuation frame.  This is used to send additional parts of a
-   * message started with SendTextFragment() or SendBinaryFragment().
-   * @param data Data to send
-   * @param fin Set to true if this is the final fragment of the message
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendFragment(span<const uv::Buffer> data, bool fin,
-                    std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    Send(kOpCont | (fin ? kFlagFin : 0), data, std::move(callback));
-  }
-
-  /**
-   * Send a continuation frame.  This is used to send additional parts of a
-   * message started with SendTextFragment() or SendBinaryFragment().
-   * @param data Data to send
-   * @param fin Set to true if this is the final fragment of the message
-   * @param callback Callback which is invoked when the write completes.
-   */
-  void SendFragment(std::initializer_list<uv::Buffer> data, bool fin,
-                    std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    SendFragment({data.begin(), data.end()}, fin, std::move(callback));
-  }
-
-  /**
-   * Send a ping frame with no data.
-   * @param callback Optional callback which is invoked when the ping frame
-   *                 write completes.
-   */
-  void SendPing(std::function<void(uv::Error)> callback = nullptr) {
-    SendPing({}, [f = std::move(callback)](auto bufs, uv::Error err) {
-      if (f) {
-        f(err);
-      }
-    });
-  }
-
-  /**
-   * Send a ping frame.
-   * @param data Data to send in the ping frame
-   * @param callback Callback which is invoked when the ping frame
-   *                 write completes.
-   */
-  void SendPing(span<const uv::Buffer> data,
-                std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    Send(kFlagFin | kOpPing, data, std::move(callback));
-  }
-
-  /**
-   * Send a ping frame.
-   * @param data Data to send in the ping frame
-   * @param callback Callback which is invoked when the ping frame
-   *                 write completes.
-   */
-  void SendPing(std::initializer_list<uv::Buffer> data,
-                std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    SendPing({data.begin(), data.end()}, std::move(callback));
-  }
-
-  /**
-   * Send a pong frame with no data.
-   * @param callback Optional callback which is invoked when the pong frame
-   *                 write completes.
-   */
-  void SendPong(std::function<void(uv::Error)> callback = nullptr) {
-    SendPong({}, [f = std::move(callback)](auto bufs, uv::Error err) {
-      if (f) {
-        f(err);
-      }
-    });
-  }
-
-  /**
-   * Send a pong frame.
-   * @param data Data to send in the pong frame
-   * @param callback Callback which is invoked when the pong frame
-   *                 write completes.
-   */
-  void SendPong(span<const uv::Buffer> data,
-                std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    Send(kFlagFin | kOpPong, data, std::move(callback));
-  }
-
-  /**
-   * Send a pong frame.
-   * @param data Data to send in the pong frame
-   * @param callback Callback which is invoked when the pong frame
-   *                 write completes.
-   */
-  void SendPong(std::initializer_list<uv::Buffer> data,
-                std::function<void(span<uv::Buffer>, uv::Error)> callback) {
-    SendPong({data.begin(), data.end()}, std::move(callback));
-  }
-
-  /**
-   * Fail the connection.
-   */
-  void Fail(uint16_t code = 1002, std::string_view reason = "protocol error");
-
-  /**
-   * Forcibly close the connection.
-   */
-  void Terminate(uint16_t code = 1006, std::string_view reason = "terminated");
-
-  /**
-   * Gets user-defined data.
-   * @return User-defined data if any, nullptr otherwise.
-   */
-  template <typename T = void>
-  std::shared_ptr<T> GetData() const {
-    return std::static_pointer_cast<T>(m_data);
-  }
-
-  /**
-   * Sets user-defined data.
-   * @param data User-defined arbitrary data.
-   */
-  void SetData(std::shared_ptr<void> data) { m_data = std::move(data); }
-
-  /**
-   * Shuts down and closes the underlying stream.
-   */
-  void Shutdown();
-
-  /**
-   * Open event.  Emitted when the connection is open and ready to communicate.
-   * The parameter is the selected subprotocol.
-   */
-  sig::Signal<std::string_view> open;
-
-  /**
-   * Close event.  Emitted when the connection is closed.  The first parameter
-   * is a numeric value indicating the status code explaining why the connection
-   * has been closed.  The second parameter is a human-readable string
-   * explaining the reason why the connection has been closed.
-   */
-  sig::Signal<uint16_t, std::string_view> closed;
-
-  /**
-   * Text message event.  Emitted when a text message is received.
-   * The first parameter is the data, the second parameter is true if the
-   * data is the last fragment of the message.
-   */
-  sig::Signal<std::string_view, bool> text;
-
-  /**
-   * Binary message event.  Emitted when a binary message is received.
-   * The first parameter is the data, the second parameter is true if the
-   * data is the last fragment of the message.
-   */
-  sig::Signal<span<const uint8_t>, bool> binary;
-
-  /**
-   * Ping event.  Emitted when a ping message is received.
-   */
-  sig::Signal<span<const uint8_t>> ping;
-
-  /**
-   * Pong event.  Emitted when a pong message is received.
-   */
-  sig::Signal<span<const uint8_t>> pong;
-
- private:
-  // user data
-  std::shared_ptr<void> m_data;
-
-  // constructor parameters
-  uv::Stream& m_stream;
-  bool m_server;
-
-  // subprotocol, set via constructor (server) or handshake (client)
-  std::string m_protocol;
-
-  // user-settable configuration
-  size_t m_maxMessageSize = 128 * 1024;
-  bool m_combineFragments = true;
-
-  // operating state
-  State m_state = CONNECTING;
-
-  // incoming message buffers/state
-  SmallVector<uint8_t, 14> m_header;
-  size_t m_headerSize = 0;
-  SmallVector<uint8_t, 1024> m_payload;
-  size_t m_frameStart = 0;
-  uint64_t m_frameSize = UINT64_MAX;
-  uint8_t m_fragmentOpcode = 0;
-
-  // temporary data used only during client handshake
-  class ClientHandshakeData;
-  std::unique_ptr<ClientHandshakeData> m_clientHandshake;
-
-  void StartClient(std::string_view uri, std::string_view host,
-                   span<const std::string_view> protocols,
-                   const ClientOptions& options);
-  void StartServer(std::string_view key, std::string_view version,
-                   std::string_view protocol);
-  void SendClose(uint16_t code, std::string_view reason);
-  void SetClosed(uint16_t code, std::string_view reason, bool failed = false);
-  void HandleIncoming(uv::Buffer& buf, size_t size);
-  void Send(uint8_t opcode, span<const uv::Buffer> data,
-            std::function<void(span<uv::Buffer>, uv::Error)> callback);
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_WEBSOCKET_H_
diff --git a/wpiutil/src/main/native/include/wpi/WebSocketServer.h b/wpiutil/src/main/native/include/wpi/WebSocketServer.h
deleted file mode 100644
index 1f76d16..0000000
--- a/wpiutil/src/main/native/include/wpi/WebSocketServer.h
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_WEBSOCKETSERVER_H_
-#define WPIUTIL_WPI_WEBSOCKETSERVER_H_
-
-#include <functional>
-#include <initializer_list>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <utility>
-
-#include "wpi/HttpParser.h"
-#include "wpi/Signal.h"
-#include "wpi/SmallString.h"
-#include "wpi/SmallVector.h"
-#include "wpi/WebSocket.h"
-#include "wpi/span.h"
-
-namespace wpi {
-
-namespace uv {
-class Stream;
-}  // namespace uv
-
-/**
- * WebSocket HTTP server helper.  Handles websocket-specific headers.  User
- * must provide the HttpParser.
- */
-class WebSocketServerHelper {
- public:
-  /**
-   * Constructor.
-   * @param req HttpParser for request
-   */
-  explicit WebSocketServerHelper(HttpParser& req);
-
-  /**
-   * Get whether or not this was a websocket upgrade.
-   * Only valid during and after the upgrade event.
-   */
-  bool IsWebsocket() const { return m_websocket; }
-
-  /**
-   * Try to find a match to the list of sub-protocols provided by the client.
-   * The list is priority ordered, so the first match wins.
-   * Only valid during and after the upgrade event.
-   * @param protocols Acceptable protocols
-   * @return Pair; first item is true if a match was made, false if not.
-   *         Second item is the matched protocol if a match was made, otherwise
-   *         is empty.
-   */
-  std::pair<bool, std::string_view> MatchProtocol(
-      span<const std::string_view> protocols);
-
-  /**
-   * Try to find a match to the list of sub-protocols provided by the client.
-   * The list is priority ordered, so the first match wins.
-   * Only valid during and after the upgrade event.
-   * @param protocols Acceptable protocols
-   * @return Pair; first item is true if a match was made, false if not.
-   *         Second item is the matched protocol if a match was made, otherwise
-   *         is empty.
-   */
-  std::pair<bool, std::string_view> MatchProtocol(
-      std::initializer_list<std::string_view> protocols) {
-    return MatchProtocol({protocols.begin(), protocols.end()});
-  }
-
-  /**
-   * Accept the upgrade.  Disconnect other readers (such as the HttpParser
-   * reader) before calling this.  See also WebSocket::CreateServer().
-   * @param stream Connection stream
-   * @param protocol The subprotocol to send to the client
-   */
-  std::shared_ptr<WebSocket> Accept(uv::Stream& stream,
-                                    std::string_view protocol = {}) {
-    return WebSocket::CreateServer(stream, m_key, m_version, protocol);
-  }
-
-  bool IsUpgrade() const { return m_gotHost && m_websocket; }
-
-  /**
-   * Upgrade event.  Call Accept() to accept the upgrade.
-   */
-  sig::Signal<> upgrade;
-
- private:
-  bool m_gotHost = false;
-  bool m_websocket = false;
-  SmallVector<std::string, 2> m_protocols;
-  SmallString<64> m_key;
-  SmallString<16> m_version;
-};
-
-/**
- * Dedicated WebSocket server.
- */
-class WebSocketServer : public std::enable_shared_from_this<WebSocketServer> {
-  struct private_init {};
-
- public:
-  /**
-   * Server options.
-   */
-  struct ServerOptions {
-    /**
-     * Checker for URL.  Return true if URL should be accepted.  By default all
-     * URLs are accepted.
-     */
-    std::function<bool(std::string_view)> checkUrl;
-
-    /**
-     * Checker for Host header.  Return true if Host should be accepted.  By
-     * default all hosts are accepted.
-     */
-    std::function<bool(std::string_view)> checkHost;
-  };
-
-  /**
-   * Private constructor.
-   */
-  WebSocketServer(uv::Stream& stream, span<const std::string_view> protocols,
-                  ServerOptions options, const private_init&);
-
-  /**
-   * Starts a dedicated WebSocket server on the provided connection.  The
-   * connection should be an accepted client stream.
-   * This also sets the stream user data to the socket server.
-   * A connected event is emitted when the connection is opened.
-   * @param stream Connection stream
-   * @param protocols Acceptable subprotocols
-   * @param options Handshake options
-   */
-  static std::shared_ptr<WebSocketServer> Create(
-      uv::Stream& stream, span<const std::string_view> protocols = {},
-      const ServerOptions& options = {});
-
-  /**
-   * Starts a dedicated WebSocket server on the provided connection.  The
-   * connection should be an accepted client stream.
-   * This also sets the stream user data to the socket server.
-   * A connected event is emitted when the connection is opened.
-   * @param stream Connection stream
-   * @param protocols Acceptable subprotocols
-   * @param options Handshake options
-   */
-  static std::shared_ptr<WebSocketServer> Create(
-      uv::Stream& stream, std::initializer_list<std::string_view> protocols,
-      const ServerOptions& options = {}) {
-    return Create(stream, {protocols.begin(), protocols.end()}, options);
-  }
-
-  /**
-   * Connected event.  First parameter is the URL, second is the websocket.
-   */
-  sig::Signal<std::string_view, WebSocket&> connected;
-
- private:
-  uv::Stream& m_stream;
-  HttpParser m_req{HttpParser::kRequest};
-  WebSocketServerHelper m_helper;
-  SmallVector<std::string, 2> m_protocols;
-  ServerOptions m_options;
-  bool m_aborted = false;
-  sig::ScopedConnection m_dataConn;
-  sig::ScopedConnection m_errorConn;
-  sig::ScopedConnection m_endConn;
-
-  void Abort(uint16_t code, std::string_view reason);
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_WEBSOCKETSERVER_H_
diff --git a/wpiutil/src/main/native/include/wpi/WorkerThread.h b/wpiutil/src/main/native/include/wpi/WorkerThread.h
deleted file mode 100644
index 6c8852e..0000000
--- a/wpiutil/src/main/native/include/wpi/WorkerThread.h
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_WORKERTHREAD_H_
-#define WPIUTIL_WPI_WORKERTHREAD_H_
-
-#include <functional>
-#include <memory>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "wpi/SafeThread.h"
-#include "wpi/future.h"
-#include "wpi/uv/Async.h"
-
-namespace wpi {
-
-namespace detail {
-
-template <typename R>
-struct WorkerThreadAsync {
-  using AfterWorkFunction = std::function<void(R)>;
-
-  ~WorkerThreadAsync() { UnsetLoop(); }
-
-  void SetLoop(uv::Loop& loop) {
-    auto async = uv::Async<AfterWorkFunction, R>::Create(loop);
-    async->wakeup.connect(
-        [](AfterWorkFunction func, R result) { func(result); });
-    m_async = async;
-  }
-
-  void UnsetLoop() {
-    if (auto async = m_async.lock()) {
-      async->Close();
-      m_async.reset();
-    }
-  }
-
-  std::weak_ptr<uv::Async<AfterWorkFunction, R>> m_async;
-};
-
-template <>
-struct WorkerThreadAsync<void> {
-  using AfterWorkFunction = std::function<void()>;
-
-  ~WorkerThreadAsync() { RemoveLoop(); }
-
-  void SetLoop(uv::Loop& loop) {
-    auto async = uv::Async<AfterWorkFunction>::Create(loop);
-    async->wakeup.connect([](AfterWorkFunction func) { func(); });
-    m_async = async;
-  }
-
-  void RemoveLoop() {
-    if (auto async = m_async.lock()) {
-      async->Close();
-      m_async.reset();
-    }
-  }
-
-  std::weak_ptr<uv::Async<AfterWorkFunction>> m_async;
-};
-
-template <typename R, typename... T>
-struct WorkerThreadRequest {
-  using WorkFunction = std::function<R(T...)>;
-  using AfterWorkFunction = typename WorkerThreadAsync<R>::AfterWorkFunction;
-
-  WorkerThreadRequest() = default;
-  WorkerThreadRequest(uint64_t promiseId_, WorkFunction work_,
-                      std::tuple<T...> params_)
-      : promiseId(promiseId_),
-        work(std::move(work_)),
-        params(std::move(params_)) {}
-  WorkerThreadRequest(WorkFunction work_, AfterWorkFunction afterWork_,
-                      std::tuple<T...> params_)
-      : promiseId(0),
-        work(std::move(work_)),
-        afterWork(std::move(afterWork_)),
-        params(std::move(params_)) {}
-
-  uint64_t promiseId;
-  WorkFunction work;
-  AfterWorkFunction afterWork;
-  std::tuple<T...> params;
-};
-
-template <typename R, typename... T>
-class WorkerThreadThread : public SafeThread {
- public:
-  using Request = WorkerThreadRequest<R, T...>;
-
-  void Main() override;
-
-  std::vector<Request> m_requests;
-  PromiseFactory<R> m_promises;
-  detail::WorkerThreadAsync<R> m_async;
-};
-
-template <typename R, typename... T>
-void RunWorkerThreadRequest(WorkerThreadThread<R, T...>& thr,
-                            WorkerThreadRequest<R, T...>& req) {
-  R result = std::apply(req.work, std::move(req.params));
-  if (req.afterWork) {
-    if (auto async = thr.m_async.m_async.lock()) {
-      async->Send(std::move(req.afterWork), std::move(result));
-    }
-  } else {
-    thr.m_promises.SetValue(req.promiseId, std::move(result));
-  }
-}
-
-template <typename... T>
-void RunWorkerThreadRequest(WorkerThreadThread<void, T...>& thr,
-                            WorkerThreadRequest<void, T...>& req) {
-  std::apply(req.work, req.params);
-  if (req.afterWork) {
-    if (auto async = thr.m_async.m_async.lock()) {
-      async->Send(std::move(req.afterWork));
-    }
-  } else {
-    thr.m_promises.SetValue(req.promiseId);
-  }
-}
-
-template <typename R, typename... T>
-void WorkerThreadThread<R, T...>::Main() {
-  std::vector<Request> requests;
-  while (m_active) {
-    std::unique_lock lock(m_mutex);
-    m_cond.wait(lock, [&] { return !m_active || !m_requests.empty(); });
-    if (!m_active) {
-      break;
-    }
-
-    // don't want to hold the lock while executing the callbacks
-    requests.swap(m_requests);
-    lock.unlock();
-
-    for (auto&& req : requests) {
-      if (!m_active) {
-        break;  // requests may be long-running
-      }
-      RunWorkerThreadRequest(*this, req);
-    }
-    requests.clear();
-    m_promises.Notify();
-  }
-}
-
-}  // namespace detail
-
-template <typename T>
-class WorkerThread;
-
-template <typename R, typename... T>
-class WorkerThread<R(T...)> final {
-  using Thread = detail::WorkerThreadThread<R, T...>;
-
- public:
-  using WorkFunction = std::function<R(T...)>;
-  using AfterWorkFunction =
-      typename detail::WorkerThreadAsync<R>::AfterWorkFunction;
-
-  WorkerThread() { m_owner.Start(); }
-
-  /**
-   * Set the loop.  This must be called from the loop thread.
-   * Subsequent calls to QueueWorkThen will run afterWork on the provided
-   * loop (via an async handle).
-   *
-   * @param loop the loop to use for running afterWork routines
-   */
-  void SetLoop(uv::Loop& loop) {
-    if (auto thr = m_owner.GetThread()) {
-      thr->m_async.SetLoop(loop);
-    }
-  }
-
-  /**
-   * Set the loop.  This must be called from the loop thread.
-   * Subsequent calls to QueueWorkThen will run afterWork on the provided
-   * loop (via an async handle).
-   *
-   * @param loop the loop to use for running afterWork routines
-   */
-  void SetLoop(std::shared_ptr<uv::Loop> loop) { SetLoop(*loop); }
-
-  /**
-   * Unset the loop.  This must be called from the loop thread.
-   * Subsequent calls to QueueWorkThen will no longer run afterWork.
-   */
-  void UnsetLoop() {
-    if (auto thr = m_owner.GetThread()) {
-      thr->m_async.UnsetLoop();
-    }
-  }
-
-  /**
-   * Get the handle used by QueueWorkThen() to run afterWork.
-   * This handle is set by SetLoop().
-   * Calling Close() on this handle is the same as calling UnsetLoop().
-   *
-   * @return The handle (if nullptr, no handle is set)
-   */
-  std::shared_ptr<uv::Handle> GetHandle() const {
-    if (auto thr = m_owner.GetThread()) {
-      return thr->m_async.m_async.lock();
-    } else {
-      return nullptr;
-    }
-  }
-
-  /**
-   * Wakeup the worker thread, call the work function, and return a future for
-   * the result.
-   *
-   * It’s safe to call this function from any thread.
-   * The work function will be called on the worker thread.
-   *
-   * The future will return a default-constructed result if this class is
-   * destroyed while waiting for a result.
-   *
-   * @param work Work function (called on worker thread)
-   * @param u Arguments to work function
-   */
-  template <typename... U>
-  future<R> QueueWork(WorkFunction work, U&&... u) {
-    if (auto thr = m_owner.GetThread()) {
-      // create the future
-      uint64_t req = thr->m_promises.CreateRequest();
-
-      // add the parameters to the input queue
-      thr->m_requests.emplace_back(
-          req, std::move(work), std::forward_as_tuple(std::forward<U>(u)...));
-
-      // signal the thread
-      thr->m_cond.notify_one();
-
-      // return future
-      return thr->m_promises.CreateFuture(req);
-    }
-
-    // XXX: is this the right thing to do?
-    return future<R>();
-  }
-
-  /**
-   * Wakeup the worker thread, call the work function, and call the afterWork
-   * function with the result on the loop set by SetLoop().
-   *
-   * It’s safe to call this function from any thread.
-   * The work function will be called on the worker thread, and the afterWork
-   * function will be called on the loop thread.
-   *
-   * SetLoop() must be called prior to calling this function for afterWork to
-   * be called.
-   *
-   * @param work Work function (called on worker thread)
-   * @param afterWork After work function (called on loop thread)
-   * @param u Arguments to work function
-   */
-  template <typename... U>
-  void QueueWorkThen(WorkFunction work, AfterWorkFunction afterWork, U&&... u) {
-    if (auto thr = m_owner.GetThread()) {
-      // add the parameters to the input queue
-      thr->m_requests.emplace_back(
-          std::move(work), std::move(afterWork),
-          std::forward_as_tuple(std::forward<U>(u)...));
-
-      // signal the thread
-      thr->m_cond.notify_one();
-    }
-  }
-
- private:
-  SafeThreadOwner<Thread> m_owner;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_WORKERTHREAD_H_
diff --git a/wpiutil/src/main/native/include/wpi/array.h b/wpiutil/src/main/native/include/wpi/array.h
index f2604ec..cfbb7b0 100644
--- a/wpiutil/src/main/native/include/wpi/array.h
+++ b/wpiutil/src/main/native/include/wpi/array.h
@@ -24,33 +24,33 @@
 template <typename T, size_t N>
 class array : public std::array<T, N> {
  public:
-  explicit array(empty_array_t) {}
+  constexpr explicit array(empty_array_t) {}
 
   template <typename... Ts>
-  array(T arg, Ts&&... args)  // NOLINT
+  constexpr array(T arg, Ts&&... args)  // NOLINT
       : std::array<T, N>{std::forward<T>(arg), std::forward<Ts>(args)...} {
     static_assert(1 + sizeof...(args) == N, "Dimension mismatch");
   }
 
-  array(const array<T, N>&) = default;
-  array& operator=(const array<T, N>&) = default;
-  array(array<T, N>&&) = default;
-  array& operator=(array<T, N>&&) = default;
+  constexpr array(const array<T, N>&) = default;
+  constexpr array& operator=(const array<T, N>&) = default;
+  constexpr array(array<T, N>&&) = default;
+  constexpr array& operator=(array<T, N>&&) = default;
 
-  array(const std::array<T, N>& rhs) {  // NOLINT
+  constexpr array(const std::array<T, N>& rhs) {  // NOLINT
     *static_cast<std::array<T, N>*>(this) = rhs;
   }
 
-  array& operator=(const std::array<T, N>& rhs) {
+  constexpr array& operator=(const std::array<T, N>& rhs) {
     *static_cast<std::array<T, N>*>(this) = rhs;
     return *this;
   }
 
-  array(std::array<T, N>&& rhs) {  // NOLINT
+  constexpr array(std::array<T, N>&& rhs) {  // NOLINT
     *static_cast<std::array<T, N>*>(this) = rhs;
   }
 
-  array& operator=(std::array<T, N>&& rhs) {
+  constexpr array& operator=(std::array<T, N>&& rhs) {
     *static_cast<std::array<T, N>*>(this) = rhs;
     return *this;
   }
diff --git a/wpiutil/src/main/native/include/wpi/circular_buffer.h b/wpiutil/src/main/native/include/wpi/circular_buffer.h
index 40913f9..c54e2f5 100644
--- a/wpiutil/src/main/native/include/wpi/circular_buffer.h
+++ b/wpiutil/src/main/native/include/wpi/circular_buffer.h
@@ -43,10 +43,7 @@
       ++(*this);
       return retval;
     }
-    bool operator==(const iterator& other) const {
-      return m_buffer == other.m_buffer && m_index == other.m_index;
-    }
-    bool operator!=(const iterator& other) const { return !(*this == other); }
+    bool operator==(const iterator&) const = default;
     reference operator*() { return (*m_buffer)[m_index]; }
 
    private:
@@ -74,12 +71,7 @@
       ++(*this);
       return retval;
     }
-    bool operator==(const const_iterator& other) const {
-      return m_buffer == other.m_buffer && m_index == other.m_index;
-    }
-    bool operator!=(const const_iterator& other) const {
-      return !(*this == other);
-    }
+    bool operator==(const const_iterator&) const = default;
     const_reference operator*() const { return (*m_buffer)[m_index]; }
 
    private:
diff --git a/wpiutil/src/main/native/include/wpi/deprecated.h b/wpiutil/src/main/native/include/wpi/deprecated.h
index 6e6a3bf..c5b4af2 100644
--- a/wpiutil/src/main/native/include/wpi/deprecated.h
+++ b/wpiutil/src/main/native/include/wpi/deprecated.h
@@ -9,4 +9,23 @@
 #define WPI_DEPRECATED(msg) [[deprecated(msg)]]
 #endif
 
+#ifndef WPI_IGNORE_DEPRECATED
+#ifdef __GNUC__
+#define WPI_IGNORE_DEPRECATED    \
+  _Pragma("GCC diagnostic push") \
+      _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif defined(_WIN32)
+#define WPI_IGNORE_DEPRECATED _Pragma("warning(disable : 4996)")
+#endif
+
+#endif
+
+#ifndef WPI_UNIGNORE_DEPRECATED
+#ifdef __GNUC__
+#define WPI_UNIGNORE_DEPRECATED _Pragma("GCC diagnostic pop")
+#elif defined(_WIN32)
+#define WPI_UNIGNORE_DEPRECATED _Pragma("warning(default : 4996)")
+#endif
+#endif
+
 #endif  // WPIUTIL_WPI_DEPRECATED_H_
diff --git a/wpiutil/src/main/native/include/wpi/fmt/raw_ostream.h b/wpiutil/src/main/native/include/wpi/fmt/raw_ostream.h
index 8779bfc..024e04c 100644
--- a/wpiutil/src/main/native/include/wpi/fmt/raw_ostream.h
+++ b/wpiutil/src/main/native/include/wpi/fmt/raw_ostream.h
@@ -22,7 +22,7 @@
  */
 template <typename S, typename... Args>
 void print(wpi::raw_ostream& os, const S& format_str, Args&&... args) {
-  vprint(os, format_str, fmt::make_args_checked<Args...>(format_str, args...));
+  vprint(os, format_str, fmt::make_format_args(args...));
 }
 
 FMT_END_NAMESPACE
diff --git a/wpiutil/src/main/native/include/wpi/fs.h b/wpiutil/src/main/native/include/wpi/fs.h
index fca8069..587a23c 100644
--- a/wpiutil/src/main/native/include/wpi/fs.h
+++ b/wpiutil/src/main/native/include/wpi/fs.h
@@ -40,7 +40,7 @@
 #ifndef GHC_USE_STD_FS
 // #define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
 #define GHC_FILESYSTEM_FWD
-#include "ghc/filesystem.hpp"
+#include "wpi/ghc/filesystem.hpp"
 namespace fs {
 using namespace ghc::filesystem;
 using ifstream = ghc::filesystem::ifstream;
diff --git a/wpiutil/src/main/native/include/wpi/future.h b/wpiutil/src/main/native/include/wpi/future.h
index 5cb4a8d..70dc60f 100644
--- a/wpiutil/src/main/native/include/wpi/future.h
+++ b/wpiutil/src/main/native/include/wpi/future.h
@@ -334,7 +334,7 @@
     }
   }
 
-  template <typename F, typename R = typename std::result_of<F && (T &&)>::type>
+  template <typename F, typename R = typename std::invoke_result_t<F&&, T&&>>
   future<R> then(F&& func) {
     return then(PromiseFactory<R>::GetInstance(), std::forward<F>(func));
   }
@@ -457,7 +457,7 @@
     }
   }
 
-  template <typename F, typename R = typename std::result_of<F && ()>::type>
+  template <typename F, typename R = typename std::invoke_result_t<F&&>>
   future<R> then(F&& func) {
     return then(PromiseFactory<R>::GetInstance(), std::forward<F>(func));
   }
diff --git a/wpiutil/src/main/native/include/wpi/hostname.h b/wpiutil/src/main/native/include/wpi/hostname.h
deleted file mode 100644
index bd93b4a..0000000
--- a/wpiutil/src/main/native/include/wpi/hostname.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_HOSTNAME_H_
-#define WPIUTIL_WPI_HOSTNAME_H_
-
-#include <string>
-#include <string_view>
-
-namespace wpi {
-template <typename T>
-class SmallVectorImpl;
-
-std::string GetHostname();
-std::string_view GetHostname(SmallVectorImpl<char>& name);
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_HOSTNAME_H_
diff --git a/wpiutil/src/main/native/include/wpi/http_parser.h b/wpiutil/src/main/native/include/wpi/http_parser.h
deleted file mode 100644
index 2189b8f..0000000
--- a/wpiutil/src/main/native/include/wpi/http_parser.h
+++ /dev/null
@@ -1,421 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef wpi_http_parser_h
-#define wpi_http_parser_h
-
-/* Also update SONAME in the Makefile whenever you change these. */
-#define HTTP_PARSER_VERSION_MAJOR 2
-#define HTTP_PARSER_VERSION_MINOR 8
-#define HTTP_PARSER_VERSION_PATCH 1
-
-#include <stddef.h>
-#include <stdint.h>
-
-/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
- * faster
- */
-#ifndef HTTP_PARSER_STRICT
-# define HTTP_PARSER_STRICT 1
-#endif
-
-/* Maximium header size allowed. If the macro is not defined
- * before including this header then the default is used. To
- * change the maximum header size, define the macro in the build
- * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
- * the effective limit on the size of the header, define the macro
- * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
- */
-#ifndef HTTP_MAX_HEADER_SIZE
-# define HTTP_MAX_HEADER_SIZE (80*1024)
-#endif
-
-namespace wpi {
-
-struct http_parser;
-struct http_parser_settings;
-
-
-/* Callbacks should return non-zero to indicate an error. The parser will
- * then halt execution.
- *
- * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
- * returning '1' from on_headers_complete will tell the parser that it
- * should not expect a body. This is used when receiving a response to a
- * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
- * chunked' headers that indicate the presence of a body.
- *
- * Returning `2` from on_headers_complete will tell parser that it should not
- * expect neither a body nor any further responses on this connection. This is
- * useful for handling responses to a CONNECT request which may not contain
- * `Upgrade` or `Connection: upgrade` headers.
- *
- * http_data_cb does not return data chunks. It will be called arbitrarily
- * many times for each string. E.G. you might get 10 callbacks for "on_url"
- * each providing just a few characters more data.
- */
-typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
-typedef int (*http_cb) (http_parser*);
-
-
-/* Status Codes */
-#define HTTP_STATUS_MAP(XX)                                                 \
-  XX(100, CONTINUE,                        Continue)                        \
-  XX(101, SWITCHING_PROTOCOLS,             Switching Protocols)             \
-  XX(102, PROCESSING,                      Processing)                      \
-  XX(200, OK,                              OK)                              \
-  XX(201, CREATED,                         Created)                         \
-  XX(202, ACCEPTED,                        Accepted)                        \
-  XX(203, NON_AUTHORITATIVE_INFORMATION,   Non-Authoritative Information)   \
-  XX(204, NO_CONTENT,                      No Content)                      \
-  XX(205, RESET_CONTENT,                   Reset Content)                   \
-  XX(206, PARTIAL_CONTENT,                 Partial Content)                 \
-  XX(207, MULTI_STATUS,                    Multi-Status)                    \
-  XX(208, ALREADY_REPORTED,                Already Reported)                \
-  XX(226, IM_USED,                         IM Used)                         \
-  XX(300, MULTIPLE_CHOICES,                Multiple Choices)                \
-  XX(301, MOVED_PERMANENTLY,               Moved Permanently)               \
-  XX(302, FOUND,                           Found)                           \
-  XX(303, SEE_OTHER,                       See Other)                       \
-  XX(304, NOT_MODIFIED,                    Not Modified)                    \
-  XX(305, USE_PROXY,                       Use Proxy)                       \
-  XX(307, TEMPORARY_REDIRECT,              Temporary Redirect)              \
-  XX(308, PERMANENT_REDIRECT,              Permanent Redirect)              \
-  XX(400, BAD_REQUEST,                     Bad Request)                     \
-  XX(401, UNAUTHORIZED,                    Unauthorized)                    \
-  XX(402, PAYMENT_REQUIRED,                Payment Required)                \
-  XX(403, FORBIDDEN,                       Forbidden)                       \
-  XX(404, NOT_FOUND,                       Not Found)                       \
-  XX(405, METHOD_NOT_ALLOWED,              Method Not Allowed)              \
-  XX(406, NOT_ACCEPTABLE,                  Not Acceptable)                  \
-  XX(407, PROXY_AUTHENTICATION_REQUIRED,   Proxy Authentication Required)   \
-  XX(408, REQUEST_TIMEOUT,                 Request Timeout)                 \
-  XX(409, CONFLICT,                        Conflict)                        \
-  XX(410, GONE,                            Gone)                            \
-  XX(411, LENGTH_REQUIRED,                 Length Required)                 \
-  XX(412, PRECONDITION_FAILED,             Precondition Failed)             \
-  XX(413, PAYLOAD_TOO_LARGE,               Payload Too Large)               \
-  XX(414, URI_TOO_LONG,                    URI Too Long)                    \
-  XX(415, UNSUPPORTED_MEDIA_TYPE,          Unsupported Media Type)          \
-  XX(416, RANGE_NOT_SATISFIABLE,           Range Not Satisfiable)           \
-  XX(417, EXPECTATION_FAILED,              Expectation Failed)              \
-  XX(421, MISDIRECTED_REQUEST,             Misdirected Request)             \
-  XX(422, UNPROCESSABLE_ENTITY,            Unprocessable Entity)            \
-  XX(423, LOCKED,                          Locked)                          \
-  XX(424, FAILED_DEPENDENCY,               Failed Dependency)               \
-  XX(426, UPGRADE_REQUIRED,                Upgrade Required)                \
-  XX(428, PRECONDITION_REQUIRED,           Precondition Required)           \
-  XX(429, TOO_MANY_REQUESTS,               Too Many Requests)               \
-  XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
-  XX(451, UNAVAILABLE_FOR_LEGAL_REASONS,   Unavailable For Legal Reasons)   \
-  XX(500, INTERNAL_SERVER_ERROR,           Internal Server Error)           \
-  XX(501, NOT_IMPLEMENTED,                 Not Implemented)                 \
-  XX(502, BAD_GATEWAY,                     Bad Gateway)                     \
-  XX(503, SERVICE_UNAVAILABLE,             Service Unavailable)             \
-  XX(504, GATEWAY_TIMEOUT,                 Gateway Timeout)                 \
-  XX(505, HTTP_VERSION_NOT_SUPPORTED,      HTTP Version Not Supported)      \
-  XX(506, VARIANT_ALSO_NEGOTIATES,         Variant Also Negotiates)         \
-  XX(507, INSUFFICIENT_STORAGE,            Insufficient Storage)            \
-  XX(508, LOOP_DETECTED,                   Loop Detected)                   \
-  XX(510, NOT_EXTENDED,                    Not Extended)                    \
-  XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
-
-enum http_status
-  {
-#define XX(num, name, string) HTTP_STATUS_##name = num,
-  HTTP_STATUS_MAP(XX)
-#undef XX
-  };
-
-
-/* Request Methods */
-#define HTTP_METHOD_MAP(XX)         \
-  XX(0,  DELETE,      DELETE)       \
-  XX(1,  GET,         GET)          \
-  XX(2,  HEAD,        HEAD)         \
-  XX(3,  POST,        POST)         \
-  XX(4,  PUT,         PUT)          \
-  /* pathological */                \
-  XX(5,  CONNECT,     CONNECT)      \
-  XX(6,  OPTIONS,     OPTIONS)      \
-  XX(7,  TRACE,       TRACE)        \
-  /* WebDAV */                      \
-  XX(8,  COPY,        COPY)         \
-  XX(9,  LOCK,        LOCK)         \
-  XX(10, MKCOL,       MKCOL)        \
-  XX(11, MOVE,        MOVE)         \
-  XX(12, PROPFIND,    PROPFIND)     \
-  XX(13, PROPPATCH,   PROPPATCH)    \
-  XX(14, SEARCH,      SEARCH)       \
-  XX(15, UNLOCK,      UNLOCK)       \
-  XX(16, BIND,        BIND)         \
-  XX(17, REBIND,      REBIND)       \
-  XX(18, UNBIND,      UNBIND)       \
-  XX(19, ACL,         ACL)          \
-  /* subversion */                  \
-  XX(20, REPORT,      REPORT)       \
-  XX(21, MKACTIVITY,  MKACTIVITY)   \
-  XX(22, CHECKOUT,    CHECKOUT)     \
-  XX(23, MERGE,       MERGE)        \
-  /* upnp */                        \
-  XX(24, MSEARCH,     M-SEARCH)     \
-  XX(25, NOTIFY,      NOTIFY)       \
-  XX(26, SUBSCRIBE,   SUBSCRIBE)    \
-  XX(27, UNSUBSCRIBE, UNSUBSCRIBE)  \
-  /* RFC-5789 */                    \
-  XX(28, PATCH,       PATCH)        \
-  XX(29, PURGE,       PURGE)        \
-  /* CalDAV */                      \
-  XX(30, MKCALENDAR,  MKCALENDAR)   \
-  /* RFC-2068, section 19.6.1.2 */  \
-  XX(31, LINK,        LINK)         \
-  XX(32, UNLINK,      UNLINK)       \
-  /* icecast */                     \
-  XX(33, SOURCE,      SOURCE)       \
-
-enum http_method
-  {
-#define XX(num, name, string) HTTP_##name = num,
-  HTTP_METHOD_MAP(XX)
-#undef XX
-  };
-
-
-enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
-
-
-/* Flag values for http_parser.flags field */
-enum flags
-  { F_CHUNKED               = 1 << 0
-  , F_CONNECTION_KEEP_ALIVE = 1 << 1
-  , F_CONNECTION_CLOSE      = 1 << 2
-  , F_CONNECTION_UPGRADE    = 1 << 3
-  , F_TRAILING              = 1 << 4
-  , F_UPGRADE               = 1 << 5
-  , F_SKIPBODY              = 1 << 6
-  , F_CONTENTLENGTH         = 1 << 7
-  };
-
-
-/* Map for errno-related constants
- *
- * The provided argument should be a macro that takes 2 arguments.
- */
-#define HTTP_ERRNO_MAP(XX)                                           \
-  /* No error */                                                     \
-  XX(OK, "success")                                                  \
-                                                                     \
-  /* Callback-related errors */                                      \
-  XX(CB_message_begin, "the on_message_begin callback failed")       \
-  XX(CB_url, "the on_url callback failed")                           \
-  XX(CB_header_field, "the on_header_field callback failed")         \
-  XX(CB_header_value, "the on_header_value callback failed")         \
-  XX(CB_headers_complete, "the on_headers_complete callback failed") \
-  XX(CB_body, "the on_body callback failed")                         \
-  XX(CB_message_complete, "the on_message_complete callback failed") \
-  XX(CB_status, "the on_status callback failed")                     \
-  XX(CB_chunk_header, "the on_chunk_header callback failed")         \
-  XX(CB_chunk_complete, "the on_chunk_complete callback failed")     \
-                                                                     \
-  /* Parsing-related errors */                                       \
-  XX(INVALID_EOF_STATE, "stream ended at an unexpected time")        \
-  XX(HEADER_OVERFLOW,                                                \
-     "too many header bytes seen; overflow detected")                \
-  XX(CLOSED_CONNECTION,                                              \
-     "data received after completed connection: close message")      \
-  XX(INVALID_VERSION, "invalid HTTP version")                        \
-  XX(INVALID_STATUS, "invalid HTTP status code")                     \
-  XX(INVALID_METHOD, "invalid HTTP method")                          \
-  XX(INVALID_URL, "invalid URL")                                     \
-  XX(INVALID_HOST, "invalid host")                                   \
-  XX(INVALID_PORT, "invalid port")                                   \
-  XX(INVALID_PATH, "invalid path")                                   \
-  XX(INVALID_QUERY_STRING, "invalid query string")                   \
-  XX(INVALID_FRAGMENT, "invalid fragment")                           \
-  XX(LF_EXPECTED, "LF character expected")                           \
-  XX(INVALID_HEADER_TOKEN, "invalid character in header")            \
-  XX(INVALID_CONTENT_LENGTH,                                         \
-     "invalid character in content-length header")                   \
-  XX(UNEXPECTED_CONTENT_LENGTH,                                      \
-     "unexpected content-length header")                             \
-  XX(INVALID_CHUNK_SIZE,                                             \
-     "invalid character in chunk size header")                       \
-  XX(INVALID_CONSTANT, "invalid constant string")                    \
-  XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
-  XX(STRICT, "strict mode assertion failed")                         \
-  XX(PAUSED, "parser is paused")                                     \
-  XX(UNKNOWN, "an unknown error occurred")
-
-
-/* Define HPE_* values for each errno value above */
-#define HTTP_ERRNO_GEN(n, s) HPE_##n,
-enum http_errno {
-  HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
-};
-#undef HTTP_ERRNO_GEN
-
-
-/* Get an http_errno value from an http_parser */
-#define HTTP_PARSER_ERRNO(p)            ((::wpi::http_errno) (p)->http_errno)
-
-
-struct http_parser {
-  /** PRIVATE **/
-  unsigned int type : 2;         /* enum http_parser_type */
-  unsigned int flags : 8;        /* F_* values from 'flags' enum; semi-public */
-  unsigned int state : 7;        /* enum state from http_parser.c */
-  unsigned int header_state : 7; /* enum header_state from http_parser.c */
-  unsigned int index : 7;        /* index into current matcher */
-  unsigned int lenient_http_headers : 1;
-
-  uint32_t nread;          /* # bytes read in various scenarios */
-  uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
-
-  /** READ-ONLY **/
-  unsigned short http_major;
-  unsigned short http_minor;
-  unsigned int status_code : 16; /* responses only */
-  unsigned int method : 8;       /* requests only */
-  unsigned int http_errno : 7;
-
-  /* 1 = Upgrade header was present and the parser has exited because of that.
-   * 0 = No upgrade header present.
-   * Should be checked when http_parser_execute() returns in addition to
-   * error checking.
-   */
-  unsigned int upgrade : 1;
-
-  /** PUBLIC **/
-  void *data; /* A pointer to get hook to the "connection" or "socket" object */
-};
-
-
-struct http_parser_settings {
-  http_cb      on_message_begin;
-  http_data_cb on_url;
-  http_data_cb on_status;
-  http_data_cb on_header_field;
-  http_data_cb on_header_value;
-  http_cb      on_headers_complete;
-  http_data_cb on_body;
-  http_cb      on_message_complete;
-  /* When on_chunk_header is called, the current chunk length is stored
-   * in parser->content_length.
-   */
-  http_cb      on_chunk_header;
-  http_cb      on_chunk_complete;
-};
-
-
-enum http_parser_url_fields
-  { UF_SCHEMA           = 0
-  , UF_HOST             = 1
-  , UF_PORT             = 2
-  , UF_PATH             = 3
-  , UF_QUERY            = 4
-  , UF_FRAGMENT         = 5
-  , UF_USERINFO         = 6
-  , UF_MAX              = 7
-  };
-
-
-/* Result structure for http_parser_parse_url().
- *
- * Callers should index into field_data[] with UF_* values iff field_set
- * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
- * because we probably have padding left over), we convert any port to
- * a uint16_t.
- */
-struct http_parser_url {
-  uint16_t field_set;           /* Bitmask of (1 << UF_*) values */
-  uint16_t port;                /* Converted UF_PORT string */
-
-  struct {
-    uint16_t off;               /* Offset into buffer in which field starts */
-    uint16_t len;               /* Length of run in buffer */
-  } field_data[UF_MAX];
-};
-
-
-/* Returns the library version. Bits 16-23 contain the major version number,
- * bits 8-15 the minor version number and bits 0-7 the patch level.
- * Usage example:
- *
- *   unsigned long version = http_parser_version();
- *   unsigned major = (version >> 16) & 255;
- *   unsigned minor = (version >> 8) & 255;
- *   unsigned patch = version & 255;
- *   printf("http_parser v%u.%u.%u\n", major, minor, patch);
- */
-unsigned long http_parser_version(void);
-
-void http_parser_init(http_parser *parser, enum http_parser_type type);
-
-
-/* Initialize http_parser_settings members to 0
- */
-void http_parser_settings_init(http_parser_settings *settings);
-
-
-/* Executes the parser. Returns number of parsed bytes. Sets
- * `parser->http_errno` on error. */
-size_t http_parser_execute(http_parser *parser,
-                           const http_parser_settings *settings,
-                           const char *data,
-                           size_t len);
-
-
-/* If http_should_keep_alive() in the on_headers_complete or
- * on_message_complete callback returns 0, then this should be
- * the last message on the connection.
- * If you are the server, respond with the "Connection: close" header.
- * If you are the client, close the connection.
- */
-int http_should_keep_alive(const http_parser *parser);
-
-/* Returns a string version of the HTTP method. */
-const char *http_method_str(enum http_method m);
-
-/* Returns a string version of the HTTP status code. */
-const char *http_status_str(enum http_status s);
-
-/* Return a string name of the given error */
-const char *http_errno_name(enum http_errno err);
-
-/* Return a string description of the given error */
-const char *http_errno_description(enum http_errno err);
-
-/* Initialize all http_parser_url members to 0 */
-void http_parser_url_init(struct http_parser_url *u);
-
-/* Parse a URL; return nonzero on failure */
-int http_parser_parse_url(const char *buf, size_t buflen,
-                          int is_connect,
-                          struct http_parser_url *u);
-
-/* Pause or un-pause the parser; a nonzero value pauses */
-void http_parser_pause(http_parser *parser, int paused);
-
-/* Checks if this is the final chunk of the body. */
-int http_body_is_final(const http_parser *parser);
-
-}  // namespace wpi
-
-#endif
diff --git a/wpiutil/src/main/native/include/wpi/interpolating_map.h b/wpiutil/src/main/native/include/wpi/interpolating_map.h
new file mode 100644
index 0000000..5eff514
--- /dev/null
+++ b/wpiutil/src/main/native/include/wpi/interpolating_map.h
@@ -0,0 +1,87 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <map>
+#include <utility>
+
+namespace wpi {
+
+/**
+ * Implements a table of key-value pairs with linear interpolation between
+ * values.
+ *
+ * If there's no matching key, the value returned will be a linear interpolation
+ * between the keys before and after the provided one.
+ *
+ * @tparam Key   The key type.
+ * @tparam Value The value type.
+ */
+template <typename Key, typename Value>
+class interpolating_map {
+ public:
+  /**
+   * Inserts a key-value pair.
+   *
+   * @param key   The key.
+   * @param value The value.
+   */
+  void insert(const Key& key, const Value& value) {
+    m_container.insert(std::make_pair(key, value));
+  }
+
+  /**
+   * Inserts a key-value pair.
+   *
+   * @param key   The key.
+   * @param value The value.
+   */
+  void insert(Key&& key, Value&& value) {
+    m_container.insert(std::make_pair(key, value));
+  }
+
+  /**
+   * Returns the value associated with a given key.
+   *
+   * If there's no matching key, the value returned will be a linear
+   * interpolation between the keys before and after the provided one.
+   *
+   * @param key The key.
+   */
+  Value operator[](const Key& key) const {
+    using const_iterator = typename std::map<Key, Value>::const_iterator;
+
+    // Get iterator to upper bound key-value pair for the given key
+    const_iterator upper = m_container.upper_bound(key);
+
+    // If key > largest key in table, return value for largest table key
+    if (upper == m_container.end()) {
+      return (--upper)->second;
+    }
+
+    // If key <= smallest key in table, return value for smallest table key
+    if (upper == m_container.begin()) {
+      return upper->second;
+    }
+
+    // Get iterator to lower bound key-value pair
+    const_iterator lower = upper;
+    --lower;
+
+    // Perform linear interpolation between lower and upper bound
+    const double delta = (key - lower->first) / (upper->first - lower->first);
+    return delta * upper->second + (1.0 - delta) * lower->second;
+  }
+
+  /**
+   * Clears the contents.
+   */
+  void clear() { m_container.clear(); }
+
+ private:
+  std::map<Key, Value> m_container;
+};
+
+}  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/jni_util.h b/wpiutil/src/main/native/include/wpi/jni_util.h
index 585c1c6..8d50fdd 100644
--- a/wpiutil/src/main/native/include/wpi/jni_util.h
+++ b/wpiutil/src/main/native/include/wpi/jni_util.h
@@ -8,6 +8,7 @@
 #include <jni.h>
 
 #include <queue>
+#include <span>
 #include <string>
 #include <string_view>
 #include <type_traits>
@@ -21,7 +22,6 @@
 #include "wpi/StringExtras.h"
 #include "wpi/mutex.h"
 #include "wpi/raw_ostream.h"
-#include "wpi/span.h"
 
 /** Java Native Interface (JNI) utility functions */
 namespace wpi::java {
@@ -154,7 +154,7 @@
       jsize size = env->GetStringLength(str);
       const jchar* chars = env->GetStringCritical(str, nullptr);
       if (chars) {
-        convertUTF16ToUTF8String(wpi::span<const jchar>(chars, size), m_str);
+        convertUTF16ToUTF8String(std::span<const jchar>(chars, size), m_str);
         env->ReleaseStringCritical(str, chars);
       }
     } else {
@@ -179,10 +179,16 @@
 namespace detail {
 
 template <typename C, typename T>
-class JArrayRefInner {};
+class JArrayRefInner {
+ public:
+  operator std::span<const T>() const {  // NOLINT
+    return static_cast<const C*>(this)->array();
+  }
+};
 
 /**
- * Specialization of JArrayRefBase to provide std::string_view conversion.
+ * Specialization of JArrayRefBase to provide std::string_view conversion
+ * and span<const uint8_t> conversion.
  */
 template <typename C>
 class JArrayRefInner<C, jbyte> {
@@ -196,6 +202,33 @@
     }
     return {reinterpret_cast<const char*>(arr.data()), arr.size()};
   }
+
+  std::span<const uint8_t> uarray() const {
+    auto arr = static_cast<const C*>(this)->array();
+    if (arr.empty()) {
+      return {};
+    }
+    return {reinterpret_cast<const uint8_t*>(arr.data()), arr.size()};
+  }
+};
+
+/**
+ * Specialization of JArrayRefBase to handle both "long long" and "long" on
+ * 64-bit systems.
+ */
+template <typename C>
+class JArrayRefInner<C, jlong> {
+ public:
+  template <typename U,
+            typename = std::enable_if_t<sizeof(U) == sizeof(jlong) &&
+                                        std::is_integral_v<U>>>
+  operator std::span<const U>() const {  // NOLINT
+    auto arr = static_cast<const C*>(this)->array();
+    if (arr.empty()) {
+      return {};
+    }
+    return {reinterpret_cast<const U*>(arr.data()), arr.size()};
+  }
 };
 
 /**
@@ -206,9 +239,7 @@
  public:
   explicit operator bool() const { return this->m_elements != nullptr; }
 
-  operator span<const T>() const { return array(); }  // NOLINT
-
-  span<const T> array() const {
+  std::span<const T> array() const {
     if (!this->m_elements) {
       return {};
     }
@@ -375,7 +406,7 @@
 template <typename T,
           bool = (std::is_integral<T>::value && sizeof(jint) == sizeof(T))>
 struct ConvertIntArray {
-  static jintArray ToJava(JNIEnv* env, span<const T> arr) {
+  static jintArray ToJava(JNIEnv* env, std::span<const T> arr) {
     jintArray jarr = env->NewIntArray(arr.size());
     if (!jarr) {
       return nullptr;
@@ -398,7 +429,7 @@
  */
 template <typename T>
 struct ConvertIntArray<T, true> {
-  static jintArray ToJava(JNIEnv* env, span<const T> arr) {
+  static jintArray ToJava(JNIEnv* env, std::span<const T> arr) {
     jintArray jarr = env->NewIntArray(arr.size());
     if (!jarr) {
       return nullptr;
@@ -418,7 +449,7 @@
  * @param arr Span to convert.
  */
 template <typename T>
-inline jintArray MakeJIntArray(JNIEnv* env, span<const T> arr) {
+inline jintArray MakeJIntArray(JNIEnv* env, std::span<const T> arr) {
   return detail::ConvertIntArray<T>::ToJava(env, arr);
 }
 
@@ -429,7 +460,7 @@
  * @param arr Span to convert.
  */
 template <typename T>
-inline jintArray MakeJIntArray(JNIEnv* env, span<T> arr) {
+inline jintArray MakeJIntArray(JNIEnv* env, std::span<T> arr) {
   return detail::ConvertIntArray<T>::ToJava(env, arr);
 }
 
@@ -462,12 +493,12 @@
 }
 
 /**
- * Convert a std::string_view into a jbyteArray.
+ * Convert a span into a jbyteArray.
  *
  * @param env JRE environment.
- * @param str std::string_view to convert.
+ * @param str span to convert.
  */
-inline jbyteArray MakeJByteArray(JNIEnv* env, std::string_view str) {
+inline jbyteArray MakeJByteArray(JNIEnv* env, std::span<const uint8_t> str) {
   jbyteArray jarr = env->NewByteArray(str.size());
   if (!jarr) {
     return nullptr;
@@ -483,7 +514,7 @@
  * @param env JRE environment.
  * @param arr Array to convert.
  */
-inline jbooleanArray MakeJBooleanArray(JNIEnv* env, span<const int> arr) {
+inline jbooleanArray MakeJBooleanArray(JNIEnv* env, std::span<const int> arr) {
   jbooleanArray jarr = env->NewBooleanArray(arr.size());
   if (!jarr) {
     return nullptr;
@@ -506,7 +537,7 @@
  * @param env JRE environment.
  * @param arr Array to convert.
  */
-inline jbooleanArray MakeJBooleanArray(JNIEnv* env, span<const bool> arr) {
+inline jbooleanArray MakeJBooleanArray(JNIEnv* env, std::span<const bool> arr) {
   jbooleanArray jarr = env->NewBooleanArray(arr.size());
   if (!jarr) {
     return nullptr;
@@ -525,32 +556,45 @@
 
 // Other MakeJ*Array conversions.
 
-#define WPI_JNI_MAKEJARRAY(T, F)                                    \
-  inline T##Array MakeJ##F##Array(JNIEnv* env, span<const T> arr) { \
-    T##Array jarr = env->New##F##Array(arr.size());                 \
-    if (!jarr) {                                                    \
-      return nullptr;                                               \
-    }                                                               \
-    env->Set##F##ArrayRegion(jarr, 0, arr.size(), arr.data());      \
-    return jarr;                                                    \
+#define WPI_JNI_MAKEJARRAY(T, F)                                         \
+  inline T##Array MakeJ##F##Array(JNIEnv* env, std::span<const T> arr) { \
+    T##Array jarr = env->New##F##Array(arr.size());                      \
+    if (!jarr) {                                                         \
+      return nullptr;                                                    \
+    }                                                                    \
+    env->Set##F##ArrayRegion(jarr, 0, arr.size(), arr.data());           \
+    return jarr;                                                         \
   }
 
 WPI_JNI_MAKEJARRAY(jboolean, Boolean)
 WPI_JNI_MAKEJARRAY(jbyte, Byte)
 WPI_JNI_MAKEJARRAY(jshort, Short)
-WPI_JNI_MAKEJARRAY(jlong, Long)
 WPI_JNI_MAKEJARRAY(jfloat, Float)
 WPI_JNI_MAKEJARRAY(jdouble, Double)
 
 #undef WPI_JNI_MAKEJARRAY
 
+template <class T, typename = std::enable_if_t<
+                       sizeof(typename T::value_type) == sizeof(jlong) &&
+                       std::is_integral_v<typename T::value_type>>>
+inline jlongArray MakeJLongArray(JNIEnv* env, const T& arr) {
+  jlongArray jarr = env->NewLongArray(arr.size());
+  if (!jarr) {
+    return nullptr;
+  }
+  env->SetLongArrayRegion(jarr, 0, arr.size(),
+                          reinterpret_cast<const jlong*>(arr.data()));
+  return jarr;
+}
+
 /**
  * Convert an array of std::string into a jarray of jstring.
  *
  * @param env JRE environment.
  * @param arr Array to convert.
  */
-inline jobjectArray MakeJStringArray(JNIEnv* env, span<const std::string> arr) {
+inline jobjectArray MakeJStringArray(JNIEnv* env,
+                                     std::span<const std::string> arr) {
   static JClass stringCls{env, "java/lang/String"};
   if (!stringCls) {
     return nullptr;
@@ -572,7 +616,8 @@
  * @param env JRE environment.
  * @param arr Array to convert.
  */
-inline jobjectArray MakeJStringArray(JNIEnv* env, span<std::string_view> arr) {
+inline jobjectArray MakeJStringArray(JNIEnv* env,
+                                     std::span<std::string_view> arr) {
   static JClass stringCls{env, "java/lang/String"};
   if (!stringCls) {
     return nullptr;
diff --git a/wpiutil/src/main/native/include/wpi/leb128.h b/wpiutil/src/main/native/include/wpi/leb128.h
index 04752c6..e89d505 100644
--- a/wpiutil/src/main/native/include/wpi/leb128.h
+++ b/wpiutil/src/main/native/include/wpi/leb128.h
@@ -8,8 +8,7 @@
 #include <stdint.h>
 
 #include <optional>
-
-#include "wpi/span.h"
+#include <span>
 
 namespace wpi {
 
@@ -100,7 +99,7 @@
    *           is left when function returns).
    * @return value (in std::optional)
    */
-  std::optional<uint64_t> ReadOne(span<const uint8_t>* in);
+  std::optional<uint64_t> ReadOne(std::span<const uint8_t>* in);
 
  private:
   uint64_t m_result = 0;
diff --git a/wpiutil/src/main/native/include/wpi/math b/wpiutil/src/main/native/include/wpi/math
deleted file mode 100644
index 25f2a64..0000000
--- a/wpiutil/src/main/native/include/wpi/math
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include "wpi/numbers"
-
-// clang-format off
-#ifdef _MSC_VER
-#pragma message("warning: Use <wpi/numbers> and wpi::numbers instead to reflect C++20 <numbers> and std::numbers")
-#else
-#warning "Use <wpi/numbers> and wpi::numbers instead to reflect C++20 <numbers> and std::numbers"
-#endif
-
-// clang-format on
-
-namespace wpi::math {
-using namespace wpi::numbers;
-}  // namespace wpi::math
diff --git a/wpiutil/src/main/native/include/wpi/numbers b/wpiutil/src/main/native/include/wpi/numbers
deleted file mode 100644
index d45aee0..0000000
--- a/wpiutil/src/main/native/include/wpi/numbers
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <type_traits>
-
-namespace wpi::numbers {
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T e_v = 2.718281828459045235360287471352662498L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T log2e_v = 1.442695040888963407359924681001892137L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T log10e_v = 0.434294481903251827651128918916605082L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T pi_v = 3.141592653589793238462643383279502884L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T inv_pi_v = 0.318309886183790671537767526745028724L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T inv_sqrtpi_v = 0.564189583547756286948079451560772586L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T ln2_v = 0.693147180559945309417232121458176568L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T ln10_v = 2.302585092994045684017991454684364208L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T sqrt2_v = 1.414213562373095048801688724209698078L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T sqrt3_v = 1.732050807568877293527446341505872366L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T inv_sqrt3_v = 0.577350269189625764509148780501957456L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T egamma_v = 0.577215664901532860606512090082402431L;
-
-template <typename T, typename = std::enable_if_t<std::is_floating_point_v<T>>>
-inline constexpr T phi_v = 1.618033988749894848204586834365638117L;
-
-inline constexpr double e = e_v<double>;
-inline constexpr double log2e = log2e_v<double>;
-inline constexpr double log10e = log10e_v<double>;
-inline constexpr double pi = pi_v<double>;
-inline constexpr double inv_pi = inv_pi_v<double>;
-inline constexpr double inv_sqrtpi = inv_sqrtpi_v<double>;
-inline constexpr double ln2 = ln2_v<double>;
-inline constexpr double ln10 = ln10_v<double>;
-inline constexpr double sqrt2 = sqrt2_v<double>;
-inline constexpr double sqrt3 = sqrt3_v<double>;
-inline constexpr double inv_sqrt3 = inv_sqrt3_v<double>;
-inline constexpr double egamma = egamma_v<double>;
-inline constexpr double phi = phi_v<double>;
-
-}  // namespace wpi::numbers
diff --git a/wpiutil/src/main/native/include/wpi/raw_istream.h b/wpiutil/src/main/native/include/wpi/raw_istream.h
index 2371fc6..2f278c8 100644
--- a/wpiutil/src/main/native/include/wpi/raw_istream.h
+++ b/wpiutil/src/main/native/include/wpi/raw_istream.h
@@ -9,13 +9,13 @@
 
 #include <algorithm>
 #include <cstddef>
+#include <span>
 #include <string>
 #include <string_view>
 #include <system_error>
 #include <vector>
 
 #include "wpi/SmallVector.h"
-#include "wpi/span.h"
 
 namespace wpi {
 
@@ -133,9 +133,9 @@
   // not const as we don't want to allow temporaries
   explicit raw_mem_istream(std::string& str)
       : raw_mem_istream(str.data(), str.size()) {}
-  explicit raw_mem_istream(span<const char> mem)
+  explicit raw_mem_istream(std::span<const char> mem)
       : raw_mem_istream(mem.data(), mem.size()) {}
-  explicit raw_mem_istream(span<const uint8_t> mem)
+  explicit raw_mem_istream(std::span<const uint8_t> mem)
       : raw_mem_istream(reinterpret_cast<const char*>(mem.data()), mem.size()) {
   }
   explicit raw_mem_istream(const char* str)
diff --git a/wpiutil/src/main/native/include/wpi/raw_socket_istream.h b/wpiutil/src/main/native/include/wpi/raw_socket_istream.h
deleted file mode 100644
index f6899e2..0000000
--- a/wpiutil/src/main/native/include/wpi/raw_socket_istream.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_RAW_SOCKET_ISTREAM_H_
-#define WPIUTIL_WPI_RAW_SOCKET_ISTREAM_H_
-
-#include "wpi/raw_istream.h"
-
-namespace wpi {
-
-class NetworkStream;
-
-class raw_socket_istream : public raw_istream {
- public:
-  explicit raw_socket_istream(NetworkStream& stream, int timeout = 0)
-      : m_stream(stream), m_timeout(timeout) {}
-
-  void close() override;
-  size_t in_avail() const override;
-
- private:
-  void read_impl(void* data, size_t len) override;
-
-  NetworkStream& m_stream;
-  int m_timeout;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_RAW_SOCKET_ISTREAM_H_
diff --git a/wpiutil/src/main/native/include/wpi/raw_socket_ostream.h b/wpiutil/src/main/native/include/wpi/raw_socket_ostream.h
deleted file mode 100644
index 5cdeb41..0000000
--- a/wpiutil/src/main/native/include/wpi/raw_socket_ostream.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_RAW_SOCKET_OSTREAM_H_
-#define WPIUTIL_WPI_RAW_SOCKET_OSTREAM_H_
-
-#include "wpi/raw_ostream.h"
-
-namespace wpi {
-
-class NetworkStream;
-
-class raw_socket_ostream : public raw_ostream {
- public:
-  raw_socket_ostream(NetworkStream& stream, bool shouldClose)
-      : m_stream(stream), m_shouldClose(shouldClose) {}
-  ~raw_socket_ostream() override;
-
-  void close();
-
-  bool has_error() const { return m_error; }
-  void clear_error() { m_error = false; }
-
- protected:
-  void error_detected() { m_error = true; }
-
- private:
-  void write_impl(const char* data, size_t len) override;
-  uint64_t current_pos() const override;
-
-  NetworkStream& m_stream;
-  bool m_error = false;
-  bool m_shouldClose;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_RAW_SOCKET_OSTREAM_H_
diff --git a/wpiutil/src/main/native/include/wpi/raw_uv_ostream.h b/wpiutil/src/main/native/include/wpi/raw_uv_ostream.h
deleted file mode 100644
index 4773c61..0000000
--- a/wpiutil/src/main/native/include/wpi/raw_uv_ostream.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_RAW_UV_OSTREAM_H_
-#define WPIUTIL_WPI_RAW_UV_OSTREAM_H_
-
-#include <functional>
-#include <utility>
-
-#include "wpi/SmallVector.h"
-#include "wpi/raw_ostream.h"
-#include "wpi/span.h"
-#include "wpi/uv/Buffer.h"
-
-namespace wpi {
-
-/**
- * raw_ostream style output to a SmallVector of uv::Buffer buffers.  Fixed-size
- * buffers are allocated and appended as necessary to fit the data being output.
- * The SmallVector need not be empty at start.
- */
-class raw_uv_ostream : public raw_ostream {
- public:
-  /**
-   * Construct a new raw_uv_ostream.
-   * @param bufs Buffers vector.  NOT cleared on construction.
-   * @param allocSize Size to allocate for each buffer; allocation will be
-   *                  performed using Buffer::Allocate().
-   */
-  raw_uv_ostream(SmallVectorImpl<uv::Buffer>& bufs, size_t allocSize)
-      : m_bufs(bufs), m_alloc([=] { return uv::Buffer::Allocate(allocSize); }) {
-    SetUnbuffered();
-  }
-
-  /**
-   * Construct a new raw_uv_ostream.
-   * @param bufs Buffers vector.  NOT cleared on construction.
-   * @param alloc Allocator.
-   */
-  raw_uv_ostream(SmallVectorImpl<uv::Buffer>& bufs,
-                 std::function<uv::Buffer()> alloc)
-      : m_bufs(bufs), m_alloc(std::move(alloc)) {
-    SetUnbuffered();
-  }
-
-  ~raw_uv_ostream() override = default;
-
-  /**
-   * Returns an span to the buffers.
-   */
-  span<uv::Buffer> bufs() { return m_bufs; }
-
-  void flush() = delete;
-
-  /**
-   * Resets the amount of allocated space.
-   */
-  void reset() { m_left = 0; }
-
- private:
-  void write_impl(const char* data, size_t len) override;
-  uint64_t current_pos() const override;
-
-  SmallVectorImpl<uv::Buffer>& m_bufs;
-  std::function<uv::Buffer()> m_alloc;
-
-  // How much allocated space is left in the current buffer.
-  size_t m_left = 0;
-};
-
-}  // namespace wpi
-
-#endif  // WPIUTIL_WPI_RAW_UV_OSTREAM_H_
diff --git a/wpiutil/src/main/native/include/wpi/scope b/wpiutil/src/main/native/include/wpi/scope
new file mode 100644
index 0000000..e25badb
--- /dev/null
+++ b/wpiutil/src/main/native/include/wpi/scope
@@ -0,0 +1,37 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#pragma once
+
+#include <utility>
+
+namespace wpi {
+
+template <typename F>
+class scope_exit {
+ public:
+  explicit scope_exit(F&& f) noexcept : m_f{std::forward<F>(f)} {}
+
+  ~scope_exit() {
+    if (m_active) {
+      m_f();
+    }
+  }
+
+  scope_exit(scope_exit&& rhs) noexcept
+      : m_f{std::move(rhs.m_f)}, m_active{rhs.m_active} {
+    rhs.release();
+  }
+
+  scope_exit(const scope_exit&) = delete;
+  scope_exit& operator=(const scope_exit&) = delete;
+
+  void release() noexcept { m_active = false; }
+
+ private:
+  F m_f;
+  bool m_active = true;
+};
+
+}  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/sendable/SendableBuilder.h b/wpiutil/src/main/native/include/wpi/sendable/SendableBuilder.h
index e092a1e..2287b73 100644
--- a/wpiutil/src/main/native/include/wpi/sendable/SendableBuilder.h
+++ b/wpiutil/src/main/native/include/wpi/sendable/SendableBuilder.h
@@ -6,12 +6,12 @@
 
 #include <functional>
 #include <memory>
+#include <span>
 #include <string>
 #include <string_view>
 #include <vector>
 
 #include "wpi/SmallVector.h"
-#include "wpi/span.h"
 
 namespace wpi {
 
@@ -60,6 +60,28 @@
                                   std::function<void(bool)> setter) = 0;
 
   /**
+   * Add an integer property.
+   *
+   * @param key     property name
+   * @param getter  getter function (returns current value)
+   * @param setter  setter function (sets new value)
+   */
+  virtual void AddIntegerProperty(std::string_view key,
+                                  std::function<int64_t()> getter,
+                                  std::function<void(int64_t)> setter) = 0;
+
+  /**
+   * Add a float property.
+   *
+   * @param key     property name
+   * @param getter  getter function (returns current value)
+   * @param setter  setter function (sets new value)
+   */
+  virtual void AddFloatProperty(std::string_view key,
+                                std::function<float()> getter,
+                                std::function<void(float)> setter) = 0;
+
+  /**
    * Add a double property.
    *
    * @param key     property name
@@ -90,7 +112,29 @@
    */
   virtual void AddBooleanArrayProperty(
       std::string_view key, std::function<std::vector<int>()> getter,
-      std::function<void(wpi::span<const int>)> setter) = 0;
+      std::function<void(std::span<const int>)> setter) = 0;
+
+  /**
+   * Add an integer array property.
+   *
+   * @param key     property name
+   * @param getter  getter function (returns current value)
+   * @param setter  setter function (sets new value)
+   */
+  virtual void AddIntegerArrayProperty(
+      std::string_view key, std::function<std::vector<int64_t>()> getter,
+      std::function<void(std::span<const int64_t>)> setter) = 0;
+
+  /**
+   * Add a float array property.
+   *
+   * @param key     property name
+   * @param getter  getter function (returns current value)
+   * @param setter  setter function (sets new value)
+   */
+  virtual void AddFloatArrayProperty(
+      std::string_view key, std::function<std::vector<float>()> getter,
+      std::function<void(std::span<const float>)> setter) = 0;
 
   /**
    * Add a double array property.
@@ -101,7 +145,7 @@
    */
   virtual void AddDoubleArrayProperty(
       std::string_view key, std::function<std::vector<double>()> getter,
-      std::function<void(wpi::span<const double>)> setter) = 0;
+      std::function<void(std::span<const double>)> setter) = 0;
 
   /**
    * Add a string array property.
@@ -112,18 +156,20 @@
    */
   virtual void AddStringArrayProperty(
       std::string_view key, std::function<std::vector<std::string>()> getter,
-      std::function<void(wpi::span<const std::string>)> setter) = 0;
+      std::function<void(std::span<const std::string>)> setter) = 0;
 
   /**
    * Add a raw property.
    *
-   * @param key     property name
-   * @param getter  getter function (returns current value)
-   * @param setter  setter function (sets new value)
+   * @param key         property name
+   * @param typeString  type string
+   * @param getter      getter function (returns current value)
+   * @param setter      setter function (sets new value)
    */
-  virtual void AddRawProperty(std::string_view key,
-                              std::function<std::string()> getter,
-                              std::function<void(std::string_view)> setter) = 0;
+  virtual void AddRawProperty(
+      std::string_view key, std::string_view typeString,
+      std::function<std::vector<uint8_t>()> getter,
+      std::function<void(std::span<const uint8_t>)> setter) = 0;
 
   /**
    * Add a string property (SmallString form).
@@ -146,9 +192,36 @@
    */
   virtual void AddSmallBooleanArrayProperty(
       std::string_view key,
-      std::function<wpi::span<const int>(wpi::SmallVectorImpl<int>& buf)>
+      std::function<std::span<const int>(wpi::SmallVectorImpl<int>& buf)>
           getter,
-      std::function<void(wpi::span<const int>)> setter) = 0;
+      std::function<void(std::span<const int>)> setter) = 0;
+
+  /**
+   * Add an integer array property (SmallVector form).
+   *
+   * @param key     property name
+   * @param getter  getter function (returns current value)
+   * @param setter  setter function (sets new value)
+   */
+  virtual void AddSmallIntegerArrayProperty(
+      std::string_view key,
+      std::function<
+          std::span<const int64_t>(wpi::SmallVectorImpl<int64_t>& buf)>
+          getter,
+      std::function<void(std::span<const int64_t>)> setter) = 0;
+
+  /**
+   * Add a float array property (SmallVector form).
+   *
+   * @param key     property name
+   * @param getter  getter function (returns current value)
+   * @param setter  setter function (sets new value)
+   */
+  virtual void AddSmallFloatArrayProperty(
+      std::string_view key,
+      std::function<std::span<const float>(wpi::SmallVectorImpl<float>& buf)>
+          getter,
+      std::function<void(std::span<const float>)> setter) = 0;
 
   /**
    * Add a double array property (SmallVector form).
@@ -159,9 +232,9 @@
    */
   virtual void AddSmallDoubleArrayProperty(
       std::string_view key,
-      std::function<wpi::span<const double>(wpi::SmallVectorImpl<double>& buf)>
+      std::function<std::span<const double>(wpi::SmallVectorImpl<double>& buf)>
           getter,
-      std::function<void(wpi::span<const double>)> setter) = 0;
+      std::function<void(std::span<const double>)> setter) = 0;
 
   /**
    * Add a string array property (SmallVector form).
@@ -173,21 +246,23 @@
   virtual void AddSmallStringArrayProperty(
       std::string_view key,
       std::function<
-          wpi::span<const std::string>(wpi::SmallVectorImpl<std::string>& buf)>
+          std::span<const std::string>(wpi::SmallVectorImpl<std::string>& buf)>
           getter,
-      std::function<void(wpi::span<const std::string>)> setter) = 0;
+      std::function<void(std::span<const std::string>)> setter) = 0;
 
   /**
    * Add a raw property (SmallVector form).
    *
    * @param key     property name
+   * @param typeString  type string
    * @param getter  getter function (returns current value)
    * @param setter  setter function (sets new value)
    */
   virtual void AddSmallRawProperty(
-      std::string_view key,
-      std::function<std::string_view(wpi::SmallVectorImpl<char>& buf)> getter,
-      std::function<void(std::string_view)> setter) = 0;
+      std::string_view key, std::string_view typeString,
+      std::function<std::span<uint8_t>(wpi::SmallVectorImpl<uint8_t>& buf)>
+          getter,
+      std::function<void(std::span<const uint8_t>)> setter) = 0;
 
   /**
    * Gets the kind of backend being used.
diff --git a/wpiutil/src/main/native/include/wpi/sendable/SendableHelper.h b/wpiutil/src/main/native/include/wpi/sendable/SendableHelper.h
index 5b6bbe3..f8dd703 100644
--- a/wpiutil/src/main/native/include/wpi/sendable/SendableHelper.h
+++ b/wpiutil/src/main/native/include/wpi/sendable/SendableHelper.h
@@ -4,11 +4,6 @@
 
 #pragma once
 
-#include <memory>
-#include <string>
-#include <string_view>
-
-#include "wpi/deprecated.h"
 #include "wpi/sendable/SendableRegistry.h"
 
 namespace wpi {
@@ -48,123 +43,6 @@
     return *this;
   }
 
-  /**
-   * Gets the name of this Sendable object.
-   *
-   * @deprecated use SendableRegistry::GetName()
-   *
-   * @return Name
-   */
-  WPI_DEPRECATED("use SendableRegistry::GetName()")
-  std::string GetName() const {
-    return SendableRegistry::GetName(static_cast<const Derived*>(this));
-  }
-
-  /**
-   * Sets the name of this Sendable object.
-   *
-   * @deprecated use SendableRegistry::SetName()
-   *
-   * @param name name
-   */
-  WPI_DEPRECATED("use SendableRegistry::SetName()")
-  void SetName(std::string_view name) {
-    SendableRegistry::SetName(static_cast<Derived*>(this), name);
-  }
-
-  /**
-   * Sets both the subsystem name and device name of this Sendable object.
-   *
-   * @deprecated use SendableRegistry::SetName()
-   *
-   * @param subsystem subsystem name
-   * @param name device name
-   */
-  WPI_DEPRECATED("use SendableRegistry::SetName()")
-  void SetName(std::string_view subsystem, std::string_view name) {
-    SendableRegistry::SetName(static_cast<Derived*>(this), subsystem, name);
-  }
-
-  /**
-   * Gets the subsystem name of this Sendable object.
-   *
-   * @deprecated use SendableRegistry::GetSubsystem().
-   *
-   * @return Subsystem name
-   */
-  WPI_DEPRECATED("use SendableRegistry::GetSubsystem()")
-  std::string GetSubsystem() const {
-    return SendableRegistry::GetSubsystem(static_cast<const Derived*>(this));
-  }
-
-  /**
-   * Sets the subsystem name of this Sendable object.
-   *
-   * @deprecated use SendableRegistry::SetSubsystem()
-   *
-   * @param subsystem subsystem name
-   */
-  WPI_DEPRECATED("use SendableRegistry::SetSubsystem()")
-  void SetSubsystem(std::string_view subsystem) {
-    SendableRegistry::SetSubsystem(static_cast<Derived*>(this), subsystem);
-  }
-
- protected:
-  /**
-   * Add a child component.
-   *
-   * @deprecated use SendableRegistry::AddChild()
-   *
-   * @param child child component
-   */
-  WPI_DEPRECATED("use SendableRegistry::AddChild()")
-  void AddChild(std::shared_ptr<Sendable> child) {
-    SendableRegistry::AddChild(static_cast<Derived*>(this), child.get());
-  }
-
-  /**
-   * Add a child component.
-   *
-   * @deprecated use SendableRegistry::AddChild()
-   *
-   * @param child child component
-   */
-  WPI_DEPRECATED("use SendableRegistry::AddChild()")
-  void AddChild(void* child) {
-    SendableRegistry::AddChild(static_cast<Derived*>(this), child);
-  }
-
-  /**
-   * Sets the name of the sensor with a channel number.
-   *
-   * @deprecated use SendableRegistry::SetName()
-   *
-   * @param moduleType A string that defines the module name in the label for
-   *                   the value
-   * @param channel    The channel number the device is plugged into
-   */
-  WPI_DEPRECATED("use SendableRegistry::SetName()")
-  void SetName(std::string_view moduleType, int channel) {
-    SendableRegistry::SetName(static_cast<Derived*>(this), moduleType, channel);
-  }
-
-  /**
-   * Sets the name of the sensor with a module and channel number.
-   *
-   * @deprecated use SendableRegistry::SetName()
-   *
-   * @param moduleType   A string that defines the module name in the label for
-   *                     the value
-   * @param moduleNumber The number of the particular module type
-   * @param channel      The channel number the device is plugged into (usually
-   * PWM)
-   */
-  WPI_DEPRECATED("use SendableRegistry::SetName()")
-  void SetName(std::string_view moduleType, int moduleNumber, int channel) {
-    SendableRegistry::SetName(static_cast<Derived*>(this), moduleType,
-                              moduleNumber, channel);
-  }
-
  protected:
   SendableHelper() = default;
 
diff --git a/wpiutil/src/main/native/include/wpi/sendable/SendableRegistry.h b/wpiutil/src/main/native/include/wpi/sendable/SendableRegistry.h
index a08f9e9..4639749 100644
--- a/wpiutil/src/main/native/include/wpi/sendable/SendableRegistry.h
+++ b/wpiutil/src/main/native/include/wpi/sendable/SendableRegistry.h
@@ -20,7 +20,7 @@
  * The SendableRegistry class is the public interface for registering sensors
  * and actuators for use on dashboards and LiveWindow.
  */
-class SendableRegistry {
+class SendableRegistry final {
  public:
   SendableRegistry() = delete;
 
diff --git a/wpiutil/src/main/native/include/wpi/span.h b/wpiutil/src/main/native/include/wpi/span.h
deleted file mode 100644
index cf71d79..0000000
--- a/wpiutil/src/main/native/include/wpi/span.h
+++ /dev/null
@@ -1,415 +0,0 @@
-
-/*
-This is an implementation of C++20's std::span
-http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
-*/
-
-//          Copyright Tristan Brindle 2018.
-// Distributed under the Boost Software License, Version 1.0.
-//    (See accompanying file ../../LICENSE_1_0.txt or copy at
-//          https://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef WPIUTIL_WPI_SPAN_HPP_INCLUDED
-#define WPIUTIL_WPI_SPAN_HPP_INCLUDED
-
-#include <array>
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <type_traits>
-#if __cplusplus >= 202002L && __has_include(<span>)
-#include <span>
-#endif
-
-namespace wpi {
-
-inline constexpr std::size_t dynamic_extent = SIZE_MAX;
-
-template <typename ElementType, std::size_t Extent = dynamic_extent>
-class span;
-
-namespace detail {
-
-template <typename E, std::size_t S>
-struct span_storage {
-    constexpr span_storage() noexcept = default;
-
-    constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept
-       : ptr(p_ptr)
-    {}
-
-    E* ptr = nullptr;
-    static constexpr std::size_t size = S;
-};
-
-template <typename E>
-struct span_storage<E, dynamic_extent> {
-    constexpr span_storage() noexcept = default;
-
-    constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept
-        : ptr(p_ptr), size(p_size)
-    {}
-
-    E* ptr = nullptr;
-    std::size_t size = 0;
-};
-
-template <typename T>
-using uncvref_t =
-    typename std::remove_cv<typename std::remove_reference<T>::type>::type;
-
-template <typename>
-struct is_span : std::false_type {};
-
-template <typename T, std::size_t S>
-struct is_span<span<T, S>> : std::true_type {};
-
-template <typename>
-struct is_std_array : std::false_type {};
-
-template <typename T, std::size_t N>
-struct is_std_array<std::array<T, N>> : std::true_type {};
-
-template <typename, typename = void>
-struct has_size_and_data : std::false_type {};
-
-template <typename T>
-struct has_size_and_data<T, std::void_t<decltype(std::size(std::declval<T>())),
-                                   decltype(std::data(std::declval<T>()))>>
-    : std::true_type {};
-
-template <typename C, typename U = uncvref_t<C>>
-struct is_container {
-    static constexpr bool value =
-        !is_span<U>::value && !is_std_array<U>::value &&
-        !std::is_array<U>::value && has_size_and_data<C>::value;
-};
-
-template <typename T>
-using remove_pointer_t = typename std::remove_pointer<T>::type;
-
-template <typename, typename, typename = void>
-struct is_container_element_type_compatible : std::false_type {};
-
-template <typename T, typename E>
-struct is_container_element_type_compatible<
-    T, E,
-    typename std::enable_if<
-        !std::is_same<typename std::remove_cv<decltype(
-                          std::data(std::declval<T>()))>::type,
-                      void>::value>::type>
-    : std::is_convertible<
-          remove_pointer_t<decltype(std::data(std::declval<T>()))> (*)[],
-          E (*)[]> {};
-
-template <typename, typename = size_t>
-struct is_complete : std::false_type {};
-
-template <typename T>
-struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
-
-} // namespace detail
-
-template <typename ElementType, std::size_t Extent>
-class span {
-    static_assert(std::is_object<ElementType>::value,
-                  "A span's ElementType must be an object type (not a "
-                  "reference type or void)");
-    static_assert(detail::is_complete<ElementType>::value,
-                  "A span's ElementType must be a complete type (not a forward "
-                  "declaration)");
-    static_assert(!std::is_abstract<ElementType>::value,
-                  "A span's ElementType cannot be an abstract class type");
-
-    using storage_type = detail::span_storage<ElementType, Extent>;
-
-public:
-    // constants and types
-    using element_type = ElementType;
-    using value_type = typename std::remove_cv<ElementType>::type;
-    using size_type = std::size_t;
-    using difference_type = std::ptrdiff_t;
-    using pointer = element_type*;
-    using const_pointer = const element_type*;
-    using reference = element_type&;
-    using const_reference = const element_type&;
-    using iterator = pointer;
-    using reverse_iterator = std::reverse_iterator<iterator>;
-
-    static constexpr size_type extent = Extent;
-
-    // [span.cons], span constructors, copy, assignment, and destructor
-    template <
-        std::size_t E = Extent,
-        typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
-    constexpr span() noexcept
-    {}
-
-    constexpr span(pointer ptr, size_type count)
-        : storage_(ptr, count)
-    {
-        assert(extent == dynamic_extent || count == extent);
-    }
-
-    constexpr span(pointer first_elem, pointer last_elem)
-        : storage_(first_elem, last_elem - first_elem)
-    {
-        assert(extent == dynamic_extent ||
-                        last_elem - first_elem ==
-                            static_cast<std::ptrdiff_t>(extent));
-    }
-
-    template <std::size_t N, std::size_t E = Extent,
-              typename std::enable_if<
-                  (E == dynamic_extent || N == E) &&
-                      detail::is_container_element_type_compatible<
-                          element_type (&)[N], ElementType>::value,
-                  int>::type = 0>
-    constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
-    {}
-
-    template <std::size_t N, std::size_t E = Extent,
-              typename std::enable_if<
-                  (E == dynamic_extent || N == E) &&
-                      detail::is_container_element_type_compatible<
-                          std::array<value_type, N>&, ElementType>::value,
-                  int>::type = 0>
-    constexpr span(std::array<value_type, N>& arr) noexcept
-        : storage_(arr.data(), N)
-    {}
-
-    template <std::size_t N, std::size_t E = Extent,
-              typename std::enable_if<
-                  (E == dynamic_extent || N == E) &&
-                      detail::is_container_element_type_compatible<
-                          const std::array<value_type, N>&, ElementType>::value,
-                  int>::type = 0>
-    constexpr span(const std::array<value_type, N>& arr) noexcept
-        : storage_(arr.data(), N)
-    {}
-
-    template <
-        typename Container, std::size_t E = Extent,
-        typename std::enable_if<
-            E == dynamic_extent && detail::is_container<Container>::value &&
-                detail::is_container_element_type_compatible<
-                    Container&, ElementType>::value,
-            int>::type = 0>
-    constexpr span(Container& cont)
-        : storage_(std::data(cont), std::size(cont))
-    {}
-
-    template <
-        typename Container, std::size_t E = Extent,
-        typename std::enable_if<
-            E == dynamic_extent && detail::is_container<Container>::value &&
-                detail::is_container_element_type_compatible<
-                    const Container&, ElementType>::value,
-            int>::type = 0>
-    constexpr span(const Container& cont)
-        : storage_(std::data(cont), std::size(cont))
-    {}
-
-    constexpr span(const span& other) noexcept = default;
-
-    template <typename OtherElementType, std::size_t OtherExtent,
-              typename std::enable_if<
-                  (Extent == OtherExtent || Extent == dynamic_extent) &&
-                      std::is_convertible<OtherElementType (*)[],
-                                          ElementType (*)[]>::value,
-                  int>::type = 0>
-    constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
-        : storage_(other.data(), other.size())
-    {}
-
-#ifdef __cpp_lib_span
-    constexpr span(std::span<ElementType> other) noexcept
-        : storage_(other.data(), other.size())
-    {}
-#endif
-
-    ~span() noexcept = default;
-
-    constexpr span&
-    operator=(const span& other) noexcept = default;
-
-    // [span.sub], span subviews
-    template <std::size_t Count>
-    constexpr span<element_type, Count> first() const
-    {
-        assert(Count <= size());
-        return {data(), Count};
-    }
-
-    template <std::size_t Count>
-    constexpr span<element_type, Count> last() const
-    {
-        assert(Count <= size());
-        return {data() + (size() - Count), Count};
-    }
-
-    template <std::size_t Offset, std::size_t Count = dynamic_extent>
-    using subspan_return_t =
-        span<ElementType, Count != dynamic_extent
-                              ? Count
-                              : (Extent != dynamic_extent ? Extent - Offset
-                                                          : dynamic_extent)>;
-
-    template <std::size_t Offset, std::size_t Count = dynamic_extent>
-    constexpr subspan_return_t<Offset, Count> subspan() const
-    {
-        assert(Offset <= size() &&
-                        (Count == dynamic_extent || Offset + Count <= size()));
-        return {data() + Offset,
-                Count != dynamic_extent ? Count : size() - Offset};
-    }
-
-    constexpr span<element_type, dynamic_extent>
-    first(size_type count) const
-    {
-        assert(count <= size());
-        return {data(), count};
-    }
-
-    constexpr span<element_type, dynamic_extent>
-    last(size_type count) const
-    {
-        assert(count <= size());
-        return {data() + (size() - count), count};
-    }
-
-    constexpr span<element_type, dynamic_extent>
-    subspan(size_type offset, size_type count = dynamic_extent) const
-    {
-        assert(offset <= size() &&
-                        (count == dynamic_extent || offset + count <= size()));
-        return {data() + offset,
-                count == dynamic_extent ? size() - offset : count};
-    }
-
-    // [span.obs], span observers
-    constexpr size_type size() const noexcept { return storage_.size; }
-
-    constexpr size_type size_bytes() const noexcept
-    {
-        return size() * sizeof(element_type);
-    }
-
-    [[nodiscard]] constexpr bool empty() const noexcept
-    {
-        return size() == 0;
-    }
-
-    // [span.elem], span element access
-    constexpr reference operator[](size_type idx) const
-    {
-        assert(idx < size());
-        return *(data() + idx);
-    }
-
-    constexpr reference front() const
-    {
-        assert(!empty());
-        return *data();
-    }
-
-    constexpr reference back() const
-    {
-        assert(!empty());
-        return *(data() + (size() - 1));
-    }
-
-    constexpr pointer data() const noexcept { return storage_.ptr; }
-
-    // [span.iterators], span iterator support
-    constexpr iterator begin() const noexcept { return data(); }
-
-    constexpr iterator end() const noexcept { return data() + size(); }
-
-    constexpr reverse_iterator rbegin() const noexcept
-    {
-        return reverse_iterator(end());
-    }
-
-    constexpr reverse_iterator rend() const noexcept
-    {
-        return reverse_iterator(begin());
-    }
-
-#ifdef __cpp_lib_span
-    constexpr operator auto() const {
-      return std::span < ElementType,
-             (Extent == dynamic_extent)
-                 ? std::dynamic_extent
-                 : Extent > (storage_.ptr, storage_.size);
-    }
-#endif
-
-private:
-    storage_type storage_{};
-};
-
-/* Deduction Guides */
-template <class T, size_t N>
-span(T (&)[N])->span<T, N>;
-
-template <class T, size_t N>
-span(std::array<T, N>&)->span<T, N>;
-
-template <class T, size_t N>
-span(const std::array<T, N>&)->span<const T, N>;
-
-template <class Container>
-span(Container&)->span<typename Container::value_type>;
-
-template <class Container>
-span(const Container&)->span<const typename Container::value_type>;
-
-template <typename ElementType, std::size_t Extent>
-span<const std::byte, ((Extent == dynamic_extent) ? dynamic_extent
-                                             : sizeof(ElementType) * Extent)>
-as_bytes(span<ElementType, Extent> s) noexcept
-{
-    return {reinterpret_cast<const std::byte*>(s.data()), s.size_bytes()};
-}
-
-template <
-    class ElementType, size_t Extent,
-    typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
-span<std::byte, ((Extent == dynamic_extent) ? dynamic_extent
-                                       : sizeof(ElementType) * Extent)>
-as_writable_bytes(span<ElementType, Extent> s) noexcept
-{
-    return {reinterpret_cast<std::byte*>(s.data()), s.size_bytes()};
-}
-
-template <std::size_t N, typename E, std::size_t S>
-constexpr auto get(span<E, S> s) -> decltype(s[N])
-{
-    return s[N];
-}
-
-} // namespace wpi
-
-namespace std {
-
-template <typename ElementType, size_t Extent>
-class tuple_size<wpi::span<ElementType, Extent>>
-    : public integral_constant<size_t, Extent> {};
-
-template <typename ElementType>
-class tuple_size<wpi::span<
-    ElementType, wpi::dynamic_extent>>; // not defined
-
-template <size_t I, typename ElementType, size_t Extent>
-class tuple_element<I, wpi::span<ElementType, Extent>> {
-public:
-    static_assert(Extent != wpi::dynamic_extent &&
-                      I < Extent,
-                  "");
-    using type = ElementType;
-};
-
-} // end namespace std
-
-#endif // WPIUTIL_WPI_SPAN_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/include/wpi/spinlock.h b/wpiutil/src/main/native/include/wpi/spinlock.h
index 9e777fa..7128a18 100644
--- a/wpiutil/src/main/native/include/wpi/spinlock.h
+++ b/wpiutil/src/main/native/include/wpi/spinlock.h
@@ -9,7 +9,7 @@
 #include <mutex>
 #include <thread>
 
-#include "Compiler.h"
+#include "wpi/Compiler.h"
 
 namespace wpi {
 
diff --git a/wpiutil/src/main/native/include/wpi/static_circular_buffer.h b/wpiutil/src/main/native/include/wpi/static_circular_buffer.h
index 8cbf3fe..76498a1 100644
--- a/wpiutil/src/main/native/include/wpi/static_circular_buffer.h
+++ b/wpiutil/src/main/native/include/wpi/static_circular_buffer.h
@@ -38,10 +38,7 @@
       ++(*this);
       return retval;
     }
-    bool operator==(const iterator& other) const {
-      return m_buffer == other.m_buffer && m_index == other.m_index;
-    }
-    bool operator!=(const iterator& other) const { return !(*this == other); }
+    bool operator==(const iterator&) const = default;
     reference operator*() { return (*m_buffer)[m_index]; }
 
    private:
@@ -69,12 +66,7 @@
       ++(*this);
       return retval;
     }
-    bool operator==(const const_iterator& other) const {
-      return m_buffer == other.m_buffer && m_index == other.m_index;
-    }
-    bool operator!=(const const_iterator& other) const {
-      return !(*this == other);
-    }
+    bool operator==(const const_iterator&) const = default;
     const_reference operator*() const { return (*m_buffer)[m_index]; }
 
    private:
diff --git a/wpiutil/src/main/native/include/wpi/type_traits.h b/wpiutil/src/main/native/include/wpi/type_traits.h
deleted file mode 100644
index 5d35ee1..0000000
--- a/wpiutil/src/main/native/include/wpi/type_traits.h
+++ /dev/null
@@ -1,125 +0,0 @@
-//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides useful additions to the standard type_traits library.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef WPIUTIL_WPI_TYPE_TRAITS_H
-#define WPIUTIL_WPI_TYPE_TRAITS_H
-
-#include "wpi/Compiler.h"
-#include <type_traits>
-#include <utility>
-
-#ifndef __has_feature
-#define WPI_DEFINED_HAS_FEATURE
-#define __has_feature(x) 0
-#endif
-
-namespace wpi {
-
-/// isPodLike - This is a type trait that is used to determine whether a given
-/// type can be copied around with memcpy instead of running ctors etc.
-template <typename T>
-struct isPodLike {
-  // std::is_trivially_copyable is available in libc++ with clang, libstdc++
-  // that comes with GCC 5.
-#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) ||      \
-    (defined(__GNUC__) && __GNUC__ >= 5)
-  // If the compiler supports the is_trivially_copyable trait use it, as it
-  // matches the definition of isPodLike closely.
-  static const bool value = std::is_trivially_copyable<T>::value;
-#elif __has_feature(is_trivially_copyable)
-  // Use the internal name if the compiler supports is_trivially_copyable but we
-  // don't know if the standard library does. This is the case for clang in
-  // conjunction with libstdc++ from GCC 4.x.
-  static const bool value = __is_trivially_copyable(T);
-#else
-  // If we don't know anything else, we can (at least) assume that all non-class
-  // types are PODs.
-  static const bool value = !std::is_class<T>::value;
-#endif
-};
-
-// std::pair's are pod-like if their elements are.
-template<typename T, typename U>
-struct isPodLike<std::pair<T, U>> {
-  static const bool value = isPodLike<T>::value && isPodLike<U>::value;
-};
-
-/// Metafunction that determines whether the given type is either an
-/// integral type or an enumeration type, including enum classes.
-///
-/// Note that this accepts potentially more integral types than is_integral
-/// because it is based on being implicitly convertible to an integral type.
-/// Also note that enum classes aren't implicitly convertible to integral types,
-/// the value may therefore need to be explicitly converted before being used.
-template <typename T> class is_integral_or_enum {
-  using UnderlyingT = typename std::remove_reference<T>::type;
-
-public:
-  static const bool value =
-      !std::is_class<UnderlyingT>::value && // Filter conversion operators.
-      !std::is_pointer<UnderlyingT>::value &&
-      !std::is_floating_point<UnderlyingT>::value &&
-      (std::is_enum<UnderlyingT>::value ||
-       std::is_convertible<UnderlyingT, unsigned long long>::value);
-};
-
-/// If T is a pointer, just return it. If it is not, return T&.
-template<typename T, typename Enable = void>
-struct add_lvalue_reference_if_not_pointer { using type = T &; };
-
-template <typename T>
-struct add_lvalue_reference_if_not_pointer<
-    T, typename std::enable_if<std::is_pointer<T>::value>::type> {
-  using type = T;
-};
-
-/// If T is a pointer to X, return a pointer to const X. If it is not,
-/// return const T.
-template<typename T, typename Enable = void>
-struct add_const_past_pointer { using type = const T; };
-
-template <typename T>
-struct add_const_past_pointer<
-    T, typename std::enable_if<std::is_pointer<T>::value>::type> {
-  using type = const typename std::remove_pointer<T>::type *;
-};
-
-template <typename T, typename Enable = void>
-struct const_pointer_or_const_ref {
-  using type = const T &;
-};
-template <typename T>
-struct const_pointer_or_const_ref<
-    T, typename std::enable_if<std::is_pointer<T>::value>::type> {
-  using type = typename add_const_past_pointer<T>::type;
-};
-
-} // namespace wpi
-
-// If the compiler supports detecting whether a class is final, define
-// an LLVM_IS_FINAL macro. If it cannot be defined properly, this
-// macro will be left undefined.
-#ifndef LLVM_IS_FINAL
-#if __cplusplus >= 201402L || defined(_MSC_VER)
-#define LLVM_IS_FINAL(Ty) std::is_final<Ty>()
-#elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0)
-#define LLVM_IS_FINAL(Ty) __is_final(Ty)
-#endif
-#endif
-
-#ifdef WPI_DEFINED_HAS_FEATURE
-#undef __has_feature
-#undef WPI_DEFINED_HAS_FEATURE
-#endif
-
-#endif // LLVM_SUPPORT_TYPE_TRAITS_H
diff --git a/wpiutil/src/main/native/include/wpi/uv/Async.h b/wpiutil/src/main/native/include/wpi/uv/Async.h
deleted file mode 100644
index 49f3dde..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Async.h
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_ASYNC_H_
-#define WPIUTIL_WPI_UV_ASYNC_H_
-
-#include <uv.h>
-
-#include <memory>
-#include <thread>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "wpi/Signal.h"
-#include "wpi/mutex.h"
-#include "wpi/uv/Handle.h"
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-/**
- * Async handle.
- * Async handles allow the user to "wakeup" the event loop and have a signal
- * generated from another thread.
- *
- * Data may be passed into the callback called on the event loop by using
- * template parameters.  If data parameters are used, the async callback will
- * be called once for every call to Send().  If no data parameters are used,
- * the async callback may or may not be called for every call to Send() (e.g.
- * the calls may be coaleasced).
- */
-template <typename... T>
-class Async final : public HandleImpl<Async<T...>, uv_async_t> {
-  struct private_init {};
-
- public:
-  Async(const std::shared_ptr<Loop>& loop, const private_init&)
-      : m_loop{loop} {}
-  ~Async() noexcept override {
-    if (auto loop = m_loop.lock()) {
-      this->Close();
-    } else {
-      this->ForceClosed();
-    }
-  }
-
-  /**
-   * Create an async handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Async> Create(Loop& loop) {
-    return Create(loop.shared_from_this());
-  }
-
-  /**
-   * Create an async handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Async> Create(const std::shared_ptr<Loop>& loop) {
-    auto h = std::make_shared<Async>(loop, private_init{});
-    int err =
-        uv_async_init(loop->GetRaw(), h->GetRaw(), [](uv_async_t* handle) {
-          auto& h = *static_cast<Async*>(handle->data);
-          std::scoped_lock lock(h.m_mutex);
-          for (auto&& v : h.m_data) {
-            std::apply(h.wakeup, v);
-          }
-          h.m_data.clear();
-        });
-    if (err < 0) {
-      loop->ReportError(err);
-      return nullptr;
-    }
-    h->Keep();
-    return h;
-  }
-
-  /**
-   * Wakeup the event loop and emit the event.
-   *
-   * It’s safe to call this function from any thread including the loop thread.
-   * An async event will be emitted on the loop thread.
-   */
-  template <typename... U>
-  void Send(U&&... u) {
-    auto loop = m_loop.lock();
-    if (loop && loop->GetThreadId() == std::this_thread::get_id()) {
-      // called from within the loop, just call the function directly
-      wakeup(std::forward<U>(u)...);
-      return;
-    }
-
-    {
-      std::scoped_lock lock(m_mutex);
-      m_data.emplace_back(std::forward_as_tuple(std::forward<U>(u)...));
-    }
-    if (loop) {
-      this->Invoke(&uv_async_send, this->GetRaw());
-    }
-  }
-
-  /**
-   * Signal generated (on event loop thread) when the async event occurs.
-   */
-  sig::Signal<T...> wakeup;
-
- private:
-  wpi::mutex m_mutex;
-  std::vector<std::tuple<T...>> m_data;
-  std::weak_ptr<Loop> m_loop;
-};
-
-/**
- * Async specialization for no data parameters.  The async callback may or may
- * not be called for every call to Send() (e.g. the calls may be coaleasced).
- */
-template <>
-class Async<> final : public HandleImpl<Async<>, uv_async_t> {
-  struct private_init {};
-
- public:
-  Async(const std::shared_ptr<Loop>& loop, const private_init&)
-      : m_loop(loop) {}
-  ~Async() noexcept override;
-
-  /**
-   * Create an async handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Async> Create(Loop& loop) {
-    return Create(loop.shared_from_this());
-  }
-
-  /**
-   * Create an async handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Async> Create(const std::shared_ptr<Loop>& loop);
-
-  /**
-   * Wakeup the event loop and emit the event.
-   *
-   * It’s safe to call this function from any thread.
-   * An async event will be emitted on the loop thread.
-   */
-  void Send() {
-    if (auto loop = m_loop.lock()) {
-      if (loop->GetThreadId() == std::this_thread::get_id()) {
-        // called from within the loop, just call the function directly
-        wakeup();
-      } else {
-        Invoke(&uv_async_send, GetRaw());
-      }
-    }
-  }
-
-  /**
-   * Signal generated (on event loop thread) when the async event occurs.
-   */
-  sig::Signal<> wakeup;
-
- private:
-  std::weak_ptr<Loop> m_loop;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_ASYNC_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/AsyncFunction.h b/wpiutil/src/main/native/include/wpi/uv/AsyncFunction.h
deleted file mode 100644
index fa4eb90..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/AsyncFunction.h
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_ASYNCFUNCTION_H_
-#define WPIUTIL_WPI_UV_ASYNCFUNCTION_H_
-
-#include <stdint.h>
-#include <uv.h>
-
-#include <functional>
-#include <memory>
-#include <thread>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "wpi/future.h"
-#include "wpi/mutex.h"
-#include "wpi/uv/Handle.h"
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-template <typename T>
-class AsyncFunction;
-
-/**
- * Function async handle.
- * Async handles allow the user to "wakeup" the event loop and have a function
- * called from another thread that returns a result to the calling thread.
- */
-template <typename R, typename... T>
-class AsyncFunction<R(T...)> final
-    : public HandleImpl<AsyncFunction<R(T...)>, uv_async_t> {
-  struct private_init {};
-
- public:
-  AsyncFunction(const std::shared_ptr<Loop>& loop,
-                std::function<void(promise<R>, T...)> func, const private_init&)
-      : wakeup{std::move(func)}, m_loop{loop} {}
-  ~AsyncFunction() noexcept override {
-    if (auto loop = m_loop.lock()) {
-      this->Close();
-    } else {
-      this->ForceClosed();
-    }
-  }
-
-  /**
-   * Create an async handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param func wakeup function to be called (sets wakeup value); the function
-   *             needs to return void, and its first parameter is the promise
-   *             for the result.  If no value is set on the promise by the
-   *             wakeup function, a default-constructed value is "returned".
-   */
-  static std::shared_ptr<AsyncFunction> Create(
-      Loop& loop, std::function<void(promise<R>, T...)> func = nullptr) {
-    return Create(loop.shared_from_this(), std::move(func));
-  }
-
-  /**
-   * Create an async handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param func wakeup function to be called (sets wakeup value); the function
-   *             needs to return void, and its first parameter is the promise
-   *             for the result.  If no value is set on the promise by the
-   *             wakeup function, a default-constructed value is "returned".
-   */
-  static std::shared_ptr<AsyncFunction> Create(
-      const std::shared_ptr<Loop>& loop,
-      std::function<void(promise<R>, T...)> func = nullptr) {
-    auto h =
-        std::make_shared<AsyncFunction>(loop, std::move(func), private_init{});
-    int err =
-        uv_async_init(loop->GetRaw(), h->GetRaw(), [](uv_async_t* handle) {
-          auto& h = *static_cast<AsyncFunction*>(handle->data);
-          std::unique_lock lock(h.m_mutex);
-
-          if (!h.m_params.empty()) {
-            // for each set of parameters in the input queue, call the wakeup
-            // function and put the result in the output queue if the caller is
-            // waiting for it
-            for (auto&& v : h.m_params) {
-              auto p = h.m_promises.CreatePromise(v.first);
-              if (h.wakeup) {
-                std::apply(h.wakeup,
-                           std::tuple_cat(std::make_tuple(std::move(p)),
-                                          std::move(v.second)));
-              }
-            }
-            h.m_params.clear();
-            // wake up any threads that might be waiting for the result
-            lock.unlock();
-            h.m_promises.Notify();
-          }
-        });
-    if (err < 0) {
-      loop->ReportError(err);
-      return nullptr;
-    }
-    h->Keep();
-    return h;
-  }
-
-  /**
-   * Wakeup the event loop, call the async function, and return a future for
-   * the result.
-   *
-   * It’s safe to call this function from any thread including the loop thread.
-   * The async function will be called on the loop thread.
-   *
-   * The future will return a default-constructed result if this handle is
-   * destroyed while waiting for a result.
-   */
-  template <typename... U>
-  future<R> Call(U&&... u) {
-    // create the future
-    uint64_t req = m_promises.CreateRequest();
-
-    auto loop = m_loop.lock();
-    if (loop && loop->GetThreadId() == std::this_thread::get_id()) {
-      // called from within the loop, just call the function directly
-      wakeup(m_promises.CreatePromise(req), std::forward<U>(u)...);
-      return m_promises.CreateFuture(req);
-    }
-
-    // add the parameters to the input queue
-    {
-      std::scoped_lock lock(m_mutex);
-      m_params.emplace_back(std::piecewise_construct,
-                            std::forward_as_tuple(req),
-                            std::forward_as_tuple(std::forward<U>(u)...));
-    }
-
-    // signal the loop
-    if (loop) {
-      this->Invoke(&uv_async_send, this->GetRaw());
-    }
-
-    // return future
-    return m_promises.CreateFuture(req);
-  }
-
-  template <typename... U>
-  future<R> operator()(U&&... u) {
-    return Call(std::forward<U>(u)...);
-  }
-
-  /**
-   * Function called (on event loop thread) when the async is called.
-   */
-  std::function<void(promise<R>, T...)> wakeup;
-
- private:
-  wpi::mutex m_mutex;
-  std::vector<std::pair<uint64_t, std::tuple<T...>>> m_params;
-  PromiseFactory<R> m_promises;
-  std::weak_ptr<Loop> m_loop;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_ASYNCFUNCTION_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Buffer.h b/wpiutil/src/main/native/include/wpi/uv/Buffer.h
deleted file mode 100644
index 5126841..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Buffer.h
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_BUFFER_H_
-#define WPIUTIL_WPI_UV_BUFFER_H_
-
-#include <uv.h>
-
-#include <cstring>
-#include <initializer_list>
-#include <string_view>
-#include <utility>
-
-#include "wpi/SmallVector.h"
-#include "wpi/span.h"
-
-namespace wpi::uv {
-
-/**
- * Data buffer.  Convenience wrapper around uv_buf_t.
- */
-class Buffer : public uv_buf_t {
- public:
-  Buffer() {
-    base = nullptr;
-    len = 0;
-  }
-  /*implicit*/ Buffer(const uv_buf_t& oth) {  // NOLINT
-    base = oth.base;
-    len = oth.len;
-  }
-  /*implicit*/ Buffer(std::string_view str)  // NOLINT
-      : Buffer{str.data(), str.size()} {}
-  /*implicit*/ Buffer(span<const uint8_t> arr)  // NOLINT
-      : Buffer{reinterpret_cast<const char*>(arr.data()), arr.size()} {}
-  Buffer(char* base_, size_t len_) {
-    base = base_;
-    len = static_cast<decltype(len)>(len_);
-  }
-  Buffer(const char* base_, size_t len_) {
-    base = const_cast<char*>(base_);
-    len = static_cast<decltype(len)>(len_);
-  }
-
-  span<const char> data() const { return {base, len}; }
-  span<char> data() { return {base, len}; }
-
-  operator span<const char>() const { return data(); }  // NOLINT
-  operator span<char>() { return data(); }              // NOLINT
-
-  static Buffer Allocate(size_t size) { return Buffer{new char[size], size}; }
-
-  static Buffer Dup(std::string_view in) {
-    Buffer buf = Allocate(in.size());
-    std::memcpy(buf.base, in.data(), in.size());
-    return buf;
-  }
-
-  static Buffer Dup(span<const uint8_t> in) {
-    Buffer buf = Allocate(in.size());
-    std::memcpy(buf.base, in.begin(), in.size());
-    return buf;
-  }
-
-  Buffer Dup() const {
-    Buffer buf = Allocate(len);
-    std::memcpy(buf.base, base, len);
-    return buf;
-  }
-
-  void Deallocate() {
-    delete[] base;
-    base = nullptr;
-    len = 0;
-  }
-
-  Buffer Move() {
-    Buffer buf = *this;
-    base = nullptr;
-    len = 0;
-    return buf;
-  }
-
-  friend void swap(Buffer& a, Buffer& b) {
-    using std::swap;
-    swap(a.base, b.base);
-    swap(a.len, b.len);
-  }
-};
-
-/**
- * A simple pool allocator for Buffers.
- * Buffers are allocated individually but are reused rather than returned
- * to the heap.
- * @tparam DEPTH depth of pool
- */
-template <size_t DEPTH = 4>
-class SimpleBufferPool {
- public:
-  /**
-   * Constructor.
-   * @param size Size of each buffer to allocate.
-   */
-  explicit SimpleBufferPool(size_t size = 4096) : m_size{size} {}
-  ~SimpleBufferPool() { Clear(); }
-
-  SimpleBufferPool(const SimpleBufferPool& other) = delete;
-  SimpleBufferPool& operator=(const SimpleBufferPool& other) = delete;
-
-  /**
-   * Allocate a buffer.
-   */
-  Buffer Allocate() {
-    if (m_pool.empty()) {
-      return Buffer::Allocate(m_size);
-    }
-    auto buf = m_pool.back();
-    m_pool.pop_back();
-    buf.len = m_size;
-    return buf;
-  }
-
-  /**
-   * Allocate a buffer.
-   */
-  Buffer operator()() { return Allocate(); }
-
-  /**
-   * Release allocated buffers back into the pool.
-   * This is NOT safe to use with arbitrary buffers unless they were
-   * allocated with the same size as the buffer pool allocation size.
-   */
-  void Release(span<Buffer> bufs) {
-    for (auto& buf : bufs) {
-      m_pool.emplace_back(buf.Move());
-    }
-  }
-
-  /**
-   * Clear the pool, releasing all buffers.
-   */
-  void Clear() {
-    for (auto& buf : m_pool) {
-      buf.Deallocate();
-    }
-    m_pool.clear();
-  }
-
-  /**
-   * Get number of buffers left in the pool before a new buffer will be
-   * allocated from the heap.
-   */
-  size_t Remaining() const { return m_pool.size(); }
-
- private:
-  SmallVector<Buffer, DEPTH> m_pool;
-  size_t m_size;  // NOLINT
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_BUFFER_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Check.h b/wpiutil/src/main/native/include/wpi/uv/Check.h
deleted file mode 100644
index 7555452..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Check.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_CHECK_H_
-#define WPIUTIL_WPI_UV_CHECK_H_
-
-#include <uv.h>
-
-#include <memory>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Handle.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * Check handle.
- * Check handles will generate a signal once per loop iteration, right
- * after polling for I/O.
- */
-class Check final : public HandleImpl<Check, uv_check_t> {
-  struct private_init {};
-
- public:
-  explicit Check(const private_init&) {}
-  ~Check() noexcept override = default;
-
-  /**
-   * Create a check handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Check> Create(Loop& loop);
-
-  /**
-   * Create a check handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Check> Create(const std::shared_ptr<Loop>& loop) {
-    return Create(*loop);
-  }
-
-  /**
-   * Start the handle.
-   */
-  void Start();
-
-  /**
-   * Stop the handle.  The signal will no longer be generated.
-   */
-  void Stop() { Invoke(&uv_check_stop, GetRaw()); }
-
-  /**
-   * Signal generated once per loop iteration after polling for I/O.
-   */
-  sig::Signal<> check;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_CHECK_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Error.h b/wpiutil/src/main/native/include/wpi/uv/Error.h
deleted file mode 100644
index 1e717a4..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Error.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_ERROR_H_
-#define WPIUTIL_WPI_UV_ERROR_H_
-
-#include <uv.h>
-
-namespace wpi::uv {
-
-/**
- * Error code.
- */
-class Error {
- public:
-  Error() = default;
-  explicit Error(int err) : m_err(err) {}
-
-  /**
-   * Boolean conversion.  Returns true if error, false if ok.
-   */
-  explicit operator bool() const { return m_err < 0; }
-
-  /**
-   * Returns the error code.
-   */
-  int code() const { return m_err; }
-
-  /**
-   * Returns the error message.
-   */
-  const char* str() const { return uv_strerror(m_err); }
-
-  /**
-   * Returns the error name.
-   */
-  const char* name() const { return uv_err_name(m_err); }
-
- private:
-  int m_err{UV_UNKNOWN};
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_ERROR_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/FsEvent.h b/wpiutil/src/main/native/include/wpi/uv/FsEvent.h
deleted file mode 100644
index 0ed2dcb..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/FsEvent.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_FSEVENT_H_
-#define WPIUTIL_WPI_UV_FSEVENT_H_
-
-#include <uv.h>
-
-#include <memory>
-#include <string>
-#include <string_view>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Handle.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * Filesystem Event handle.
- */
-class FsEvent final : public HandleImpl<FsEvent, uv_fs_event_t> {
-  struct private_init {};
-
- public:
-  explicit FsEvent(const private_init&) {}
-  ~FsEvent() noexcept override = default;
-
-  /**
-   * Create a filesystem event handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<FsEvent> Create(Loop& loop);
-
-  /**
-   * Create a filesystem event handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<FsEvent> Create(const std::shared_ptr<Loop>& loop) {
-    return Create(*loop);
-  }
-
-  /**
-   * Start watching the specified path for changes.
-   *
-   * @param path Path to watch for changes
-   * @param events Bitmask of event flags.  Only UV_FS_EVENT_RECURSIVE is
-   *               supported (and only on OSX and Windows).
-   */
-  void Start(std::string_view path, unsigned int flags = 0);
-
-  /**
-   * Stop watching for changes.
-   */
-  void Stop() { Invoke(&uv_fs_event_stop, GetRaw()); }
-
-  /**
-   * Get the path being monitored.  Signals error and returns empty string if
-   * an error occurs.
-   * @return Monitored path.
-   */
-  std::string GetPath();
-
-  /**
-   * Signal generated when a filesystem change occurs.  The first parameter
-   * is the filename (if a directory was passed to Start(), the filename is
-   * relative to that directory).  The second parameter is an ORed mask of
-   * UV_RENAME and UV_CHANGE.
-   */
-  sig::Signal<const char*, int> fsEvent;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_FSEVENT_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/GetAddrInfo.h b/wpiutil/src/main/native/include/wpi/uv/GetAddrInfo.h
deleted file mode 100644
index 18d4f32..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/GetAddrInfo.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_GETADDRINFO_H_
-#define WPIUTIL_WPI_UV_GETADDRINFO_H_
-
-#include <uv.h>
-
-#include <functional>
-#include <memory>
-#include <string_view>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Request.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * GetAddrInfo request.
- * For use with `GetAddrInfo()` function family.
- */
-class GetAddrInfoReq : public RequestImpl<GetAddrInfoReq, uv_getaddrinfo_t> {
- public:
-  GetAddrInfoReq();
-
-  Loop& GetLoop() const { return *static_cast<Loop*>(GetRaw()->loop->data); }
-
-  /**
-   * Resolved lookup signal.
-   * Parameter is resolved address info.
-   */
-  sig::Signal<const addrinfo&> resolved;
-};
-
-/**
- * Asynchronous getaddrinfo(3).  HandleResolvedAddress() is called on the
- * request when the resolution completes.  HandleError() is called on the
- * request if any errors occur.
- *
- * Either node or service may be empty but not both.
- *
- * @param loop Event loop
- * @param req request
- * @param node Either a numerical network address or a network hostname.
- * @param service Either a service name or a port number as a string.
- * @param hints Optional `addrinfo` data structure with additional address
- *              type constraints.
- */
-void GetAddrInfo(Loop& loop, const std::shared_ptr<GetAddrInfoReq>& req,
-                 std::string_view node, std::string_view service = {},
-                 const addrinfo* hints = nullptr);
-
-/**
- * Asynchronous getaddrinfo(3).  HandleResolvedAddress() is called on the
- * request when the resolution completes.  HandleError() is called on the
- * request if any errors occur.
- *
- * Either node or service may be empty but not both.
- *
- * @param loop Event loop
- * @param req request
- * @param node Either a numerical network address or a network hostname.
- * @param service Either a service name or a port number as a string.
- * @param hints Optional `addrinfo` data structure with additional address
- *              type constraints.
- */
-inline void GetAddrInfo(const std::shared_ptr<Loop>& loop,
-                        const std::shared_ptr<GetAddrInfoReq>& req,
-                        std::string_view node, std::string_view service = {},
-                        const addrinfo* hints = nullptr) {
-  GetAddrInfo(*loop, req, node, service, hints);
-}
-
-/**
- * Asynchronous getaddrinfo(3).  The callback is called when the resolution
- * completes, and errors are forwarded to the loop.  This is a convenience
- * wrapper.
- *
- * Either node or service may be empty but not both.
- *
- * @param loop Event loop
- * @param callback Callback function to call when resolution completes
- * @param node Either a numerical network address or a network hostname.
- * @param service Either a service name or a port number as a string.
- * @param hints Optional `addrinfo` data structure with additional address
- *              type constraints.
- */
-void GetAddrInfo(Loop& loop, std::function<void(const addrinfo&)> callback,
-                 std::string_view node, std::string_view service = {},
-                 const addrinfo* hints = nullptr);
-
-/**
- * Asynchronous getaddrinfo(3).  The callback is called when the resolution
- * completes, and errors are forwarded to the loop.  This is a convenience
- * wrapper.
- *
- * Either node or service may be empty but not both.
- *
- * @param loop Event loop
- * @param callback Callback function to call when resolution completes
- * @param node Either a numerical network address or a network hostname.
- * @param service Either a service name or a port number as a string.
- * @param hints Optional `addrinfo` data structure with additional address
- *              type constraints.
- */
-inline void GetAddrInfo(const std::shared_ptr<Loop>& loop,
-                        std::function<void(const addrinfo&)> callback,
-                        std::string_view node, std::string_view service = {},
-                        const addrinfo* hints = nullptr) {
-  GetAddrInfo(*loop, std::move(callback), node, service, hints);
-}
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_GETADDRINFO_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/GetNameInfo.h b/wpiutil/src/main/native/include/wpi/uv/GetNameInfo.h
deleted file mode 100644
index d35dd95..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/GetNameInfo.h
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_GETNAMEINFO_H_
-#define WPIUTIL_WPI_UV_GETNAMEINFO_H_
-
-#include <uv.h>
-
-#include <functional>
-#include <memory>
-#include <string_view>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Request.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * GetNameInfo request.
- * For use with `GetNameInfo()` function family.
- */
-class GetNameInfoReq : public RequestImpl<GetNameInfoReq, uv_getnameinfo_t> {
- public:
-  GetNameInfoReq();
-
-  Loop& GetLoop() const { return *static_cast<Loop*>(GetRaw()->loop->data); }
-
-  /**
-   * Resolved lookup signal.
-   * Parameters are hostname and service.
-   */
-  sig::Signal<const char*, const char*> resolved;
-};
-
-/**
- * Asynchronous getnameinfo(3).  HandleResolvedName() is called on the
- * request when the resolution completes.  HandleError() is called on the
- * request if any errors occur.
- *
- * @param loop Event loop
- * @param req request
- * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-void GetNameInfo(Loop& loop, const std::shared_ptr<GetNameInfoReq>& req,
-                 const sockaddr& addr, int flags = 0);
-
-/**
- * Asynchronous getnameinfo(3).  HandleResolvedName() is called on the
- * request when the resolution completes.  HandleError() is called on the
- * request if any errors occur.
- *
- * @param loop Event loop
- * @param req request
- * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-inline void GetNameInfo(const std::shared_ptr<Loop>& loop,
-                        const std::shared_ptr<GetNameInfoReq>& req,
-                        const sockaddr& addr, int flags = 0) {
-  GetNameInfo(*loop, req, addr, flags);
-}
-
-/**
- * Asynchronous getnameinfo(3).  The callback is called when the resolution
- * completes, and errors are forwarded to the loop.
- *
- * @param loop Event loop
- * @param callback Callback function to call when resolution completes
- * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-void GetNameInfo(Loop& loop,
-                 std::function<void(const char*, const char*)> callback,
-                 const sockaddr& addr, int flags = 0);
-
-/**
- * Asynchronous getnameinfo(3).  The callback is called when the resolution
- * completes, and errors are forwarded to the loop.
- *
- * @param loop Event loop
- * @param callback Callback function to call when resolution completes
- * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- * @return Connection object for the callback
- */
-inline void GetNameInfo(const std::shared_ptr<Loop>& loop,
-                        std::function<void(const char*, const char*)> callback,
-                        const sockaddr& addr, int flags = 0) {
-  GetNameInfo(*loop, std::move(callback), addr, flags);
-}
-
-/**
- * Asynchronous IPv4 getnameinfo(3).  HandleResolvedName() is called on the
- * request when the resolution completes.  HandleError() is called on the
- * request if any errors occur.
- *
- * @param loop Event loop
- * @param req request
- * @param ip A valid IPv4 address
- * @param port A valid port number
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-void GetNameInfo4(Loop& loop, const std::shared_ptr<GetNameInfoReq>& req,
-                  std::string_view ip, unsigned int port, int flags = 0);
-
-/**
- * Asynchronous IPv4 getnameinfo(3).  HandleResolvedName() is called on the
- * request when the resolution completes.  HandleError() is called on the
- * request if any errors occur.
- *
- * @param loop Event loop
- * @param req request
- * @param ip A valid IPv4 address
- * @param port A valid port number
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-inline void GetNameInfo4(const std::shared_ptr<Loop>& loop,
-                         const std::shared_ptr<GetNameInfoReq>& req,
-                         std::string_view ip, unsigned int port,
-                         int flags = 0) {
-  return GetNameInfo4(*loop, req, ip, port, flags);
-}
-
-/**
- * Asynchronous IPv4 getnameinfo(3).  The callback is called when the resolution
- * completes, and errors are forwarded to the loop.
- *
- * @param loop Event loop
- * @param callback Callback function to call when resolution completes
- * @param ip A valid IPv4 address
- * @param port A valid port number
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-void GetNameInfo4(Loop& loop,
-                  std::function<void(const char*, const char*)> callback,
-                  std::string_view ip, unsigned int port, int flags = 0);
-
-/**
- * Asynchronous IPv4 getnameinfo(3).  The callback is called when the resolution
- * completes, and errors are forwarded to the loop.  This is a convenience
- * wrapper.
- *
- * @param loop Event loop
- * @param ip A valid IPv4 address
- * @param port A valid port number
- * @param callback Callback function to call when resolution completes
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-inline void GetNameInfo4(const std::shared_ptr<Loop>& loop,
-                         std::function<void(const char*, const char*)> callback,
-                         std::string_view ip, unsigned int port,
-                         int flags = 0) {
-  return GetNameInfo4(*loop, std::move(callback), ip, port, flags);
-}
-
-/**
- * Asynchronous IPv6 getnameinfo(3).  HandleResolvedName() is called on the
- * request when the resolution completes.  HandleError() is called on the
- * request if any errors occur.
- *
- * @param loop Event loop
- * @param req request
- * @param ip A valid IPv6 address
- * @param port A valid port number
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-void GetNameInfo6(Loop& loop, const std::shared_ptr<GetNameInfoReq>& req,
-                  std::string_view ip, unsigned int port, int flags = 0);
-
-/**
- * Asynchronous IPv6 getnameinfo(3).  HandleResolvedName() is called on the
- * request when the resolution completes.  HandleError() is called on the
- * request if any errors occur.
- *
- * @param loop Event loop
- * @param req request
- * @param ip A valid IPv6 address
- * @param port A valid port number
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-inline void GetNameInfo6(const std::shared_ptr<Loop>& loop,
-                         const std::shared_ptr<GetNameInfoReq>& req,
-                         std::string_view ip, unsigned int port,
-                         int flags = 0) {
-  GetNameInfo6(*loop, req, ip, port, flags);
-}
-
-/**
- * Asynchronous IPv6 getnameinfo(3).  The callback is called when the resolution
- * completes, and errors are forwarded to the loop.  This is a convenience
- * wrapper.
- *
- * @param loop Event loop
- * @param callback Callback function to call when resolution completes
- * @param ip A valid IPv6 address
- * @param port A valid port number
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-void GetNameInfo6(Loop& loop,
-                  std::function<void(const char*, const char*)> callback,
-                  std::string_view ip, unsigned int port, int flags = 0);
-
-/**
- * Asynchronous IPv6 getnameinfo(3).  The callback is called when the resolution
- * completes, and errors are forwarded to the loop.  This is a convenience
- * wrapper.
- *
- * @param loop Event loop
- * @param callback Callback function to call when resolution completes
- * @param ip A valid IPv6 address
- * @param port A valid port number
- * @param flags Optional flags to modify the behavior of `getnameinfo`.
- */
-inline void GetNameInfo6(const std::shared_ptr<Loop>& loop,
-                         std::function<void(const char*, const char*)> callback,
-                         std::string_view ip, unsigned int port,
-                         int flags = 0) {
-  return GetNameInfo6(*loop, std::move(callback), ip, port, flags);
-}
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_GETNAMEINFO_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Handle.h b/wpiutil/src/main/native/include/wpi/uv/Handle.h
deleted file mode 100644
index b61cd81..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Handle.h
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_HANDLE_H_
-#define WPIUTIL_WPI_UV_HANDLE_H_
-
-#include <uv.h>
-
-#include <cstdlib>
-#include <functional>
-#include <memory>
-#include <string_view>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Buffer.h"
-#include "wpi/uv/Error.h"
-#include "wpi/uv/Loop.h"
-
-namespace wpi::uv {
-
-/**
- * Handle.
- * Handles are not moveable or copyable and cannot be directly constructed.
- * This class provides shared_ptr ownership and shared_from_this.
- * Use the specific handle type Create() functions to create handles.
- */
-class Handle : public std::enable_shared_from_this<Handle> {
- public:
-  using Type = uv_handle_type;
-
-  Handle(const Handle&) = delete;
-  Handle(Handle&&) = delete;
-  Handle& operator=(const Handle&) = delete;
-  Handle& operator=(Handle&&) = delete;
-  virtual ~Handle() noexcept;
-
-  /**
-   * Get the type of the handle.
-   *
-   * A base handle offers no functionality to promote it to the actual handle
-   * type. By means of this function, the type of the underlying handle as
-   * specified by Type is made available.
-   *
-   * @return The actual type of the handle.
-   */
-  Type GetType() const noexcept { return m_uv_handle->type; }
-
-  /**
-   * Get the name of the type of the handle.  E.g. "pipe" for pipe handles.
-   */
-  std::string_view GetTypeName() const noexcept {
-    return uv_handle_type_name(m_uv_handle->type);
-  }
-
-  /**
-   * Get the loop where this handle runs.
-   *
-   * @return The loop.
-   */
-  std::shared_ptr<Loop> GetLoop() const noexcept {
-    return GetLoopRef().shared_from_this();
-  }
-
-  /**
-   * Get the loop where this handle runs.
-   *
-   * @return The loop.
-   */
-  Loop& GetLoopRef() const noexcept {
-    return *static_cast<Loop*>(m_uv_handle->loop->data);
-  }
-
-  /**
-   * Check if the handle is active.
-   *
-   * What _active_ means depends on the type of handle:
-   *
-   * * An AsyncHandle handle is always active and cannot be deactivated,
-   * except by closing it with uv_close().
-   * * A PipeHandle, TcpHandle, UDPHandle, etc. handle - basically any handle
-   * that deals with I/O - is active when it is doing something that involves
-   * I/O, like reading, writing, connecting, accepting new connections, etc.
-   * * A CheckHandle, IdleHandle, TimerHandle, etc. handle is active when it
-   * has been started with a call to `Start()`.
-   *
-   * Rule of thumb: if a handle of type `FooHandle` has a `Start()` member
-   * method, then it’s active from the moment that method is called. Likewise,
-   * `Stop()` deactivates the handle again.
-   *
-   * @return True if the handle is active, false otherwise.
-   */
-  bool IsActive() const noexcept { return uv_is_active(m_uv_handle) != 0; }
-
-  /**
-   * Check if a handle is closing or closed.
-   *
-   * This function should only be used between the initialization of the
-   * handle and the arrival of the close callback.
-   *
-   * @return True if the handle is closing or closed, false otherwise.
-   */
-  bool IsClosing() const noexcept {
-    return m_closed || uv_is_closing(m_uv_handle) != 0;
-  }
-
-  /**
-   * Request handle to be closed.
-   *
-   * This **must** be called on each handle before memory is released.
-   * In-progress requests are cancelled and this can result in error() being
-   * emitted.
-   *
-   * The handle will emit closed() when finished.
-   */
-  void Close() noexcept;
-
-  /**
-   * Set if the loop is closing.
-   *
-   * This is set during EventLoopRunner.Stop(), and can be used for other cases
-   * to indicate the loop should be closing. For instance for a uv_walk loop can
-   * use this to close existing handles.
-   *
-   * @param loopClosing true to set the loop currently in closing stages.
-   */
-  void SetLoopClosing(bool loopClosing) noexcept {
-    m_loopClosing = loopClosing;
-  }
-
-  /**
-   * Get the loop closing status.
-   *
-   * This can be used from closed() in order to tell if a closing loop is the
-   * reason for the close, or another reason.
-   *
-   * @return true if the loop is closing, otherwise false.
-   */
-  bool IsLoopClosing() const noexcept { return m_loopClosing; }
-
-  /**
-   * Reference the given handle.
-   *
-   * References are idempotent, that is, if a handle is already referenced
-   * calling this function again will have no effect.
-   */
-  void Reference() noexcept { uv_ref(m_uv_handle); }
-
-  /**
-   * Unreference the given handle.
-   *
-   * References are idempotent, that is, if a handle is not referenced calling
-   * this function again will have no effect.
-   */
-  void Unreference() noexcept { uv_unref(m_uv_handle); }
-
-  /**
-   * Check if the given handle is referenced.
-   * @return True if the handle is referenced, false otherwise.
-   */
-  bool HasReference() const noexcept { return uv_has_ref(m_uv_handle) != 0; }
-
-  /**
-   * Return the size of the underlying handle type.
-   * @return The size of the underlying handle type.
-   */
-  size_t RawSize() const noexcept { return uv_handle_size(m_uv_handle->type); }
-
-  /**
-   * Get the underlying handle data structure.
-   *
-   * @return The underlying handle data structure.
-   */
-  uv_handle_t* GetRawHandle() const noexcept { return m_uv_handle; }
-
-  /**
-   * Set the functions used for allocating and releasing buffers.  The size
-   * passed to the allocator function is a "suggested" size--it's just an
-   * indication, not related in any way to the pending data to be read.  The
-   * user is free to allocate the amount of memory they decide.  For example,
-   * applications with custom allocation schemes may decide to use a different
-   * size which matches the memory chunks they already have for other purposes.
-   *
-   * @warning Be very careful changing the allocator after the loop has started
-   * running; there are no interlocks between this and buffers currently in
-   * flight.
-   *
-   * @param alloc Allocation function
-   * @param dealloc Deallocation function
-   */
-  void SetBufferAllocator(std::function<Buffer(size_t)> alloc,
-                          std::function<void(Buffer&)> dealloc) {
-    m_allocBuf = std::move(alloc);
-    m_freeBuf = std::move(dealloc);
-  }
-
-  /**
-   * Free a buffer.  Uses the function provided to SetBufFree() or
-   * Buffer::Deallocate by default.
-   *
-   * @param buf The buffer
-   */
-  void FreeBuf(Buffer& buf) const noexcept { m_freeBuf(buf); }
-
-  /**
-   * Gets user-defined data.
-   * @return User-defined data if any, nullptr otherwise.
-   */
-  template <typename T = void>
-  std::shared_ptr<T> GetData() const {
-    return std::static_pointer_cast<T>(m_data);
-  }
-
-  /**
-   * Sets user-defined data.
-   * @param data User-defined arbitrary data.
-   */
-  void SetData(std::shared_ptr<void> data) { m_data = std::move(data); }
-
-  /**
-   * Error signal
-   */
-  sig::Signal<Error> error;
-
-  /**
-   * Closed signal
-   */
-  sig::Signal<> closed;
-
-  /**
-   * Report an error.
-   * @param err Error code
-   */
-  void ReportError(int err) const { error(Error(err)); }
-
- protected:
-  explicit Handle(uv_handle_t* uv_handle) : m_uv_handle{uv_handle} {
-    m_uv_handle->data = this;
-  }
-
-  void Keep() noexcept { m_self = shared_from_this(); }
-  void Release() noexcept { m_self.reset(); }
-  void ForceClosed() noexcept { m_closed = true; }
-
-  static void AllocBuf(uv_handle_t* handle, size_t size, uv_buf_t* buf);
-  static void DefaultFreeBuf(Buffer& buf);
-
-  template <typename F, typename... Args>
-  bool Invoke(F&& f, Args&&... args) const {
-    auto err = std::forward<F>(f)(std::forward<Args>(args)...);
-    if (err < 0) {
-      ReportError(err);
-    }
-    return err == 0;
-  }
-
- private:
-  std::shared_ptr<Handle> m_self;
-  uv_handle_t* m_uv_handle;
-  bool m_closed = false;
-  bool m_loopClosing = false;
-  std::function<Buffer(size_t)> m_allocBuf{&Buffer::Allocate};
-  std::function<void(Buffer&)> m_freeBuf{&DefaultFreeBuf};
-  std::shared_ptr<void> m_data;
-};
-
-/**
- * Handle.
- */
-template <typename T, typename U>
-class HandleImpl : public Handle {
- public:
-  std::shared_ptr<T> shared_from_this() {
-    return std::static_pointer_cast<T>(Handle::shared_from_this());
-  }
-
-  std::shared_ptr<const T> shared_from_this() const {
-    return std::static_pointer_cast<const T>(Handle::shared_from_this());
-  }
-
-  /**
-   * Get the underlying handle data structure.
-   *
-   * @return The underlying handle data structure.
-   */
-  U* GetRaw() const noexcept {
-    return reinterpret_cast<U*>(this->GetRawHandle());
-  }
-
- protected:
-  HandleImpl() : Handle{static_cast<uv_handle_t*>(std::malloc(sizeof(U)))} {}
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_HANDLE_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Idle.h b/wpiutil/src/main/native/include/wpi/uv/Idle.h
deleted file mode 100644
index 869d43d..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Idle.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_IDLE_H_
-#define WPIUTIL_WPI_UV_IDLE_H_
-
-#include <uv.h>
-
-#include <memory>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Handle.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * Idle handle.
- *
- * Idle handles will generate a signal once per loop iteration, right
- * before the Prepare handles.
- *
- * The notable difference with Prepare handles is that when there are active
- * idle handles, the loop will perform a zero timeout poll instead of blocking
- * for I/O.
- *
- * @warning Despite the name, idle handles will signal every loop iteration,
- * not when the loop is actually "idle".  This also means they can easly become
- * CPU hogs.
- */
-class Idle final : public HandleImpl<Idle, uv_idle_t> {
-  struct private_init {};
-
- public:
-  explicit Idle(const private_init&) {}
-  ~Idle() noexcept override = default;
-
-  /**
-   * Create an idle handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Idle> Create(Loop& loop);
-
-  /**
-   * Create an idle handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Idle> Create(const std::shared_ptr<Loop>& loop) {
-    return Create(*loop);
-  }
-
-  /**
-   * Start the handle.
-   */
-  void Start();
-
-  /**
-   * Stop the handle.  The signal will no longer be generated.
-   */
-  void Stop() { Invoke(&uv_idle_stop, GetRaw()); }
-
-  /**
-   * Signal generated once per loop iteration prior to Prepare signals.
-   */
-  sig::Signal<> idle;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_IDLE_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Loop.h b/wpiutil/src/main/native/include/wpi/uv/Loop.h
deleted file mode 100644
index 9693053..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Loop.h
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_LOOP_H_
-#define WPIUTIL_WPI_UV_LOOP_H_
-
-#include <uv.h>
-
-#include <atomic>
-#include <chrono>
-#include <functional>
-#include <memory>
-#include <thread>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/function_ref.h"
-#include "wpi/uv/Error.h"
-
-namespace wpi::uv {
-
-class Handle;
-
-/**
- * Event loop.
- *
- * The event loop is the central part of uv functionality.  It takes care of
- * polling for I/O and scheduling signals to be generated based on different
- * sources of events.
- *
- * The event loop is not moveable, copyable, or directly constructible.  Use
- * Create() to create an event loop, or GetDefault() to get the default loop
- * if you know your program will only have a single one.
- */
-class Loop final : public std::enable_shared_from_this<Loop> {
-  struct private_init {};
-
- public:
-  using Time = std::chrono::duration<uint64_t, std::milli>;
-
-  enum Mode {
-    kDefault = UV_RUN_DEFAULT,
-    kOnce = UV_RUN_ONCE,
-    kNoWait = UV_RUN_NOWAIT
-  };
-
-  explicit Loop(const private_init&) noexcept;
-
-  Loop(const Loop&) = delete;
-  Loop& operator=(const Loop&) = delete;
-  Loop(Loop&& oth) = delete;
-  Loop& operator=(Loop&& oth) = delete;
-
-  ~Loop() noexcept;
-
-  /**
-   * Create a new event loop.  The created loop is not the default event loop.
-   *
-   * @return The newly created loop.  May return nullptr if a failure occurs.
-   */
-  static std::shared_ptr<Loop> Create();
-
-  /**
-   * Create the default event loop.  Only use this event loop if a single loop
-   * is needed for the entire application.
-   *
-   * @return The newly created loop.  May return nullptr if a failure occurs.
-   */
-  static std::shared_ptr<Loop> GetDefault();
-
-  /**
-   * Release all internal loop resources.
-   *
-   * Call this function only when the loop has finished executing and all open
-   * handles and requests have been closed, or the loop will emit an error.
-   *
-   * error() will be emitted in case of errors.
-   */
-  void Close();
-
-  /**
-   * Run the event loop.
-   *
-   * Available modes are:
-   *
-   * * `Loop::kDefault`: Run the event loop until there are no
-   *                     active and referenced handles or requests.
-   * * `Loop::kOnce`: Run a single event loop iteration. Note that this
-   *                  function blocksif there are no pending callbacks.
-   * * `Loop::kNoWait`: Run a single event loop iteration, but don't block
-   *                    if there are no pending callbacks.
-   *
-   * @return True when done, false in all other cases.
-   */
-  bool Run(Mode mode = kDefault) {
-    m_tid = std::this_thread::get_id();
-    int rv = uv_run(m_loop, static_cast<uv_run_mode>(static_cast<int>(mode)));
-    m_tid = std::thread::id{};
-    return rv == 0;
-  }
-
-  /**
-   * Check if there are active resources.
-   *
-   * @return True if there are active resources in the loop.
-   */
-  bool IsAlive() const noexcept { return uv_loop_alive(m_loop) != 0; }
-
-  /**
-   * Stop the event loop.
-   *
-   * This will cause Run() to end as soon as possible.
-   * This will happen not sooner than the next loop iteration.
-   * If this function was called before blocking for I/O, the loop won’t block
-   * for I/O on this iteration.
-   */
-  void Stop() noexcept { uv_stop(m_loop); }
-
-  /**
-   * Get backend file descriptor.
-   *
-   * Only kqueue, epoll and event ports are supported.
-   * This can be used in conjunction with `run(Loop::kNoWait)` to poll
-   * in one thread and run the event loop’s callbacks in another.
-   *
-   * @return The backend file descriptor.
-   */
-  int GetDescriptor() const noexcept { return uv_backend_fd(m_loop); }
-
-  /**
-   * Get the poll timeout.
-   *
-   * @return A `std::pair` composed of a boolean value that is true in case of
-   * valid timeout, false otherwise, and the timeout
-   * (`std::chrono::duration<uint64_t, std::milli>`).
-   */
-  std::pair<bool, Time> GetTimeout() const noexcept {
-    auto to = uv_backend_timeout(m_loop);
-    return std::make_pair(to == -1, Time{to});
-  }
-
-  /**
-   * Return the current timestamp in milliseconds.
-   *
-   * The timestamp is cached at the start of the event loop tick.
-   * The timestamp increases monotonically from some arbitrary point in
-   * time.
-   * Don’t make assumptions about the starting point, you will only get
-   * disappointed.
-   *
-   * @return The current timestamp in milliseconds (actual type is
-   * `std::chrono::duration<uint64_t, std::milli>`).
-   */
-  Time Now() const noexcept { return Time{uv_now(m_loop)}; }
-
-  /**
-   * Update the event loop’s concept of _now_.
-   *
-   * The current time is cached at the start of the event loop tick in order
-   * to reduce the number of time-related system calls.
-   * You won’t normally need to call this function unless you have callbacks
-   * that block the event loop for longer periods of time, where _longer_ is
-   * somewhat subjective but probably on the order of a millisecond or more.
-   */
-  void UpdateTime() noexcept { uv_update_time(m_loop); }
-
-  /**
-   * Walk the list of handles.
-   *
-   * The callback will be executed once for each handle that is still active.
-   *
-   * @param callback A function to be invoked once for each active handle.
-   */
-  void Walk(function_ref<void(Handle&)> callback);
-
-  /**
-   * Reinitialize any kernel state necessary in the child process after
-   * a fork(2) system call.
-   *
-   * Previously started watchers will continue to be started in the child
-   * process.
-   *
-   * It is necessary to explicitly call this function on every event loop
-   * created in the parent process that you plan to continue to use in the
-   * child, including the default loop (even if you don’t continue to use it
-   * in the parent). This function must be called before calling any API
-   * function using the loop in the child. Failure to do so will result in
-   * undefined behaviour, possibly including duplicate events delivered to
-   * both parent and child or aborting the child process.
-   *
-   * When possible, it is preferred to create a new loop in the child process
-   * instead of reusing a loop created in the parent. New loops created in the
-   * child process after the fork should not use this function.
-   *
-   * Note that this function is not implemented on Windows.
-   * Note also that this function is experimental in `libuv`. It may contain
-   * bugs, and is subject to change or removal. API and ABI stability is not
-   * guaranteed.
-   *
-   * error() will be emitted in case of errors.
-   */
-  void Fork();
-
-  /**
-   * Get the underlying event loop data structure.
-   *
-   * @return The underlying event loop data structure.
-   */
-  uv_loop_t* GetRaw() const noexcept { return m_loop; }
-
-  /**
-   * Gets user-defined data.
-   * @return User-defined data if any, nullptr otherwise.
-   */
-  template <typename T = void>
-  std::shared_ptr<T> GetData() const {
-    return std::static_pointer_cast<T>(m_data);
-  }
-
-  /**
-   * Sets user-defined data.
-   * @param data User-defined arbitrary data.
-   */
-  void SetData(std::shared_ptr<void> data) { m_data = std::move(data); }
-
-  /**
-   * Get the thread id of the loop thread.  If the loop is not currently
-   * running, returns default-constructed thread id.
-   */
-  std::thread::id GetThreadId() const { return m_tid; }
-
-  /**
-   * Error signal
-   */
-  sig::Signal<Error> error;
-
-  /**
-   * Reports error.
-   * @param err Error code
-   */
-  void ReportError(int err) { error(Error(err)); }
-
- private:
-  std::shared_ptr<void> m_data;
-  uv_loop_t* m_loop;
-  uv_loop_t m_loopStruct;
-  std::atomic<std::thread::id> m_tid;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_LOOP_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/NetworkStream.h b/wpiutil/src/main/native/include/wpi/uv/NetworkStream.h
deleted file mode 100644
index faac9fe..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/NetworkStream.h
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_NETWORKSTREAM_H_
-#define WPIUTIL_WPI_UV_NETWORKSTREAM_H_
-
-#include <uv.h>
-
-#include <cstdlib>
-#include <functional>
-#include <memory>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Stream.h"
-
-namespace wpi::uv {
-
-class NetworkStream;
-
-/**
- * Connection request.
- */
-class ConnectReq : public RequestImpl<ConnectReq, uv_connect_t> {
- public:
-  ConnectReq();
-
-  NetworkStream& GetStream() const {
-    return *static_cast<NetworkStream*>(GetRaw()->handle->data);
-  }
-
-  /**
-   * Connection completed signal.
-   */
-  sig::Signal<> connected;
-};
-
-/**
- * Network stream handle.
- * This is an abstract type; there are two network stream implementations (Tcp
- * and Pipe).
- */
-class NetworkStream : public Stream {
- public:
-  static constexpr int kDefaultBacklog = 128;
-
-  std::shared_ptr<NetworkStream> shared_from_this() {
-    return std::static_pointer_cast<NetworkStream>(Handle::shared_from_this());
-  }
-
-  std::shared_ptr<const NetworkStream> shared_from_this() const {
-    return std::static_pointer_cast<const NetworkStream>(
-        Handle::shared_from_this());
-  }
-
-  /**
-   * Start listening for incoming connections.  When a new incoming connection
-   * is received the connection signal is generated.
-   * @param backlog the number of connections the kernel might queue, same as
-   *        listen(2).
-   */
-  void Listen(int backlog = kDefaultBacklog);
-
-  /**
-   * Start listening for incoming connections.  This is a convenience wrapper
-   * around `Listen(int)` that also connects a callback to the connection
-   * signal.  When a new incoming connection is received the connection signal
-   * is generated (and the callback is called).
-   * @param callback the callback to call when a connection is received.
-   *        `Accept()` should be called from this callback.
-   * @param backlog the number of connections the kernel might queue, same as
-   *        listen(2).
-   */
-  void Listen(std::function<void()> callback, int backlog = kDefaultBacklog);
-
-  /**
-   * Accept incoming connection.
-   *
-   * This call is used in conjunction with `Listen()` to accept incoming
-   * connections. Call this function after receiving a ListenEvent event to
-   * accept the connection.
-   * An error signal will be emitted in case of errors.
-   *
-   * When the connection signal is emitted it is guaranteed that this
-   * function will complete successfully the first time. If you attempt to use
-   * it more than once, it may fail.
-   * It is suggested to only call this function once per connection signal.
-   *
-   * @return The stream handle for the accepted connection, or nullptr on error.
-   */
-  std::shared_ptr<NetworkStream> Accept() {
-    return DoAccept()->shared_from_this();
-  }
-
-  /**
-   * Accept incoming connection.
-   *
-   * This call is used in conjunction with `Listen()` to accept incoming
-   * connections. Call this function after receiving a connection signal to
-   * accept the connection.
-   * An error signal will be emitted in case of errors.
-   *
-   * When the connection signal is emitted it is guaranteed that this
-   * function will complete successfully the first time. If you attempt to use
-   * it more than once, it may fail.
-   * It is suggested to only call this function once per connection signal.
-   *
-   * @param client Client stream object.
-   * @return False on error.
-   */
-  bool Accept(const std::shared_ptr<NetworkStream>& client) {
-    return Invoke(&uv_accept, GetRawStream(), client->GetRawStream());
-  }
-
-  /**
-   * Signal generated when an incoming connection is received.
-   */
-  sig::Signal<> connection;
-
- protected:
-  explicit NetworkStream(uv_stream_t* uv_stream) : Stream{uv_stream} {}
-
-  virtual NetworkStream* DoAccept() = 0;
-};
-
-template <typename T, typename U>
-class NetworkStreamImpl : public NetworkStream {
- public:
-  std::shared_ptr<T> shared_from_this() {
-    return std::static_pointer_cast<T>(Handle::shared_from_this());
-  }
-
-  std::shared_ptr<const T> shared_from_this() const {
-    return std::static_pointer_cast<const T>(Handle::shared_from_this());
-  }
-
-  /**
-   * Get the underlying handle data structure.
-   *
-   * @return The underlying handle data structure.
-   */
-  U* GetRaw() const noexcept {
-    return reinterpret_cast<U*>(this->GetRawHandle());
-  }
-
- protected:
-  NetworkStreamImpl()
-      : NetworkStream{static_cast<uv_stream_t*>(std::malloc(sizeof(U)))} {}
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_NETWORKSTREAM_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Pipe.h b/wpiutil/src/main/native/include/wpi/uv/Pipe.h
deleted file mode 100644
index e223268..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Pipe.h
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_PIPE_H_
-#define WPIUTIL_WPI_UV_PIPE_H_
-
-#include <uv.h>
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <string_view>
-
-#include "wpi/uv/NetworkStream.h"
-
-namespace wpi::uv {
-
-class Loop;
-class PipeConnectReq;
-
-/**
- * Pipe handle.
- * Pipe handles provide an abstraction over local domain sockets on Unix and
- * named pipes on Windows.
- */
-class Pipe final : public NetworkStreamImpl<Pipe, uv_pipe_t> {
-  struct private_init {};
-
- public:
-  explicit Pipe(const private_init&) {}
-  ~Pipe() noexcept override = default;
-
-  /**
-   * Create a pipe handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param ipc Indicates if this pipe will be used for handle passing between
-   *            processes.
-   */
-  static std::shared_ptr<Pipe> Create(Loop& loop, bool ipc = false);
-
-  /**
-   * Create a pipe handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param ipc Indicates if this pipe will be used for handle passing between
-   *            processes.
-   */
-  static std::shared_ptr<Pipe> Create(const std::shared_ptr<Loop>& loop,
-                                      bool ipc = false) {
-    return Create(*loop, ipc);
-  }
-
-  /**
-   * Reuse this handle.  This closes the handle, and after the close completes,
-   * reinitializes it (identically to Create) and calls the provided callback.
-   * Unlike Close(), it does NOT emit the closed signal, however, IsClosing()
-   * will return true until the callback is called.  This does nothing if
-   * IsClosing() is true (e.g. if Close() was called).
-   *
-   * @param ipc IPC
-   * @param callback Callback
-   */
-  void Reuse(std::function<void()> callback, bool ipc = false);
-
-  /**
-   * Accept incoming connection.
-   *
-   * This call is used in conjunction with `Listen()` to accept incoming
-   * connections. Call this function after receiving a ListenEvent event to
-   * accept the connection.
-   * An error signal will be emitted in case of errors.
-   *
-   * When the connection signal is emitted it is guaranteed that this
-   * function will complete successfully the first time. If you attempt to use
-   * it more than once, it may fail.
-   * It is suggested to only call this function once per connection signal.
-   *
-   * @return The stream handle for the accepted connection, or nullptr on error.
-   */
-  std::shared_ptr<Pipe> Accept();
-
-  /**
-   * Accept incoming connection.
-   *
-   * This call is used in conjunction with `Listen()` to accept incoming
-   * connections. Call this function after receiving a connection signal to
-   * accept the connection.
-   * An error signal will be emitted in case of errors.
-   *
-   * When the connection signal is emitted it is guaranteed that this
-   * function will complete successfully the first time. If you attempt to use
-   * it more than once, it may fail.
-   * It is suggested to only call this function once per connection signal.
-   *
-   * @param client Client stream object.
-   * @return False on error.
-   */
-  bool Accept(const std::shared_ptr<Pipe>& client) {
-    return NetworkStream::Accept(client);
-  }
-
-  /**
-   * Open an existing file descriptor or HANDLE as a pipe.
-   *
-   * @note The passed file descriptor or HANDLE is not checked for its type, but
-   * it's required that it represents a valid pipe.
-   *
-   * @param file A valid file handle (either a file descriptor or a HANDLE).
-   */
-  void Open(uv_file file) { Invoke(&uv_pipe_open, GetRaw(), file); }
-
-  /**
-   * Bind the pipe to a file path (Unix) or a name (Windows).
-   *
-   * @note Paths on Unix get truncated to `sizeof(sockaddr_un.sun_path)` bytes,
-   * typically between 92 and 108 bytes.
-   *
-   * @param name File path (Unix) or name (Windows).
-   */
-  void Bind(std::string_view name);
-
-  /**
-   * Connect to the Unix domain socket or the named pipe.
-   *
-   * @note Paths on Unix get truncated to `sizeof(sockaddr_un.sun_path)` bytes,
-   * typically between 92 and 108 bytes.
-   *
-   * HandleConnected() is called on the request when the connection has been
-   * established.
-   * HandleError() is called on the request in case of errors during the
-   * connection.
-   *
-   * @param name File path (Unix) or name (Windows).
-   * @param req connection request
-   */
-  void Connect(std::string_view name,
-               const std::shared_ptr<PipeConnectReq>& req);
-
-  /**
-   * Connect to the Unix domain socket or the named pipe.
-   *
-   * @note Paths on Unix get truncated to `sizeof(sockaddr_un.sun_path)` bytes,
-   * typically between 92 and 108 bytes.
-   *
-   * The callback is called when the connection has been established.  Errors
-   * are reported to the stream error handler.
-   *
-   * @param name File path (Unix) or name (Windows).
-   * @param callback Callback function to call when connection established
-   */
-  void Connect(std::string_view name, std::function<void()> callback);
-
-  /**
-   * Get the name of the Unix domain socket or the named pipe.
-   * @return The name (will be empty if an error occurred).
-   */
-  std::string GetSock();
-
-  /**
-   * Get the name of the Unix domain socket or the named pipe to which the
-   * handle is connected.
-   * @return The name (will be empty if an error occurred).
-   */
-  std::string GetPeer();
-
-  /**
-   * Set the number of pending pipe instance handles when the pipe server is
-   * waiting for connections.
-   * @note This setting applies to Windows only.
-   * @param count Number of pending handles.
-   */
-  void SetPendingInstances(int count) {
-    uv_pipe_pending_instances(GetRaw(), count);
-  }
-
-  /**
-   * Alters pipe permissions, allowing it to be accessed from processes run
-   * by different users.  Makes the pipe writable or readable by all users.
-   * Mode can be UV_WRITABLE, UV_READABLE, or both.  This function is blocking.
-   * @param flags chmod flags
-   */
-  void Chmod(int flags) { Invoke(&uv_pipe_chmod, GetRaw(), flags); }
-
- private:
-  Pipe* DoAccept() override;
-
-  struct ReuseData {
-    std::function<void()> callback;
-    bool ipc;
-  };
-  std::unique_ptr<ReuseData> m_reuseData;
-};
-
-/**
- * Pipe connection request.
- */
-class PipeConnectReq : public ConnectReq {
- public:
-  Pipe& GetStream() const {
-    return *static_cast<Pipe*>(&ConnectReq::GetStream());
-  }
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_PIPE_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Poll.h b/wpiutil/src/main/native/include/wpi/uv/Poll.h
deleted file mode 100644
index 6e1e26d..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Poll.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_POLL_H_
-#define WPIUTIL_WPI_UV_POLL_H_
-
-#include <uv.h>
-
-#include <memory>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Handle.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * Poll handle.
- */
-class Poll final : public HandleImpl<Poll, uv_poll_t> {
-  struct private_init {};
-
- public:
-  explicit Poll(const private_init&) {}
-  ~Poll() noexcept override = default;
-
-  /**
-   * Create a poll handle using a file descriptor.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param fd File descriptor.
-   */
-  static std::shared_ptr<Poll> Create(Loop& loop, int fd);
-
-  /**
-   * Create a poll handle using a file descriptor.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param fd File descriptor.
-   */
-  static std::shared_ptr<Poll> Create(const std::shared_ptr<Loop>& loop,
-                                      int fd) {
-    return Create(*loop, fd);
-  }
-
-  /**
-   * Create a poll handle using a socket descriptor.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param sock Socket descriptor.
-   */
-  static std::shared_ptr<Poll> CreateSocket(Loop& loop, uv_os_sock_t sock);
-
-  /**
-   * Create a poll handle using a socket descriptor.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param sock Socket descriptor.
-   */
-  static std::shared_ptr<Poll> CreateSocket(const std::shared_ptr<Loop>& loop,
-                                            uv_os_sock_t sock) {
-    return CreateSocket(*loop, sock);
-  }
-
-  /**
-   * Reuse this handle.  This closes the handle, and after the close completes,
-   * reinitializes it (identically to Create) and calls the provided callback.
-   * Unlike Close(), it does NOT emit the closed signal, however, IsClosing()
-   * will return true until the callback is called.  This does nothing if
-   * IsClosing() is true (e.g. if Close() was called).
-   *
-   * @param fd File descriptor
-   * @param callback Callback
-   */
-  void Reuse(int fd, std::function<void()> callback);
-
-  /**
-   * Reuse this handle.  This closes the handle, and after the close completes,
-   * reinitializes it (identically to CreateSocket) and calls the provided
-   * callback.  Unlike Close(), it does NOT emit the closed signal, however,
-   * IsClosing() will return true until the callback is called.  This does
-   * nothing if IsClosing() is true (e.g. if Close() was called).
-   *
-   * @param sock Socket descriptor.
-   * @param callback Callback
-   */
-  void ReuseSocket(uv_os_sock_t sock, std::function<void()> callback);
-
-  /**
-   * Start polling the file descriptor.
-   *
-   * @param events Bitmask of events (UV_READABLE, UV_WRITEABLE, UV_PRIORITIZED,
-   *               and UV_DISCONNECT).
-   */
-  void Start(int events);
-
-  /**
-   * Stop polling the file descriptor.
-   */
-  void Stop() { Invoke(&uv_poll_stop, GetRaw()); }
-
-  /**
-   * Signal generated when a poll event occurs.
-   */
-  sig::Signal<int> pollEvent;
-
- private:
-  struct ReuseData {
-    std::function<void()> callback;
-    bool isSocket;
-    int fd;
-    uv_os_sock_t sock;
-  };
-  std::unique_ptr<ReuseData> m_reuseData;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_POLL_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Prepare.h b/wpiutil/src/main/native/include/wpi/uv/Prepare.h
deleted file mode 100644
index 88ae2d9..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Prepare.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_PREPARE_H_
-#define WPIUTIL_WPI_UV_PREPARE_H_
-
-#include <uv.h>
-
-#include <memory>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Handle.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * Prepare handle.
- * Prepare handles will generate a signal once per loop iteration, right
- * before polling for I/O.
- */
-class Prepare final : public HandleImpl<Prepare, uv_prepare_t> {
-  struct private_init {};
-
- public:
-  explicit Prepare(const private_init&) {}
-  ~Prepare() noexcept override = default;
-
-  /**
-   * Create a prepare handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Prepare> Create(Loop& loop);
-
-  /**
-   * Create a prepare handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Prepare> Create(const std::shared_ptr<Loop>& loop) {
-    return Create(*loop);
-  }
-
-  /**
-   * Start the handle.
-   */
-  void Start();
-
-  /**
-   * Stop the handle.  The signal will no longer be generated.
-   */
-  void Stop() { Invoke(&uv_prepare_stop, GetRaw()); }
-
-  /**
-   * Signal generated once per loop iteration prior to polling for I/O.
-   */
-  sig::Signal<> prepare;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_PREPARE_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Process.h b/wpiutil/src/main/native/include/wpi/uv/Process.h
deleted file mode 100644
index fc2315e..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Process.h
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_PROCESS_H_
-#define WPIUTIL_WPI_UV_PROCESS_H_
-
-#include <uv.h>
-
-#include <initializer_list>
-#include <memory>
-#include <string>
-#include <string_view>
-
-#include "wpi/Signal.h"
-#include "wpi/SmallVector.h"
-#include "wpi/span.h"
-#include "wpi/uv/Handle.h"
-
-namespace wpi::uv {
-
-class Loop;
-class Pipe;
-
-/**
- * Process handle.
- * Process handles will spawn a new process and allow the user to control it
- * and establish communication channels with it using streams.
- */
-class Process final : public HandleImpl<Process, uv_process_t> {
-  struct private_init {};
-
- public:
-  explicit Process(const private_init&) {}
-  ~Process() noexcept override = default;
-
-  /**
-   * Structure for Spawn() option temporaries.  This is a reference type, so if
-   * this value is stored outside of a temporary, be careful about overwriting
-   * what it points to.
-   */
-  struct Option {
-    enum Type {
-      kNone,
-      kArg,
-      kEnv,
-      kCwd,
-      kUid,
-      kGid,
-      kSetFlags,
-      kClearFlags,
-      kStdioIgnore,
-      kStdioInheritFd,
-      kStdioInheritPipe,
-      kStdioCreatePipe
-    };
-
-    Option() : m_type(kNone) {}
-
-    /*implicit*/ Option(const char* arg) {  // NOLINT
-      m_data.str = arg;
-    }
-
-    /*implicit*/ Option(const std::string& arg) {  // NOLINT
-      m_data.str = arg.data();
-    }
-
-    /*implicit*/ Option(std::string_view arg)  // NOLINT
-        : m_strData(arg) {
-      m_data.str = m_strData.c_str();
-    }
-
-    /*implicit*/ Option(const SmallVectorImpl<char>& arg)  // NOLINT
-        : m_strData(arg.data(), arg.size()) {
-      m_data.str = m_strData.c_str();
-    }
-
-    explicit Option(Type type) : m_type(type) {}
-
-    Type m_type = kArg;
-    std::string m_strData;
-    union {
-      const char* str;
-      uv_uid_t uid;
-      uv_gid_t gid;
-      unsigned int flags;
-      struct {
-        size_t index;
-        union {
-          int fd;
-          Pipe* pipe;
-        };
-        unsigned int flags;
-      } stdio;
-    } m_data;
-  };
-
-  /**
-   * Set environment variable for the subprocess.  If not set, the parent's
-   * environment is used.
-   * @param env environment variable
-   */
-  static Option Env(std::string_view env) {
-    Option o(Option::kEnv);
-    o.m_strData = env;
-    o.m_data.str = o.m_strData.c_str();
-    return o;
-  }
-
-  /**
-   * Set the current working directory for the subprocess.
-   * @param cwd current working directory
-   */
-  static Option Cwd(std::string_view cwd) {
-    Option o(Option::kCwd);
-    o.m_strData = cwd;
-    o.m_data.str = o.m_strData.c_str();
-    return o;
-  }
-
-  /**
-   * Set the child process' user id.
-   * @param uid user id
-   */
-  static Option Uid(uv_uid_t uid) {
-    Option o(Option::kUid);
-    o.m_data.uid = uid;
-    return o;
-  }
-
-  /**
-   * Set the child process' group id.
-   * @param gid group id
-   */
-  static Option Gid(uv_gid_t gid) {
-    Option o(Option::kGid);
-    o.m_data.gid = gid;
-    return o;
-  }
-
-  /**
-   * Set spawn flags.
-   * @param flags Bitmask values from uv_process_flags.
-   */
-  static Option SetFlags(unsigned int flags) {
-    Option o(Option::kSetFlags);
-    o.m_data.flags = flags;
-    return o;
-  }
-
-  /**
-   * Clear spawn flags.
-   * @param flags Bitmask values from uv_process_flags.
-   */
-  static Option ClearFlags(unsigned int flags) {
-    Option o(Option::kClearFlags);
-    o.m_data.flags = flags;
-    return o;
-  }
-
-  /**
-   * Explicitly ignore a stdio.
-   * @param index stdio index
-   */
-  static Option StdioIgnore(size_t index) {
-    Option o(Option::kStdioIgnore);
-    o.m_data.stdio.index = index;
-    return o;
-  }
-
-  /**
-   * Inherit a file descriptor from the parent process.
-   * @param index stdio index
-   * @param fd parent file descriptor
-   */
-  static Option StdioInherit(size_t index, int fd) {
-    Option o(Option::kStdioInheritFd);
-    o.m_data.stdio.index = index;
-    o.m_data.stdio.fd = fd;
-    return o;
-  }
-
-  /**
-   * Inherit a pipe from the parent process.
-   * @param index stdio index
-   * @param pipe pipe
-   */
-  static Option StdioInherit(size_t index, Pipe& pipe) {
-    Option o(Option::kStdioInheritPipe);
-    o.m_data.stdio.index = index;
-    o.m_data.stdio.pipe = &pipe;
-    return o;
-  }
-
-  /**
-   * Create a pipe between the child and the parent.
-   * @param index stdio index
-   * @param pipe pipe
-   * @param flags Some combination of UV_READABLE_PIPE, UV_WRITABLE_PIPE, and
-   *              UV_OVERLAPPED_PIPE (Windows only, ignored on Unix).
-   */
-  static Option StdioCreatePipe(size_t index, Pipe& pipe, unsigned int flags) {
-    Option o(Option::kStdioCreatePipe);
-    o.m_data.stdio.index = index;
-    o.m_data.stdio.pipe = &pipe;
-    o.m_data.stdio.flags = flags;
-    return o;
-  }
-
-  /**
-   * Disables inheritance for file descriptors / handles that this process
-   * inherited from its parent.  The effect is that child processes spawned
-   * by this process don't accidentally inherit these handles.
-   *
-   * It is recommended to call this function as early in your program as
-   * possible, before the inherited file descriptors can be closed or
-   * duplicated.
-   */
-  static void DisableStdioInheritance() { uv_disable_stdio_inheritance(); }
-
-  /**
-   * Starts a process.  If the process is not successfully spawned, an error
-   * is generated on the loop and this function returns nullptr.
-   *
-   * Possible reasons for failing to spawn would include (but not be limited to)
-   * the file to execute not existing, not having permissions to use the setuid
-   * or setgid specified, or not having enough memory to allocate for the new
-   * process.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param file Path pointing to the program to be executed
-   * @param options Process options
-   */
-  static std::shared_ptr<Process> SpawnArray(Loop& loop, std::string_view file,
-                                             span<const Option> options);
-
-  static std::shared_ptr<Process> SpawnArray(
-      Loop& loop, std::string_view file,
-      std::initializer_list<Option> options) {
-    return SpawnArray(loop, file, {options.begin(), options.end()});
-  }
-
-  template <typename... Args>
-  static std::shared_ptr<Process> Spawn(Loop& loop, std::string_view file,
-                                        const Args&... options) {
-    return SpawnArray(loop, file, {options...});
-  }
-
-  /**
-   * Starts a process.  If the process is not successfully spawned, an error
-   * is generated on the loop and this function returns nullptr.
-   *
-   * Possible reasons for failing to spawn would include (but not be limited to)
-   * the file to execute not existing, not having permissions to use the setuid
-   * or setgid specified, or not having enough memory to allocate for the new
-   * process.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param file Path pointing to the program to be executed
-   * @param options Process options
-   */
-  static std::shared_ptr<Process> SpawnArray(const std::shared_ptr<Loop>& loop,
-                                             std::string_view file,
-                                             span<const Option> options) {
-    return SpawnArray(*loop, file, options);
-  }
-
-  static std::shared_ptr<Process> SpawnArray(
-      const std::shared_ptr<Loop>& loop, std::string_view file,
-      std::initializer_list<Option> options) {
-    return SpawnArray(*loop, file, options);
-  }
-
-  template <typename... Args>
-  static std::shared_ptr<Process> Spawn(const std::shared_ptr<Loop>& loop,
-                                        std::string_view file,
-                                        const Args&... options) {
-    return SpawnArray(*loop, file, {options...});
-  }
-
-  /**
-   * Sends the specified signal to the process.
-   * @param signum signal number
-   */
-  void Kill(int signum) { Invoke(&uv_process_kill, GetRaw(), signum); }
-
-  /**
-   * Sends the specified signal to the given PID.
-   * @param pid process ID
-   * @param signum signal number
-   * @return 0 on success, otherwise error code.
-   */
-  static int Kill(int pid, int signum) noexcept { return uv_kill(pid, signum); }
-
-  /**
-   * Get the process ID.
-   * @return Process ID.
-   */
-  uv_pid_t GetPid() const noexcept { return GetRaw()->pid; }
-
-  /**
-   * Signal generated when the process exits.  The parameters are the exit
-   * status and the signal that caused the process to terminate, if any.
-   */
-  sig::Signal<int64_t, int> exited;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_PROCESS_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Request.h b/wpiutil/src/main/native/include/wpi/uv/Request.h
deleted file mode 100644
index 3f6a19d..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Request.h
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_REQUEST_H_
-#define WPIUTIL_WPI_UV_REQUEST_H_
-
-#include <uv.h>
-
-#include <functional>
-#include <memory>
-
-#include "wpi/uv/Error.h"
-
-namespace wpi::uv {
-
-/**
- * Request.  Requests are not moveable or copyable.
- * This class provides shared_ptr ownership and shared_from_this.
- */
-class Request : public std::enable_shared_from_this<Request> {
- public:
-  using Type = uv_req_type;
-
-  Request(const Request&) = delete;
-  Request(Request&&) = delete;
-  Request& operator=(const Request&) = delete;
-  Request& operator=(Request&&) = delete;
-  virtual ~Request() noexcept = default;
-
-  /**
-   * Get the type of the request.
-   *
-   * A base request offers no functionality to promote it to the actual request
-   * type. By means of this function, the type of the underlying request as
-   * specified by Type is made available.
-   *
-   * @return The actual type of the request.
-   */
-  Type GetType() const noexcept { return m_uv_req->type; }
-
-  /**
-   * Get the name of the type of the request.  E.g. "connect" for connect.
-   */
-  const char* GetTypeName() const noexcept {
-    return uv_req_type_name(m_uv_req->type);
-  }
-
-  /**
-   * Cancel a pending request.
-   *
-   * This method fails if the request is executing or has finished
-   * executing.
-   * It can emit an error signal in case of errors.
-   *
-   * @return True in case of success, false otherwise.
-   */
-  bool Cancel() { return uv_cancel(m_uv_req) == 0; }
-
-  /**
-   * Return the size of the underlying request type.
-   * @return The size of the underlying request type.
-   */
-  size_t RawSize() const noexcept { return uv_req_size(m_uv_req->type); }
-
-  /**
-   * Get the underlying request data structure.
-   *
-   * @return The underlying request data structure.
-   */
-  uv_req_t* GetRawReq() noexcept { return m_uv_req; }
-
-  /**
-   * Get the underlying request data structure.
-   *
-   * @return The underlying request data structure.
-   */
-  const uv_req_t* GetRawReq() const noexcept { return m_uv_req; }
-
-  /**
-   * Keep this request in memory even if no outside shared_ptr references
-   * remain.  To release call Release().
-   *
-   * Derived classes can override this method for different memory management
-   * approaches (e.g. pooled storage of requests).
-   */
-  virtual void Keep() noexcept { m_self = shared_from_this(); }
-
-  /**
-   * No longer force holding this request in memory.  Does not immediately
-   * destroy the object unless no outside shared_ptr references remain.
-   *
-   * Derived classes can override this method for different memory management
-   * approaches (e.g. pooled storage of requests).
-   */
-  virtual void Release() noexcept { m_self.reset(); }
-
-  /**
-   * Error callback.  By default, this is set up to report errors to the handle
-   * that created this request.
-   * @param err error code
-   */
-  std::function<void(Error)> error;
-
-  /**
-   * Report an error.
-   * @param err Error code
-   */
-  void ReportError(int err) { error(Error(err)); }
-
- protected:
-  /**
-   * Constructor.
-   */
-  explicit Request(uv_req_t* uv_req) : m_uv_req{uv_req} {
-    m_uv_req->data = this;
-  }
-
- private:
-  std::shared_ptr<Request> m_self;
-  uv_req_t* m_uv_req;
-};
-
-/**
- * Request.  Requests are not moveable or copyable.
- * @tparam T CRTP derived class
- * @tparam U underlying libuv request type
- */
-template <typename T, typename U>
-class RequestImpl : public Request {
- public:
-  std::shared_ptr<T> shared_from_this() {
-    return std::static_pointer_cast<T>(this->shared_from_this());
-  }
-
-  std::shared_ptr<const T> shared_from_this() const {
-    return std::static_pointer_cast<const T>(this->shared_from_this());
-  }
-
-  /**
-   * Get the underlying request data structure.
-   *
-   * @return The underlying request data structure.
-   */
-  U* GetRaw() noexcept { return &m_uv_req; }
-
-  /**
-   * Get the underlying request data structure.
-   *
-   * @return The underlying request data structure.
-   */
-  const U* GetRaw() const noexcept { return &m_uv_req; }
-
- protected:
-  /**
-   * Constructor.
-   */
-  RequestImpl() : Request{reinterpret_cast<uv_req_t*>(&m_uv_req)} {}
-
- private:
-  U m_uv_req;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_REQUEST_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Signal.h b/wpiutil/src/main/native/include/wpi/uv/Signal.h
deleted file mode 100644
index 9abcad3..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Signal.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_SIGNAL_H_
-#define WPIUTIL_WPI_UV_SIGNAL_H_
-
-#include <uv.h>
-
-#include <memory>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Handle.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * Signal handle.
- */
-class Signal final : public HandleImpl<Signal, uv_signal_t> {
-  struct private_init {};
-
- public:
-  explicit Signal(const private_init&) {}
-  ~Signal() noexcept override = default;
-
-  /**
-   * Create a signal handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Signal> Create(Loop& loop);
-
-  /**
-   * Create a signal handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Signal> Create(const std::shared_ptr<Loop>& loop) {
-    return Create(*loop);
-  }
-
-  /**
-   * Start watching for the given signal.
-   *
-   * @param signum Signal to watch for.
-   */
-  void Start(int signum);
-
-  /**
-   * Start watching for the given signal.  Same as Start() but the signal
-   * handler is reset the moment the signal is received.
-   *
-   * @param signum Signal to watch for.
-   */
-  void StartOneshot(int signum);
-
-  /**
-   * Stop watching for the signal.
-   */
-  void Stop() { Invoke(&uv_signal_stop, GetRaw()); }
-
-  /**
-   * Get the signal being monitored.
-   * @return Signal number.
-   */
-  int GetSignal() const { return GetRaw()->signum; }
-
-  /**
-   * Signal generated when a signal occurs.
-   */
-  sig::Signal<int> signal;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_SIGNAL_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Stream.h b/wpiutil/src/main/native/include/wpi/uv/Stream.h
deleted file mode 100644
index 0ade972..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Stream.h
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_STREAM_H_
-#define WPIUTIL_WPI_UV_STREAM_H_
-
-#include <uv.h>
-
-#include <cstdlib>
-#include <functional>
-#include <initializer_list>
-#include <memory>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/span.h"
-#include "wpi/uv/Buffer.h"
-#include "wpi/uv/Handle.h"
-#include "wpi/uv/Request.h"
-
-namespace wpi::uv {
-
-class Stream;
-
-/**
- * Shutdown request.
- */
-class ShutdownReq : public RequestImpl<ShutdownReq, uv_shutdown_t> {
- public:
-  ShutdownReq();
-
-  Stream& GetStream() const {
-    return *static_cast<Stream*>(GetRaw()->handle->data);
-  }
-
-  /**
-   * Shutdown completed signal.
-   */
-  sig::Signal<> complete;
-};
-
-/**
- * Write request.
- */
-class WriteReq : public RequestImpl<WriteReq, uv_write_t> {
- public:
-  WriteReq();
-
-  Stream& GetStream() const {
-    return *static_cast<Stream*>(GetRaw()->handle->data);
-  }
-
-  /**
-   * Write completed signal.  This is called even if an error occurred.
-   * @param err error value
-   */
-  sig::Signal<Error> finish;
-};
-
-/**
- * Stream handle.
- * Stream handles provide an abstraction of a duplex communication channel.
- * This is an abstract type; there are three stream implementations (Tcp,
- * Pipe, and Tty).
- */
-class Stream : public Handle {
- public:
-  std::shared_ptr<Stream> shared_from_this() {
-    return std::static_pointer_cast<Stream>(Handle::shared_from_this());
-  }
-
-  std::shared_ptr<const Stream> shared_from_this() const {
-    return std::static_pointer_cast<const Stream>(Handle::shared_from_this());
-  }
-
-  /**
-   * Shutdown the outgoing (write) side of a duplex stream. It waits for pending
-   * write requests to complete.  HandleShutdownComplete() is called on the
-   * request after shutdown is complete.
-   *
-   * @param req shutdown request
-   */
-  void Shutdown(const std::shared_ptr<ShutdownReq>& req);
-
-  /**
-   * Shutdown the outgoing (write) side of a duplex stream. It waits for pending
-   * write requests to complete.  The callback is called after shutdown is
-   * complete.  Errors will be reported to the stream error handler.
-   *
-   * @param callback Callback function to call when shutdown completes
-   * @return Connection object for the callback
-   */
-  void Shutdown(std::function<void()> callback = nullptr);
-
-  /**
-   * Start reading data from an incoming stream.
-   *
-   * This will only succeed after a connection has been established.
-   *
-   * A data signal will be emitted several times until there is no more
-   * data to read or `StopRead()` is called.
-   * An end signal will be emitted when there is no more data to read.
-   */
-  void StartRead();
-
-  /**
-   * Stop reading data from the stream.
-   *
-   * This function is idempotent and may be safely called on a stopped stream.
-   */
-  void StopRead() { Invoke(&uv_read_stop, GetRawStream()); }
-
-  /**
-   * Write data to the stream.
-   *
-   * Data are written in order. The lifetime of the data pointers passed in
-   * the `bufs` parameter must exceed the lifetime of the write request.
-   * An easy way to ensure this is to have the write request keep track of
-   * the data and use either its Complete() function or destructor to free the
-   * data.
-   *
-   * The finish signal will be emitted on the request object when the data
-   * has been written (or if an error occurs).
-   * The error signal will be emitted on the request object in case of errors.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @param req write request
-   */
-  void Write(span<const Buffer> bufs, const std::shared_ptr<WriteReq>& req);
-
-  /**
-   * Write data to the stream.
-   *
-   * Data are written in order. The lifetime of the data pointers passed in
-   * the `bufs` parameter must exceed the lifetime of the write request.
-   * An easy way to ensure this is to have the write request keep track of
-   * the data and use either its Complete() function or destructor to free the
-   * data.
-   *
-   * The finish signal will be emitted on the request object when the data
-   * has been written (or if an error occurs).
-   * The error signal will be emitted on the request object in case of errors.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @param req write request
-   */
-  void Write(std::initializer_list<Buffer> bufs,
-             const std::shared_ptr<WriteReq>& req) {
-    Write({bufs.begin(), bufs.end()}, req);
-  }
-
-  /**
-   * Write data to the stream.
-   *
-   * Data are written in order. The lifetime of the data pointers passed in
-   * the `bufs` parameter must exceed the lifetime of the write request.
-   * The callback can be used to free data after the request completes.
-   *
-   * The callback will be called when the data has been written (even if an
-   * error occurred).  Errors will be reported to the stream error handler.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @param callback Callback function to call when the write completes
-   */
-  void Write(span<const Buffer> bufs,
-             std::function<void(span<Buffer>, Error)> callback);
-
-  /**
-   * Write data to the stream.
-   *
-   * Data are written in order. The lifetime of the data pointers passed in
-   * the `bufs` parameter must exceed the lifetime of the write request.
-   * The callback can be used to free data after the request completes.
-   *
-   * The callback will be called when the data has been written (even if an
-   * error occurred).  Errors will be reported to the stream error handler.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @param callback Callback function to call when the write completes
-   */
-  void Write(std::initializer_list<Buffer> bufs,
-             std::function<void(span<Buffer>, Error)> callback) {
-    Write({bufs.begin(), bufs.end()}, std::move(callback));
-  }
-
-  /**
-   * Queue a write request if it can be completed immediately.
-   *
-   * Same as `Write()`, but won’t queue a write request if it can’t be
-   * completed immediately.
-   * An error signal will be emitted in case of errors.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @return Number of bytes written.
-   */
-  int TryWrite(span<const Buffer> bufs);
-
-  /**
-   * Queue a write request if it can be completed immediately.
-   *
-   * Same as `Write()`, but won’t queue a write request if it can’t be
-   * completed immediately.
-   * An error signal will be emitted in case of errors.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @return Number of bytes written.
-   */
-  int TryWrite(std::initializer_list<Buffer> bufs) {
-    return TryWrite({bufs.begin(), bufs.end()});
-  }
-
-  /**
-   * Check if the stream is readable.
-   * @return True if the stream is readable, false otherwise.
-   */
-  bool IsReadable() const noexcept {
-    return uv_is_readable(GetRawStream()) == 1;
-  }
-
-  /**
-   * @brief Checks if the stream is writable.
-   * @return True if the stream is writable, false otherwise.
-   */
-  bool IsWritable() const noexcept {
-    return uv_is_writable(GetRawStream()) == 1;
-  }
-
-  /**
-   * Enable or disable blocking mode for a stream.
-   *
-   * When blocking mode is enabled all writes complete synchronously. The
-   * interface remains unchanged otherwise, e.g. completion or failure of the
-   * operation will still be reported through events which are emitted
-   * asynchronously.
-   *
-   * @param enable True to enable blocking mode, false otherwise.
-   * @return True in case of success, false otherwise.
-   */
-  bool SetBlocking(bool enable) noexcept {
-    return uv_stream_set_blocking(GetRawStream(), enable) == 0;
-  }
-
-  /**
-   * Gets the amount of queued bytes waiting to be sent.
-   * @return Amount of queued bytes waiting to be sent.
-   */
-  size_t GetWriteQueueSize() const noexcept {
-    return GetRawStream()->write_queue_size;
-  }
-
-  /**
-   * Get the underlying stream data structure.
-   *
-   * @return The underlying stream data structure.
-   */
-  uv_stream_t* GetRawStream() const noexcept {
-    return reinterpret_cast<uv_stream_t*>(GetRawHandle());
-  }
-
-  /**
-   * Signal generated when data was read on a stream.
-   */
-  sig::Signal<Buffer&, size_t> data;
-
-  /**
-   * Signal generated when no more read data is available.
-   */
-  sig::Signal<> end;
-
- protected:
-  explicit Stream(uv_stream_t* uv_stream)
-      : Handle{reinterpret_cast<uv_handle_t*>(uv_stream)} {}
-};
-
-template <typename T, typename U>
-class StreamImpl : public Stream {
- public:
-  std::shared_ptr<T> shared_from_this() {
-    return std::static_pointer_cast<T>(Handle::shared_from_this());
-  }
-
-  std::shared_ptr<const T> shared_from_this() const {
-    return std::static_pointer_cast<const T>(Handle::shared_from_this());
-  }
-
-  /**
-   * Get the underlying handle data structure.
-   *
-   * @return The underlying handle data structure.
-   */
-  U* GetRaw() const noexcept {
-    return reinterpret_cast<U*>(this->GetRawHandle());
-  }
-
- protected:
-  StreamImpl() : Stream{static_cast<uv_stream_t*>(std::malloc(sizeof(U)))} {}
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_STREAM_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Tcp.h b/wpiutil/src/main/native/include/wpi/uv/Tcp.h
deleted file mode 100644
index c712f0b..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Tcp.h
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_TCP_H_
-#define WPIUTIL_WPI_UV_TCP_H_
-
-#include <uv.h>
-
-#include <chrono>
-#include <functional>
-#include <memory>
-#include <string_view>
-#include <utility>
-
-#include "wpi/uv/NetworkStream.h"
-
-namespace wpi::uv {
-
-class Loop;
-class TcpConnectReq;
-
-/**
- * TCP handle.
- * TCP handles are used to represent both TCP streams and servers.
- */
-class Tcp final : public NetworkStreamImpl<Tcp, uv_tcp_t> {
-  struct private_init {};
-
- public:
-  using Time = std::chrono::duration<uint64_t, std::milli>;
-
-  explicit Tcp(const private_init&) {}
-  ~Tcp() noexcept override = default;
-
-  /**
-   * Create a TCP handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param flags Flags
-   */
-  static std::shared_ptr<Tcp> Create(Loop& loop,
-                                     unsigned int flags = AF_UNSPEC);
-
-  /**
-   * Create a TCP handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param flags Flags
-   */
-  static std::shared_ptr<Tcp> Create(const std::shared_ptr<Loop>& loop,
-                                     unsigned int flags = AF_UNSPEC) {
-    return Create(*loop, flags);
-  }
-
-  /**
-   * Reuse this handle.  This closes the handle, and after the close completes,
-   * reinitializes it (identically to Create) and calls the provided callback.
-   * Unlike Close(), it does NOT emit the closed signal, however, IsClosing()
-   * will return true until the callback is called.  This does nothing if
-   * IsClosing() is true (e.g. if Close() was called).
-   *
-   * @param flags Flags
-   * @param callback Callback
-   */
-  void Reuse(std::function<void()> callback, unsigned int flags = AF_UNSPEC);
-
-  /**
-   * Accept incoming connection.
-   *
-   * This call is used in conjunction with `Listen()` to accept incoming
-   * connections. Call this function after receiving a ListenEvent event to
-   * accept the connection.
-   * An error signal will be emitted in case of errors.
-   *
-   * When the connection signal is emitted it is guaranteed that this
-   * function will complete successfully the first time. If you attempt to use
-   * it more than once, it may fail.
-   * It is suggested to only call this function once per connection signal.
-   *
-   * @return The stream handle for the accepted connection, or nullptr on error.
-   */
-  std::shared_ptr<Tcp> Accept();
-
-  /**
-   * Accept incoming connection.
-   *
-   * This call is used in conjunction with `Listen()` to accept incoming
-   * connections. Call this function after receiving a connection signal to
-   * accept the connection.
-   * An error signal will be emitted in case of errors.
-   *
-   * When the connection signal is emitted it is guaranteed that this
-   * function will complete successfully the first time. If you attempt to use
-   * it more than once, it may fail.
-   * It is suggested to only call this function once per connection signal.
-   *
-   * @param client Client stream object.
-   * @return False on error.
-   */
-  bool Accept(const std::shared_ptr<Tcp>& client) {
-    return NetworkStream::Accept(client);
-  }
-
-  /**
-   * Open an existing file descriptor or SOCKET as a TCP handle.
-   *
-   * @note The passed file descriptor or SOCKET is not checked for its type, but
-   * it's required that it represents a valid stream socket.
-   *
-   * @param sock A valid socket handle (either a file descriptor or a SOCKET).
-   */
-  void Open(uv_os_sock_t sock) { Invoke(&uv_tcp_open, GetRaw(), sock); }
-
-  /**
-   * Enable no delay operation (turns off Nagle's algorithm).
-   * @param enable True to enable it, false otherwise.
-   * @return True in case of success, false otherwise.
-   */
-  bool SetNoDelay(bool enable) { return uv_tcp_nodelay(GetRaw(), enable) == 0; }
-
-  /**
-   * Enable/Disable TCP keep-alive.
-   * @param enable True to enable it, false otherwise.
-   * @param time Initial delay in seconds (use
-   * `std::chrono::duration<unsigned int>`).
-   * @return True in case of success, false otherwise.
-   */
-  bool SetKeepAlive(bool enable, Time time = Time{0}) {
-    return uv_tcp_keepalive(GetRaw(), enable,
-                            static_cast<unsigned>(time.count())) == 0;
-  }
-
-  /**
-   * Enable/Disable simultaneous asynchronous accept requests.
-   *
-   * Enable/Disable simultaneous asynchronous accept requests that are
-   * queued by the operating system when listening for new TCP
-   * connections.
-   * This setting is used to tune a TCP server for the desired performance.
-   * Having simultaneous accepts can significantly improve the rate of
-   * accepting connections (which is why it is enabled by default) but may
-   * lead to uneven load distribution in multi-process setups.
-   *
-   * @param enable True to enable it, false otherwise.
-   * @return True in case of success, false otherwise.
-   */
-  bool SetSimultaneousAccepts(bool enable) {
-    return uv_tcp_simultaneous_accepts(GetRaw(), enable) == 0;
-  }
-
-  /**
-   * Bind the handle to an IPv4 or IPv6 address and port.
-   *
-   * A successful call to this function does not guarantee that the call to
-   * `Listen()` or `Connect()` will work properly.
-   * An error signal can be emitted because of either this function or the
-   * ones mentioned above.
-   *
-   * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
-   * @param flags Optional additional flags.
-   */
-  void Bind(const sockaddr& addr, unsigned int flags = 0) {
-    Invoke(&uv_tcp_bind, GetRaw(), &addr, flags);
-  }
-
-  void Bind(const sockaddr_in& addr, unsigned int flags = 0) {
-    Bind(reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-
-  void Bind(const sockaddr_in6& addr, unsigned int flags = 0) {
-    Bind(reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-
-  /**
-   * Bind the handle to an IPv4 address and port.
-   *
-   * A successful call to this function does not guarantee that the call to
-   * `Listen()` or `Connect()` will work properly.
-   * An error signal can be emitted because of either this function or the
-   * ones mentioned above.
-   *
-   * Available flags are:
-   *
-   * @param ip The address to which to bind.
-   * @param port The port to which to bind.
-   * @param flags Optional additional flags.
-   */
-  void Bind(std::string_view ip, unsigned int port, unsigned int flags = 0);
-
-  /**
-   * Bind the handle to an IPv6 address and port.
-   *
-   * A successful call to this function does not guarantee that the call to
-   * `Listen()` or `Connect()` will work properly.
-   * An error signal can be emitted because of either this function or the
-   * ones mentioned above.
-   *
-   * Available flags are:
-   *
-   * @param ip The address to which to bind.
-   * @param port The port to which to bind.
-   * @param flags Optional additional flags.
-   */
-  void Bind6(std::string_view ip, unsigned int port, unsigned int flags = 0);
-
-  /**
-   * Get the current address to which the handle is bound.
-   * @return The address (will be zeroed if an error occurred).
-   */
-  sockaddr_storage GetSock();
-
-  /**
-   * Get the address of the peer connected to the handle.
-   * @return The address (will be zeroed if an error occurred).
-   */
-  sockaddr_storage GetPeer();
-
-  /**
-   * Establish an IPv4 or IPv6 TCP connection.
-   *
-   * On Windows if the addr is initialized to point to an unspecified address
-   * (`0.0.0.0` or `::`) it will be changed to point to localhost. This is
-   * done to match the behavior of Linux systems.
-   *
-   * The connected signal is emitted on the request when the connection has been
-   * established.
-   * The error signal is emitted on the request in case of errors during the
-   * connection.
-   *
-   * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
-   * @param req connection request
-   */
-  void Connect(const sockaddr& addr, const std::shared_ptr<TcpConnectReq>& req);
-
-  void Connect(const sockaddr_in& addr,
-               const std::shared_ptr<TcpConnectReq>& req) {
-    Connect(reinterpret_cast<const sockaddr&>(addr), req);
-  }
-
-  void Connect(const sockaddr_in6& addr,
-               const std::shared_ptr<TcpConnectReq>& req) {
-    Connect(reinterpret_cast<const sockaddr&>(addr), req);
-  }
-
-  /**
-   * Establish an IPv4 or IPv6 TCP connection.
-   *
-   * On Windows if the addr is initialized to point to an unspecified address
-   * (`0.0.0.0` or `::`) it will be changed to point to localhost. This is
-   * done to match the behavior of Linux systems.
-   *
-   * The callback is called when the connection has been established.  Errors
-   * are reported to the stream error handler.
-   *
-   * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
-   * @param callback Callback function to call when connection established
-   */
-  void Connect(const sockaddr& addr, std::function<void()> callback);
-
-  void Connect(const sockaddr_in& addr, std::function<void()> callback) {
-    Connect(reinterpret_cast<const sockaddr&>(addr), std::move(callback));
-  }
-
-  void Connect(const sockaddr_in6& addr, std::function<void()> callback) {
-    Connect(reinterpret_cast<const sockaddr&>(addr), std::move(callback));
-  }
-
-  /**
-   * Establish an IPv4 TCP connection.
-   *
-   * On Windows if the addr is initialized to point to an unspecified address
-   * (`0.0.0.0` or `::`) it will be changed to point to localhost. This is
-   * done to match the behavior of Linux systems.
-   *
-   * The connected signal is emitted on the request when the connection has been
-   * established.
-   * The error signal is emitted on the request in case of errors during the
-   * connection.
-   *
-   * @param ip The address to which to connect to.
-   * @param port The port to which to connect to.
-   * @param req connection request
-   */
-  void Connect(std::string_view ip, unsigned int port,
-               const std::shared_ptr<TcpConnectReq>& req);
-
-  /**
-   * Establish an IPv4 TCP connection.
-   *
-   * On Windows if the addr is initialized to point to an unspecified address
-   * (`0.0.0.0` or `::`) it will be changed to point to localhost. This is
-   * done to match the behavior of Linux systems.
-   *
-   * The callback is called when the connection has been established.  Errors
-   * are reported to the stream error handler.
-   *
-   * @param ip The address to which to connect to.
-   * @param port The port to which to connect to.
-   * @param callback Callback function to call when connection established
-   */
-  void Connect(std::string_view ip, unsigned int port,
-               std::function<void()> callback);
-
-  /**
-   * Establish an IPv6 TCP connection.
-   *
-   * On Windows if the addr is initialized to point to an unspecified address
-   * (`0.0.0.0` or `::`) it will be changed to point to localhost. This is
-   * done to match the behavior of Linux systems.
-   *
-   * The connected signal is emitted on the request when the connection has been
-   * established.
-   * The error signal is emitted on the request in case of errors during the
-   * connection.
-   *
-   * @param ip The address to which to connect to.
-   * @param port The port to which to connect to.
-   * @param req connection request
-   */
-  void Connect6(std::string_view ip, unsigned int port,
-                const std::shared_ptr<TcpConnectReq>& req);
-
-  /**
-   * Establish an IPv6 TCP connection.
-   *
-   * On Windows if the addr is initialized to point to an unspecified address
-   * (`0.0.0.0` or `::`) it will be changed to point to localhost. This is
-   * done to match the behavior of Linux systems.
-   *
-   * The callback is called when the connection has been established.  Errors
-   * are reported to the stream error handler.
-   *
-   * @param ip The address to which to connect to.
-   * @param port The port to which to connect to.
-   * @param callback Callback function to call when connection established
-   */
-  void Connect6(std::string_view ip, unsigned int port,
-                std::function<void()> callback);
-
- private:
-  Tcp* DoAccept() override;
-
-  struct ReuseData {
-    std::function<void()> callback;
-    unsigned int flags;
-  };
-  std::unique_ptr<ReuseData> m_reuseData;
-};
-
-/**
- * TCP connection request.
- */
-class TcpConnectReq : public ConnectReq {
- public:
-  Tcp& GetStream() const {
-    return *static_cast<Tcp*>(&ConnectReq::GetStream());
-  }
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_TCP_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Timer.h b/wpiutil/src/main/native/include/wpi/uv/Timer.h
deleted file mode 100644
index 00363a5..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Timer.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_TIMER_H_
-#define WPIUTIL_WPI_UV_TIMER_H_
-
-#include <uv.h>
-
-#include <chrono>
-#include <functional>
-#include <memory>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Handle.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * Timer handle.
- * Timer handles are used to schedule signals to be called in the future.
- */
-class Timer final : public HandleImpl<Timer, uv_timer_t> {
-  struct private_init {};
-
- public:
-  using Time = std::chrono::duration<uint64_t, std::milli>;
-
-  explicit Timer(const private_init&) {}
-  ~Timer() noexcept override = default;
-
-  /**
-   * Create a timer handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Timer> Create(Loop& loop);
-
-  /**
-   * Create a timer handle.
-   *
-   * @param loop Loop object where this handle runs.
-   */
-  static std::shared_ptr<Timer> Create(const std::shared_ptr<Loop>& loop) {
-    return Create(*loop);
-  }
-
-  /**
-   * Create a timer that calls a functor after a given time interval.
-   *
-   * @param loop Loop object where the timer should run.
-   * @param timeout Time interval
-   * @param func Functor
-   */
-  static void SingleShot(Loop& loop, Time timeout, std::function<void()> func);
-
-  /**
-   * Create a timer that calls a functor after a given time interval.
-   *
-   * @param loop Loop object where the timer should run.
-   * @param timeout Time interval
-   * @param func Functor
-   */
-  static void SingleShot(const std::shared_ptr<Loop>& loop, Time timeout,
-                         std::function<void()> func) {
-    return SingleShot(*loop, timeout, std::move(func));
-  }
-
-  /**
-   * Start the timer.
-   *
-   * If timeout is zero, an event is emitted on the next event loop
-   * iteration. If repeat is non-zero, an event is emitted first
-   * after timeout milliseconds and then repeatedly after repeat milliseconds.
-   *
-   * @param timeout Milliseconds before to emit an event (use
-   * `std::chrono::duration<uint64_t, std::milli>`).
-   * @param repeat Milliseconds between successive events (use
-   * `std::chrono::duration<uint64_t, std::milli>`).
-   */
-  void Start(Time timeout, Time repeat = Time{0});
-
-  /**
-   * Stop the timer.
-   */
-  void Stop() { Invoke(&uv_timer_stop, GetRaw()); }
-
-  /**
-   * Stop the timer and restart it if it was repeating.
-   *
-   * Stop the timer, and if it is repeating restart it using the repeat value
-   * as the timeout.
-   * If the timer has never been started before it emits sigError.
-   */
-  void Again() { Invoke(&uv_timer_again, GetRaw()); }
-
-  /**
-   * Set the repeat interval value.
-   *
-   * The timer will be scheduled to run on the given interval and will follow
-   * normal timer semantics in the case of a time-slice overrun.
-   * For example, if a 50ms repeating timer first runs for 17ms, it will be
-   * scheduled to run again 33ms later. If other tasks consume more than the
-   * 33ms following the first timer event, then another event will be emitted
-   * as soon as possible.
-   *
-   * If the repeat value is set from a listener bound to an event, it does
-   * not immediately take effect. If the timer was non-repeating before, it
-   * will have been stopped. If it was repeating, then the old repeat value
-   * will have been used to schedule the next timeout.
-   *
-   * @param repeat Repeat interval in milliseconds (use
-   * `std::chrono::duration<uint64_t, std::milli>`).
-   */
-  void SetRepeat(Time repeat) { uv_timer_set_repeat(GetRaw(), repeat.count()); }
-
-  /**
-   * Get the timer repeat value.
-   * @return Timer repeat value in milliseconds (as a
-   * `std::chrono::duration<uint64_t, std::milli>`).
-   */
-  Time GetRepeat() const { return Time{uv_timer_get_repeat(GetRaw())}; }
-
-  /**
-   * Signal generated when the timeout event occurs.
-   */
-  sig::Signal<> timeout;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_TIMER_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Tty.h b/wpiutil/src/main/native/include/wpi/uv/Tty.h
deleted file mode 100644
index bb0a6db..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Tty.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_TTY_H_
-#define WPIUTIL_WPI_UV_TTY_H_
-
-#include <uv.h>
-
-#include <memory>
-#include <utility>
-
-#include "wpi/uv/Stream.h"
-
-namespace wpi::uv {
-
-class Loop;
-class Tty;
-
-/**
- * TTY handle.
- * TTY handles represent a stream for the console.
- */
-class Tty final : public StreamImpl<Tty, uv_tty_t> {
-  struct private_init {};
-
- public:
-  explicit Tty(const private_init&) {}
-  ~Tty() noexcept override = default;
-
-  /**
-   * Create a TTY handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param fd File descriptor, usually 0=stdin, 1=stdout, 2=stderr
-   * @param readable Specifies if you plan on calling StartRead().  stdin is
-   *                 readable, stdout is not.
-   */
-  static std::shared_ptr<Tty> Create(Loop& loop, uv_file fd, bool readable);
-
-  /**
-   * Create a TTY handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param fd File descriptor, usually 0=stdin, 1=stdout, 2=stderr
-   * @param readable Specifies if you plan on calling StartRead().  stdin is
-   *                 readable, stdout is not.
-   */
-  static std::shared_ptr<Tty> Create(const std::shared_ptr<Loop>& loop,
-                                     uv_file fd, bool readable) {
-    return Create(*loop, fd, readable);
-  }
-
-  /**
-   * Set the TTY using the specified terminal mode.
-   *
-   * @param mode terminal mode
-   */
-  void SetMode(uv_tty_mode_t mode) {
-    int err = uv_tty_set_mode(GetRaw(), mode);
-    if (err < 0) {
-      ReportError(err);
-    }
-  }
-
-  /**
-   * Reset TTY settings to default values for the next process to take over.
-   * Typically called when the program exits.
-   */
-  void ResetMode() { Invoke(&uv_tty_reset_mode); }
-
-  /**
-   * Gets the current window size.
-   * @return Window size (pair of width and height).
-   */
-  std::pair<int, int> GetWindowSize() {
-    int width = 0, height = 0;
-    Invoke(&uv_tty_get_winsize, GetRaw(), &width, &height);
-    return std::make_pair(width, height);
-  }
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_TTY_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Udp.h b/wpiutil/src/main/native/include/wpi/uv/Udp.h
deleted file mode 100644
index 71fab13..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Udp.h
+++ /dev/null
@@ -1,378 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_UDP_H_
-#define WPIUTIL_WPI_UV_UDP_H_
-
-#include <uv.h>
-
-#include <functional>
-#include <memory>
-#include <string_view>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/span.h"
-#include "wpi/uv/Handle.h"
-#include "wpi/uv/Request.h"
-
-namespace wpi::uv {
-
-class Loop;
-class Udp;
-
-/**
- * UDP send request.
- */
-class UdpSendReq : public RequestImpl<UdpSendReq, uv_udp_send_t> {
- public:
-  UdpSendReq();
-
-  Udp& GetUdp() const { return *static_cast<Udp*>(GetRaw()->handle->data); }
-
-  /**
-   * Send completed signal.  This is called even if an error occurred.
-   * @param err error value
-   */
-  sig::Signal<Error> complete;
-};
-
-/**
- * UDP handle.
- * UDP handles encapsulate UDP communication for both clients and servers.
- */
-class Udp final : public HandleImpl<Udp, uv_udp_t> {
-  struct private_init {};
-
- public:
-  explicit Udp(const private_init&) {}
-  ~Udp() noexcept override = default;
-
-  /**
-   * Create a UDP handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param flags Flags
-   */
-  static std::shared_ptr<Udp> Create(Loop& loop,
-                                     unsigned int flags = AF_UNSPEC);
-
-  /**
-   * Create a UDP handle.
-   *
-   * @param loop Loop object where this handle runs.
-   * @param flags Flags
-   */
-  static std::shared_ptr<Udp> Create(const std::shared_ptr<Loop>& loop,
-                                     unsigned int flags = AF_UNSPEC) {
-    return Create(*loop, flags);
-  }
-
-  /**
-   * Open an existing file descriptor or SOCKET as a UDP handle.
-   *
-   * @param sock A valid socket handle (either a file descriptor or a SOCKET).
-   */
-  void Open(uv_os_sock_t sock) { Invoke(&uv_udp_open, GetRaw(), sock); }
-
-  /**
-   * Bind the handle to an IPv4 or IPv6 address and port.
-   *
-   * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
-   * @param flags Optional additional flags.
-   */
-  void Bind(const sockaddr& addr, unsigned int flags = 0) {
-    Invoke(&uv_udp_bind, GetRaw(), &addr, flags);
-  }
-
-  void Bind(const sockaddr_in& addr, unsigned int flags = 0) {
-    Bind(reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-
-  void Bind(const sockaddr_in6& addr, unsigned int flags = 0) {
-    Bind(reinterpret_cast<const sockaddr&>(addr), flags);
-  }
-
-  /**
-   * Bind the handle to an IPv4 address and port.
-   *
-   * @param ip The address to which to bind.
-   * @param port The port to which to bind.
-   * @param flags Optional additional flags.
-   */
-  void Bind(std::string_view ip, unsigned int port, unsigned int flags = 0);
-
-  /**
-   * Bind the handle to an IPv6 address and port.
-   *
-   * @param ip The address to which to bind.
-   * @param port The port to which to bind.
-   * @param flags Optional additional flags.
-   */
-  void Bind6(std::string_view ip, unsigned int port, unsigned int flags = 0);
-
-  /**
-   * Associate the handle to a remote address and port, so every message sent
-   * by this handle is automatically sent to that destination.
-   *
-   * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
-   */
-  void Connect(const sockaddr& addr) {
-    Invoke(&uv_udp_connect, GetRaw(), &addr);
-  }
-
-  void Connect(const sockaddr_in& addr) {
-    Connect(reinterpret_cast<const sockaddr&>(addr));
-  }
-
-  void Connect(const sockaddr_in6& addr) {
-    Connect(reinterpret_cast<const sockaddr&>(addr));
-  }
-
-  /**
-   * Associate the handle to an IPv4 address and port, so every message sent
-   * by this handle is automatically sent to that destination.
-   *
-   * @param ip The address to which to bind.
-   * @param port The port to which to bind.
-   */
-  void Connect(std::string_view ip, unsigned int port);
-
-  /**
-   * Associate the handle to an IPv6 address and port, so every message sent
-   * by this handle is automatically sent to that destination.
-   *
-   * @param ip The address to which to bind.
-   * @param port The port to which to bind.
-   * @param flags Optional additional flags.
-   */
-  void Connect6(std::string_view ip, unsigned int port);
-
-  /**
-   * Get the remote IP and port on connected UDP handles.
-   * @return The address (will be zeroed if an error occurred).
-   */
-  sockaddr_storage GetPeer();
-
-  /**
-   * Get the current address to which the handle is bound.
-   * @return The address (will be zeroed if an error occurred).
-   */
-  sockaddr_storage GetSock();
-
-  /**
-   * Set membership for a multicast address.
-   *
-   * @param multicastAddr Multicast address to set membership for
-   * @param interfaceAddr Interface address
-   * @param membership Should be UV_JOIN_GROUP or UV_LEAVE_GROUP
-   */
-  void SetMembership(std::string_view multicastAddr,
-                     std::string_view interfaceAddr, uv_membership membership);
-
-  /**
-   * Set IP multicast loop flag.  Makes multicast packets loop back to local
-   * sockets.
-   *
-   * @param enabled True for enabled, false for disabled
-   */
-  void SetMulticastLoop(bool enabled) {
-    Invoke(&uv_udp_set_multicast_loop, GetRaw(), enabled ? 1 : 0);
-  }
-
-  /**
-   * Set the multicast TTL.
-   *
-   * @param ttl Time to live (1-255)
-   */
-  void SetMulticastTtl(int ttl) {
-    Invoke(&uv_udp_set_multicast_ttl, GetRaw(), ttl);
-  }
-
-  /**
-   * Set the multicast interface to send or receive data on.
-   *
-   * @param interfaceAddr Interface address
-   */
-  void SetMulticastInterface(std::string_view interfaceAddr);
-
-  /**
-   * Set broadcast on or off.
-   *
-   * @param enabled True for enabled, false for disabled
-   */
-  void SetBroadcast(bool enabled) {
-    Invoke(&uv_udp_set_broadcast, GetRaw(), enabled ? 1 : 0);
-  }
-
-  /**
-   * Set the time to live (TTL).
-   *
-   * @param ttl Time to live (1-255)
-   */
-  void SetTtl(int ttl) { Invoke(&uv_udp_set_ttl, GetRaw(), ttl); }
-
-  /**
-   * Send data over the UDP socket.  If the socket has not previously been bound
-   * with Bind() it will be bound to 0.0.0.0 (the "all interfaces" IPv4 address)
-   * and a random port number.
-   *
-   * Data are written in order. The lifetime of the data pointers passed in
-   * the `bufs` parameter must exceed the lifetime of the send request.
-   * The callback can be used to free data after the request completes.
-   *
-   * HandleSendComplete() will be called on the request object when the data
-   * has been written.  HandleSendComplete() is called even if an error occurs.
-   * HandleError() will be called on the request object in case of errors.
-   *
-   * @param addr sockaddr_in or sockaddr_in6 with the address and port of the
-   *             remote peer.
-   * @param bufs The buffers to be written to the stream.
-   * @param req write request
-   */
-  void Send(const sockaddr& addr, span<const Buffer> bufs,
-            const std::shared_ptr<UdpSendReq>& req);
-
-  void Send(const sockaddr_in& addr, span<const Buffer> bufs,
-            const std::shared_ptr<UdpSendReq>& req) {
-    Send(reinterpret_cast<const sockaddr&>(addr), bufs, req);
-  }
-
-  void Send(const sockaddr_in6& addr, span<const Buffer> bufs,
-            const std::shared_ptr<UdpSendReq>& req) {
-    Send(reinterpret_cast<const sockaddr&>(addr), bufs, req);
-  }
-
-  /**
-   * Variant of Send() for connected sockets.  Cannot be used with
-   * connectionless sockets.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @param req write request
-   */
-  void Send(span<const Buffer> bufs, const std::shared_ptr<UdpSendReq>& req);
-
-  /**
-   * Send data over the UDP socket.  If the socket has not previously been bound
-   * with Bind() it will be bound to 0.0.0.0 (the "all interfaces" IPv4 address)
-   * and a random port number.
-   *
-   * Data are written in order. The lifetime of the data pointers passed in
-   * the `bufs` parameter must exceed the lifetime of the send request.
-   * The callback can be used to free data after the request completes.
-   *
-   * The callback will be called when the data has been sent.  Errors will
-   * be reported via the error signal.
-   *
-   * @param addr sockaddr_in or sockaddr_in6 with the address and port of the
-   *             remote peer.
-   * @param bufs The buffers to be sent.
-   * @param callback Callback function to call when the data has been sent.
-   */
-  void Send(const sockaddr& addr, span<const Buffer> bufs,
-            std::function<void(span<Buffer>, Error)> callback);
-
-  void Send(const sockaddr_in& addr, span<const Buffer> bufs,
-            std::function<void(span<Buffer>, Error)> callback) {
-    Send(reinterpret_cast<const sockaddr&>(addr), bufs, std::move(callback));
-  }
-
-  void Send(const sockaddr_in6& addr, span<const Buffer> bufs,
-            std::function<void(span<Buffer>, Error)> callback) {
-    Send(reinterpret_cast<const sockaddr&>(addr), bufs, std::move(callback));
-  }
-
-  /**
-   * Variant of Send() for connected sockets.  Cannot be used with
-   * connectionless sockets.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @param callback Callback function to call when the data has been sent.
-   */
-  void Send(span<const Buffer> bufs,
-            std::function<void(span<Buffer>, Error)> callback);
-
-  /**
-   * Same as Send(), but won't queue a send request if it can't be completed
-   * immediately.
-   *
-   * @param addr sockaddr_in or sockaddr_in6 with the address and port of the
-   *             remote peer.
-   * @param bufs The buffers to be send.
-   * @return Number of bytes sent.
-   */
-  int TrySend(const sockaddr& addr, span<const Buffer> bufs) {
-    int val = uv_udp_try_send(GetRaw(), bufs.data(),
-                              static_cast<unsigned>(bufs.size()), &addr);
-    if (val < 0) {
-      this->ReportError(val);
-      return 0;
-    }
-    return val;
-  }
-
-  int TrySend(const sockaddr_in& addr, span<const Buffer> bufs) {
-    return TrySend(reinterpret_cast<const sockaddr&>(addr), bufs);
-  }
-
-  int TrySend(const sockaddr_in6& addr, span<const Buffer> bufs) {
-    return TrySend(reinterpret_cast<const sockaddr&>(addr), bufs);
-  }
-
-  /**
-   * Variant of TrySend() for connected sockets.  Cannot be used with
-   * connectionless sockets.
-   *
-   * @param bufs The buffers to be written to the stream.
-   * @return Number of bytes sent.
-   */
-  int TrySend(span<const Buffer> bufs) {
-    int val = uv_udp_try_send(GetRaw(), bufs.data(),
-                              static_cast<unsigned>(bufs.size()), nullptr);
-    if (val < 0) {
-      this->ReportError(val);
-      return 0;
-    }
-    return val;
-  }
-
-  /**
-   * Prepare for receiving data.  If the socket has not previously been bound
-   * with Bind() it is bound to 0.0.0.0 (the "all interfaces" IPv4 address) and
-   * a random port number.
-   *
-   * A received signal will be emitted for each received data packet until
-   * `StopRecv()` is called.
-   */
-  void StartRecv();
-
-  /**
-   * Stop listening for incoming datagrams.
-   */
-  void StopRecv() { Invoke(&uv_udp_recv_stop, GetRaw()); }
-
-  /**
-   * Gets the amount of queued bytes waiting to be sent.
-   * @return Amount of queued bytes waiting to be sent.
-   */
-  size_t GetSendQueueSize() const noexcept { return GetRaw()->send_queue_size; }
-
-  /**
-   * Gets the amount of queued packets waiting to be sent.
-   * @return Amount of queued packets waiting to be sent.
-   */
-  size_t GetSendQueueCount() const noexcept {
-    return GetRaw()->send_queue_count;
-  }
-
-  /**
-   * Signal generated for each incoming datagram.  Parameters are the buffer,
-   * the number of bytes received, the address of the sender, and flags.
-   */
-  sig::Signal<Buffer&, size_t, const sockaddr&, unsigned> received;
-};
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_UDP_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/Work.h b/wpiutil/src/main/native/include/wpi/uv/Work.h
deleted file mode 100644
index 5a3a5d2..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/Work.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_WORK_H_
-#define WPIUTIL_WPI_UV_WORK_H_
-
-#include <uv.h>
-
-#include <functional>
-#include <memory>
-#include <utility>
-
-#include "wpi/Signal.h"
-#include "wpi/uv/Request.h"
-
-namespace wpi::uv {
-
-class Loop;
-
-/**
- * Work request.
- * For use with `QueueWork()` function family.
- */
-class WorkReq : public RequestImpl<WorkReq, uv_work_t> {
- public:
-  WorkReq();
-
-  Loop& GetLoop() const { return *static_cast<Loop*>(GetRaw()->loop->data); }
-
-  /**
-   * Function(s) that will be run on the thread pool.
-   */
-  sig::Signal<> work;
-
-  /**
-   * Function(s) that will be run on the loop thread after the work on the
-   * thread pool has been completed by the work callback.
-   */
-  sig::Signal<> afterWork;
-};
-
-/**
- * Initializes a work request which will run on the thread pool.
- *
- * @param loop Event loop
- * @param req request
- */
-void QueueWork(Loop& loop, const std::shared_ptr<WorkReq>& req);
-
-/**
- * Initializes a work request which will run on the thread pool.
- *
- * @param loop Event loop
- * @param req request
- */
-inline void QueueWork(const std::shared_ptr<Loop>& loop,
-                      const std::shared_ptr<WorkReq>& req) {
-  QueueWork(*loop, req);
-}
-
-/**
- * Initializes a work request which will run on the thread pool.  The work
- * callback will be run on a thread from the thread pool, and the afterWork
- * callback will be called on the loop thread after the work completes.  Any
- * errors are forwarded to the loop.
- *
- * @param loop Event loop
- * @param work Work callback (called from separate thread)
- * @param afterWork After work callback (called on loop thread)
- */
-void QueueWork(Loop& loop, std::function<void()> work,
-               std::function<void()> afterWork);
-
-/**
- * Initializes a work request which will run on the thread pool.  The work
- * callback will be run on a thread from the thread pool, and the afterWork
- * callback will be called on the loop thread after the work completes.  Any
- * errors are forwarded to the loop.
- *
- * @param loop Event loop
- * @param work Work callback (called from separate thread)
- * @param afterWork After work callback (called on loop thread)
- */
-inline void QueueWork(const std::shared_ptr<Loop>& loop,
-                      std::function<void()> work,
-                      std::function<void()> afterWork) {
-  QueueWork(*loop, std::move(work), std::move(afterWork));
-}
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_WORK_H_
diff --git a/wpiutil/src/main/native/include/wpi/uv/util.h b/wpiutil/src/main/native/include/wpi/uv/util.h
deleted file mode 100644
index 01dec0b..0000000
--- a/wpiutil/src/main/native/include/wpi/uv/util.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef WPIUTIL_WPI_UV_UTIL_H_
-#define WPIUTIL_WPI_UV_UTIL_H_
-
-#include <uv.h>
-
-#include <cstring>
-#include <string_view>
-
-namespace wpi::uv {
-
-/**
- * Convert a binary structure containing an IPv4 address to a string.
- * @param addr Binary structure
- * @param ip Output string (any type that has `assign(char*, char*)`)
- * @param port Output port number
- * @return Error (same as `uv_ip4_name()`).
- */
-template <typename T>
-int AddrToName(const sockaddr_in& addr, T* ip, unsigned int* port) {
-  char name[128];
-  int err = uv_ip4_name(&addr, name, 128);
-  if (err == 0) {
-    ip->assign(name, name + std::strlen(name));
-    *port = ntohs(addr.sin_port);
-  } else {
-    ip->assign(name, name);
-  }
-  return err;
-}
-
-/**
- * Convert a binary structure containing an IPv6 address to a string.
- * @param addr Binary structure
- * @param ip Output string (any type that has `assign(char*, char*)`)
- * @param port Output port number
- * @return Error (same as `uv_ip6_name()`).
- */
-template <typename T>
-int AddrToName(const sockaddr_in6& addr, T* ip, unsigned int* port) {
-  char name[128];
-  int err = uv_ip6_name(&addr, name, 128);
-  if (err == 0) {
-    ip->assign(name, name + std::strlen(name));
-    *port = ntohs(addr.sin6_port);
-  } else {
-    ip->assign(name, name);
-  }
-  return err;
-}
-
-/**
- * Convert a binary structure containing an IPv4 or IPv6 address to a string.
- * @param addr Binary structure
- * @param ip Output string (any type that has `assign(char*, char*)`)
- * @param port Output port number
- * @return Error (same as `uv_ip6_name()`).
- */
-template <typename T>
-int AddrToName(const sockaddr_storage& addr, T* ip, unsigned int* port) {
-  if (addr.ss_family == AF_INET) {
-    return AddrToName(reinterpret_cast<const sockaddr_in&>(addr), ip, port);
-  }
-  if (addr.ss_family == AF_INET6) {
-    return AddrToName(reinterpret_cast<const sockaddr_in6&>(addr), ip, port);
-  }
-  char name[1];
-  ip->assign(name, name);
-  return -1;
-}
-
-/**
- * Convert a binary IPv4 address to a string.
- * @param addr Binary address
- * @param ip Output string (any type that has `assign(char*, char*)`)
- * @return Error (same as `uv_inet_ntop()`).
- */
-template <typename T>
-int AddrToName(const in_addr& addr, T* ip) {
-  char name[128];
-  int err = uv_inet_ntop(AF_INET, &addr, name, 128);
-  if (err == 0) {
-    ip->assign(name, name + std::strlen(name));
-  } else {
-    ip->assign(name, name);
-  }
-  return err;
-}
-
-/**
- * Convert a binary IPv6 address to a string.
- * @param addr Binary address
- * @param ip Output string (any type that has `assign(char*, char*)`)
- * @return Error (same as `uv_inet_ntop()`).
- */
-template <typename T>
-int AddrToName(const in6_addr& addr, T* ip) {
-  char name[128];
-  int err = uv_inet_ntop(AF_INET6, &addr, name, 128);
-  if (err == 0) {
-    ip->assign(name, name + std::strlen(name));
-  } else {
-    ip->assign(name, name);
-  }
-  return err;
-}
-
-/**
- * Convert a string containing an IPv4 address to a binary structure.
- * @param ip IPv4 address string
- * @param port Port number
- * @param addr Output binary structure
- * @return Error (same as `uv_ip4_addr()`).
- */
-int NameToAddr(std::string_view ip, unsigned int port, sockaddr_in* addr);
-
-/**
- * Convert a string containing an IPv6 address to a binary structure.
- * @param ip IPv6 address string
- * @param port Port number
- * @param addr Output binary structure
- * @return Error (same as `uv_ip6_addr()`).
- */
-int NameToAddr(std::string_view ip, unsigned int port, sockaddr_in6* addr);
-
-/**
- * Convert a string containing an IPv4 address to binary format.
- * @param ip IPv4 address string
- * @param addr Output binary
- * @return Error (same as `uv_inet_pton()`).
- */
-int NameToAddr(std::string_view ip, in_addr* addr);
-
-/**
- * Convert a string containing an IPv6 address to binary format.
- * @param ip IPv6 address string
- * @param addr Output binary
- * @return Error (same as `uv_inet_pton()`).
- */
-int NameToAddr(std::string_view ip, in6_addr* addr);
-
-}  // namespace wpi::uv
-
-#endif  // WPIUTIL_WPI_UV_UTIL_H_
diff --git a/wpiutil/src/main/native/libuv/include/uv.h b/wpiutil/src/main/native/libuv/include/uv.h
deleted file mode 100644
index ccf62c8..0000000
--- a/wpiutil/src/main/native/libuv/include/uv.h
+++ /dev/null
@@ -1,1683 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/* See https://github.com/libuv/libuv#documentation for documentation. */
-
-#ifndef UV_H
-#define UV_H
-
-#ifdef _WIN32
-  /* Windows - set up dll import/export decorators. */
-# if defined(BUILDING_UV_SHARED)
-    /* Building shared library. */
-#   define UV_EXTERN __declspec(dllexport)
-# elif defined(USING_UV_SHARED)
-    /* Using shared library. */
-#   define UV_EXTERN __declspec(dllimport)
-# else
-    /* Building static library. */
-#   define UV_EXTERN /* nothing */
-# endif
-#elif __GNUC__ >= 4
-# define UV_EXTERN __attribute__((visibility("default")))
-#else
-# define UV_EXTERN /* nothing */
-#endif
-
-#include "uv/errno.h"
-#include "uv/version.h"
-#include <stddef.h>
-#include <stdio.h>
-
-#include <stdint.h>
-
-#if defined(_WIN32)
-# include "uv/win.h"
-#else
-# include "uv/unix.h"
-#endif
-
-/* Expand this list if necessary. */
-#define UV_ERRNO_MAP(XX)                                                      \
-  XX(E2BIG, "argument list too long")                                         \
-  XX(EACCES, "permission denied")                                             \
-  XX(EADDRINUSE, "address already in use")                                    \
-  XX(EADDRNOTAVAIL, "address not available")                                  \
-  XX(EAFNOSUPPORT, "address family not supported")                            \
-  XX(EAGAIN, "resource temporarily unavailable")                              \
-  XX(EAI_ADDRFAMILY, "address family not supported")                          \
-  XX(EAI_AGAIN, "temporary failure")                                          \
-  XX(EAI_BADFLAGS, "bad ai_flags value")                                      \
-  XX(EAI_BADHINTS, "invalid value for hints")                                 \
-  XX(EAI_CANCELED, "request canceled")                                        \
-  XX(EAI_FAIL, "permanent failure")                                           \
-  XX(EAI_FAMILY, "ai_family not supported")                                   \
-  XX(EAI_MEMORY, "out of memory")                                             \
-  XX(EAI_NODATA, "no address")                                                \
-  XX(EAI_NONAME, "unknown node or service")                                   \
-  XX(EAI_OVERFLOW, "argument buffer overflow")                                \
-  XX(EAI_PROTOCOL, "resolved protocol is unknown")                            \
-  XX(EAI_SERVICE, "service not available for socket type")                    \
-  XX(EAI_SOCKTYPE, "socket type not supported")                               \
-  XX(EALREADY, "connection already in progress")                              \
-  XX(EBADF, "bad file descriptor")                                            \
-  XX(EBUSY, "resource busy or locked")                                        \
-  XX(ECANCELED, "operation canceled")                                         \
-  XX(ECHARSET, "invalid Unicode character")                                   \
-  XX(ECONNABORTED, "software caused connection abort")                        \
-  XX(ECONNREFUSED, "connection refused")                                      \
-  XX(ECONNRESET, "connection reset by peer")                                  \
-  XX(EDESTADDRREQ, "destination address required")                            \
-  XX(EEXIST, "file already exists")                                           \
-  XX(EFAULT, "bad address in system call argument")                           \
-  XX(EFBIG, "file too large")                                                 \
-  XX(EHOSTUNREACH, "host is unreachable")                                     \
-  XX(EINTR, "interrupted system call")                                        \
-  XX(EINVAL, "invalid argument")                                              \
-  XX(EIO, "i/o error")                                                        \
-  XX(EISCONN, "socket is already connected")                                  \
-  XX(EISDIR, "illegal operation on a directory")                              \
-  XX(ELOOP, "too many symbolic links encountered")                            \
-  XX(EMFILE, "too many open files")                                           \
-  XX(EMSGSIZE, "message too long")                                            \
-  XX(ENAMETOOLONG, "name too long")                                           \
-  XX(ENETDOWN, "network is down")                                             \
-  XX(ENETUNREACH, "network is unreachable")                                   \
-  XX(ENFILE, "file table overflow")                                           \
-  XX(ENOBUFS, "no buffer space available")                                    \
-  XX(ENODEV, "no such device")                                                \
-  XX(ENOENT, "no such file or directory")                                     \
-  XX(ENOMEM, "not enough memory")                                             \
-  XX(ENONET, "machine is not on the network")                                 \
-  XX(ENOPROTOOPT, "protocol not available")                                   \
-  XX(ENOSPC, "no space left on device")                                       \
-  XX(ENOSYS, "function not implemented")                                      \
-  XX(ENOTCONN, "socket is not connected")                                     \
-  XX(ENOTDIR, "not a directory")                                              \
-  XX(ENOTEMPTY, "directory not empty")                                        \
-  XX(ENOTSOCK, "socket operation on non-socket")                              \
-  XX(ENOTSUP, "operation not supported on socket")                            \
-  XX(EPERM, "operation not permitted")                                        \
-  XX(EPIPE, "broken pipe")                                                    \
-  XX(EPROTO, "protocol error")                                                \
-  XX(EPROTONOSUPPORT, "protocol not supported")                               \
-  XX(EPROTOTYPE, "protocol wrong type for socket")                            \
-  XX(ERANGE, "result too large")                                              \
-  XX(EROFS, "read-only file system")                                          \
-  XX(ESHUTDOWN, "cannot send after transport endpoint shutdown")              \
-  XX(ESPIPE, "invalid seek")                                                  \
-  XX(ESRCH, "no such process")                                                \
-  XX(ETIMEDOUT, "connection timed out")                                       \
-  XX(ETXTBSY, "text file is busy")                                            \
-  XX(EXDEV, "cross-device link not permitted")                                \
-  XX(UNKNOWN, "unknown error")                                                \
-  XX(EOF, "end of file")                                                      \
-  XX(ENXIO, "no such device or address")                                      \
-  XX(EMLINK, "too many links")                                                \
-  XX(EHOSTDOWN, "host is down")                                               \
-  XX(EREMOTEIO, "remote I/O error")                                           \
-  XX(ENOTTY, "inappropriate ioctl for device")                                \
-  XX(EFTYPE, "inappropriate file type or format")                             \
-
-#define UV_HANDLE_TYPE_MAP(XX)                                                \
-  XX(ASYNC, async)                                                            \
-  XX(CHECK, check)                                                            \
-  XX(FS_EVENT, fs_event)                                                      \
-  XX(FS_POLL, fs_poll)                                                        \
-  XX(HANDLE, handle)                                                          \
-  XX(IDLE, idle)                                                              \
-  XX(NAMED_PIPE, pipe)                                                        \
-  XX(POLL, poll)                                                              \
-  XX(PREPARE, prepare)                                                        \
-  XX(PROCESS, process)                                                        \
-  XX(STREAM, stream)                                                          \
-  XX(TCP, tcp)                                                                \
-  XX(TIMER, timer)                                                            \
-  XX(TTY, tty)                                                                \
-  XX(UDP, udp)                                                                \
-  XX(SIGNAL, signal)                                                          \
-
-#define UV_REQ_TYPE_MAP(XX)                                                   \
-  XX(REQ, req)                                                                \
-  XX(CONNECT, connect)                                                        \
-  XX(WRITE, write)                                                            \
-  XX(SHUTDOWN, shutdown)                                                      \
-  XX(UDP_SEND, udp_send)                                                      \
-  XX(FS, fs)                                                                  \
-  XX(WORK, work)                                                              \
-  XX(GETADDRINFO, getaddrinfo)                                                \
-  XX(GETNAMEINFO, getnameinfo)                                                \
-
-typedef enum {
-#define XX(code, _) UV_ ## code = UV__ ## code,
-  UV_ERRNO_MAP(XX)
-#undef XX
-  UV_ERRNO_MAX = UV__EOF - 1
-} uv_errno_t;
-
-typedef enum {
-  UV_UNKNOWN_HANDLE = 0,
-#define XX(uc, lc) UV_##uc,
-  UV_HANDLE_TYPE_MAP(XX)
-#undef XX
-  UV_FILE,
-  UV_HANDLE_TYPE_MAX
-} uv_handle_type;
-
-typedef enum {
-  UV_UNKNOWN_REQ = 0,
-#define XX(uc, lc) UV_##uc,
-  UV_REQ_TYPE_MAP(XX)
-#undef XX
-  UV_REQ_TYPE_PRIVATE
-  UV_REQ_TYPE_MAX
-} uv_req_type;
-
-
-/* Handle types. */
-typedef struct uv_loop_s uv_loop_t;
-typedef struct uv_handle_s uv_handle_t;
-typedef struct uv_dir_s uv_dir_t;
-typedef struct uv_stream_s uv_stream_t;
-typedef struct uv_tcp_s uv_tcp_t;
-typedef struct uv_udp_s uv_udp_t;
-typedef struct uv_pipe_s uv_pipe_t;
-typedef struct uv_tty_s uv_tty_t;
-typedef struct uv_poll_s uv_poll_t;
-typedef struct uv_timer_s uv_timer_t;
-typedef struct uv_prepare_s uv_prepare_t;
-typedef struct uv_check_s uv_check_t;
-typedef struct uv_idle_s uv_idle_t;
-typedef struct uv_async_s uv_async_t;
-typedef struct uv_process_s uv_process_t;
-typedef struct uv_fs_event_s uv_fs_event_t;
-typedef struct uv_fs_poll_s uv_fs_poll_t;
-typedef struct uv_signal_s uv_signal_t;
-
-/* Request types. */
-typedef struct uv_req_s uv_req_t;
-typedef struct uv_getaddrinfo_s uv_getaddrinfo_t;
-typedef struct uv_getnameinfo_s uv_getnameinfo_t;
-typedef struct uv_shutdown_s uv_shutdown_t;
-typedef struct uv_write_s uv_write_t;
-typedef struct uv_connect_s uv_connect_t;
-typedef struct uv_udp_send_s uv_udp_send_t;
-typedef struct uv_fs_s uv_fs_t;
-typedef struct uv_work_s uv_work_t;
-
-/* None of the above. */
-typedef struct uv_cpu_info_s uv_cpu_info_t;
-typedef struct uv_interface_address_s uv_interface_address_t;
-typedef struct uv_dirent_s uv_dirent_t;
-typedef struct uv_passwd_s uv_passwd_t;
-typedef struct uv_utsname_s uv_utsname_t;
-
-typedef enum {
-  UV_LOOP_BLOCK_SIGNAL
-} uv_loop_option;
-
-typedef enum {
-  UV_RUN_DEFAULT = 0,
-  UV_RUN_ONCE,
-  UV_RUN_NOWAIT
-} uv_run_mode;
-
-
-UV_EXTERN unsigned int uv_version(void);
-UV_EXTERN const char* uv_version_string(void);
-
-typedef void* (*uv_malloc_func)(size_t size);
-typedef void* (*uv_realloc_func)(void* ptr, size_t size);
-typedef void* (*uv_calloc_func)(size_t count, size_t size);
-typedef void (*uv_free_func)(void* ptr);
-
-UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func,
-                                   uv_realloc_func realloc_func,
-                                   uv_calloc_func calloc_func,
-                                   uv_free_func free_func);
-
-UV_EXTERN uv_loop_t* uv_default_loop(void);
-UV_EXTERN int uv_loop_init(uv_loop_t* loop);
-UV_EXTERN int uv_loop_close(uv_loop_t* loop);
-/*
- * NOTE:
- *  This function is DEPRECATED (to be removed after 0.12), users should
- *  allocate the loop manually and use uv_loop_init instead.
- */
-UV_EXTERN uv_loop_t* uv_loop_new(void);
-/*
- * NOTE:
- *  This function is DEPRECATED (to be removed after 0.12). Users should use
- *  uv_loop_close and free the memory manually instead.
- */
-UV_EXTERN void uv_loop_delete(uv_loop_t*);
-UV_EXTERN size_t uv_loop_size(void);
-UV_EXTERN int uv_loop_alive(const uv_loop_t* loop);
-UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...);
-UV_EXTERN int uv_loop_fork(uv_loop_t* loop);
-
-UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode);
-UV_EXTERN void uv_stop(uv_loop_t*);
-
-UV_EXTERN void uv_ref(uv_handle_t*);
-UV_EXTERN void uv_unref(uv_handle_t*);
-UV_EXTERN int uv_has_ref(const uv_handle_t*);
-
-UV_EXTERN void uv_update_time(uv_loop_t*);
-UV_EXTERN uint64_t uv_now(const uv_loop_t*);
-
-UV_EXTERN int uv_backend_fd(const uv_loop_t*);
-UV_EXTERN int uv_backend_timeout(const uv_loop_t*);
-
-typedef void (*uv_alloc_cb)(uv_handle_t* handle,
-                            size_t suggested_size,
-                            uv_buf_t* buf);
-typedef void (*uv_read_cb)(uv_stream_t* stream,
-                           ssize_t nread,
-                           const uv_buf_t* buf);
-typedef void (*uv_write_cb)(uv_write_t* req, int status);
-typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
-typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
-typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
-typedef void (*uv_close_cb)(uv_handle_t* handle);
-typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events);
-typedef void (*uv_timer_cb)(uv_timer_t* handle);
-typedef void (*uv_async_cb)(uv_async_t* handle);
-typedef void (*uv_prepare_cb)(uv_prepare_t* handle);
-typedef void (*uv_check_cb)(uv_check_t* handle);
-typedef void (*uv_idle_cb)(uv_idle_t* handle);
-typedef void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal);
-typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg);
-typedef void (*uv_fs_cb)(uv_fs_t* req);
-typedef void (*uv_work_cb)(uv_work_t* req);
-typedef void (*uv_after_work_cb)(uv_work_t* req, int status);
-typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req,
-                                  int status,
-                                  struct addrinfo* res);
-typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req,
-                                  int status,
-                                  const char* hostname,
-                                  const char* service);
-
-typedef struct {
-  long tv_sec;
-  long tv_nsec;
-} uv_timespec_t;
-
-
-typedef struct {
-  uint64_t st_dev;
-  uint64_t st_mode;
-  uint64_t st_nlink;
-  uint64_t st_uid;
-  uint64_t st_gid;
-  uint64_t st_rdev;
-  uint64_t st_ino;
-  uint64_t st_size;
-  uint64_t st_blksize;
-  uint64_t st_blocks;
-  uint64_t st_flags;
-  uint64_t st_gen;
-  uv_timespec_t st_atim;
-  uv_timespec_t st_mtim;
-  uv_timespec_t st_ctim;
-  uv_timespec_t st_birthtim;
-} uv_stat_t;
-
-
-typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle,
-                               const char* filename,
-                               int events,
-                               int status);
-
-typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle,
-                              int status,
-                              const uv_stat_t* prev,
-                              const uv_stat_t* curr);
-
-typedef void (*uv_signal_cb)(uv_signal_t* handle, int signum);
-
-
-typedef enum {
-  UV_LEAVE_GROUP = 0,
-  UV_JOIN_GROUP
-} uv_membership;
-
-
-UV_EXTERN int uv_translate_sys_error(int sys_errno);
-
-UV_EXTERN const char* uv_strerror(int err);
-UV_EXTERN char* uv_strerror_r(int err, char* buf, size_t buflen);
-
-UV_EXTERN const char* uv_err_name(int err);
-UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen);
-
-
-#define UV_REQ_FIELDS                                                         \
-  /* public */                                                                \
-  void* data;                                                                 \
-  /* read-only */                                                             \
-  uv_req_type type;                                                           \
-  /* private */                                                               \
-  void* reserved[6];                                                          \
-  UV_REQ_PRIVATE_FIELDS                                                       \
-
-/* Abstract base class of all requests. */
-struct uv_req_s {
-  UV_REQ_FIELDS
-};
-
-
-/* Platform-specific request types. */
-UV_PRIVATE_REQ_TYPES
-
-
-UV_EXTERN int uv_shutdown(uv_shutdown_t* req,
-                          uv_stream_t* handle,
-                          uv_shutdown_cb cb);
-
-struct uv_shutdown_s {
-  UV_REQ_FIELDS
-  uv_stream_t* handle;
-  uv_shutdown_cb cb;
-  UV_SHUTDOWN_PRIVATE_FIELDS
-};
-
-
-#define UV_HANDLE_FIELDS                                                      \
-  /* public */                                                                \
-  void* data;                                                                 \
-  /* read-only */                                                             \
-  uv_loop_t* loop;                                                            \
-  uv_handle_type type;                                                        \
-  /* private */                                                               \
-  uv_close_cb close_cb;                                                       \
-  void* handle_queue[2];                                                      \
-  union {                                                                     \
-    int fd;                                                                   \
-    void* reserved[4];                                                        \
-  } u;                                                                        \
-  UV_HANDLE_PRIVATE_FIELDS                                                    \
-
-/* The abstract base class of all handles. */
-struct uv_handle_s {
-  UV_HANDLE_FIELDS
-};
-
-UV_EXTERN size_t uv_handle_size(uv_handle_type type);
-UV_EXTERN uv_handle_type uv_handle_get_type(const uv_handle_t* handle);
-UV_EXTERN const char* uv_handle_type_name(uv_handle_type type);
-UV_EXTERN void* uv_handle_get_data(const uv_handle_t* handle);
-UV_EXTERN uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle);
-UV_EXTERN void uv_handle_set_data(uv_handle_t* handle, void* data);
-
-UV_EXTERN size_t uv_req_size(uv_req_type type);
-UV_EXTERN void* uv_req_get_data(const uv_req_t* req);
-UV_EXTERN void uv_req_set_data(uv_req_t* req, void* data);
-UV_EXTERN uv_req_type uv_req_get_type(const uv_req_t* req);
-UV_EXTERN const char* uv_req_type_name(uv_req_type type);
-
-UV_EXTERN int uv_is_active(const uv_handle_t* handle);
-
-UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg);
-
-/* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */
-UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream);
-UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream);
-
-UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb);
-
-UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value);
-UV_EXTERN int uv_recv_buffer_size(uv_handle_t* handle, int* value);
-
-UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd);
-
-UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);
-
-
-#define UV_STREAM_FIELDS                                                      \
-  /* number of bytes queued for writing */                                    \
-  size_t write_queue_size;                                                    \
-  uv_alloc_cb alloc_cb;                                                       \
-  uv_read_cb read_cb;                                                         \
-  /* private */                                                               \
-  UV_STREAM_PRIVATE_FIELDS
-
-/*
- * uv_stream_t is a subclass of uv_handle_t.
- *
- * uv_stream is an abstract class.
- *
- * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t and uv_tty_t.
- */
-struct uv_stream_s {
-  UV_HANDLE_FIELDS
-  UV_STREAM_FIELDS
-};
-
-UV_EXTERN size_t uv_stream_get_write_queue_size(const uv_stream_t* stream);
-
-UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
-UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);
-
-UV_EXTERN int uv_read_start(uv_stream_t*,
-                            uv_alloc_cb alloc_cb,
-                            uv_read_cb read_cb);
-UV_EXTERN int uv_read_stop(uv_stream_t*);
-
-UV_EXTERN int uv_write(uv_write_t* req,
-                       uv_stream_t* handle,
-                       const uv_buf_t bufs[],
-                       unsigned int nbufs,
-                       uv_write_cb cb);
-UV_EXTERN int uv_write2(uv_write_t* req,
-                        uv_stream_t* handle,
-                        const uv_buf_t bufs[],
-                        unsigned int nbufs,
-                        uv_stream_t* send_handle,
-                        uv_write_cb cb);
-UV_EXTERN int uv_try_write(uv_stream_t* handle,
-                           const uv_buf_t bufs[],
-                           unsigned int nbufs);
-
-/* uv_write_t is a subclass of uv_req_t. */
-struct uv_write_s {
-  UV_REQ_FIELDS
-  uv_write_cb cb;
-  uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */
-  uv_stream_t* handle;
-  UV_WRITE_PRIVATE_FIELDS
-};
-
-
-UV_EXTERN int uv_is_readable(const uv_stream_t* handle);
-UV_EXTERN int uv_is_writable(const uv_stream_t* handle);
-
-UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking);
-
-UV_EXTERN int uv_is_closing(const uv_handle_t* handle);
-
-
-/*
- * uv_tcp_t is a subclass of uv_stream_t.
- *
- * Represents a TCP stream or TCP server.
- */
-struct uv_tcp_s {
-  UV_HANDLE_FIELDS
-  UV_STREAM_FIELDS
-  UV_TCP_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle);
-UV_EXTERN int uv_tcp_init_ex(uv_loop_t*, uv_tcp_t* handle, unsigned int flags);
-UV_EXTERN int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock);
-UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
-UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle,
-                               int enable,
-                               unsigned int delay);
-UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
-
-enum uv_tcp_flags {
-  /* Used with uv_tcp_bind, when an IPv6 address is used. */
-  UV_TCP_IPV6ONLY = 1
-};
-
-UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle,
-                          const struct sockaddr* addr,
-                          unsigned int flags);
-UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle,
-                                 struct sockaddr* name,
-                                 int* namelen);
-UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle,
-                                 struct sockaddr* name,
-                                 int* namelen);
-UV_EXTERN int uv_tcp_connect(uv_connect_t* req,
-                             uv_tcp_t* handle,
-                             const struct sockaddr* addr,
-                             uv_connect_cb cb);
-
-/* uv_connect_t is a subclass of uv_req_t. */
-struct uv_connect_s {
-  UV_REQ_FIELDS
-  uv_connect_cb cb;
-  uv_stream_t* handle;
-  UV_CONNECT_PRIVATE_FIELDS
-};
-
-
-/*
- * UDP support.
- */
-
-enum uv_udp_flags {
-  /* Disables dual stack mode. */
-  UV_UDP_IPV6ONLY = 1,
-  /*
-   * Indicates message was truncated because read buffer was too small. The
-   * remainder was discarded by the OS. Used in uv_udp_recv_cb.
-   */
-  UV_UDP_PARTIAL = 2,
-  /*
-   * Indicates if SO_REUSEADDR will be set when binding the handle.
-   * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other
-   * Unix platforms, it sets the SO_REUSEADDR flag.  What that means is that
-   * multiple threads or processes can bind to the same address without error
-   * (provided they all set the flag) but only the last one to bind will receive
-   * any traffic, in effect "stealing" the port from the previous listener.
-   */
-  UV_UDP_REUSEADDR = 4
-};
-
-typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
-typedef void (*uv_udp_recv_cb)(uv_udp_t* handle,
-                               ssize_t nread,
-                               const uv_buf_t* buf,
-                               const struct sockaddr* addr,
-                               unsigned flags);
-
-/* uv_udp_t is a subclass of uv_handle_t. */
-struct uv_udp_s {
-  UV_HANDLE_FIELDS
-  /* read-only */
-  /*
-   * Number of bytes queued for sending. This field strictly shows how much
-   * information is currently queued.
-   */
-  size_t send_queue_size;
-  /*
-   * Number of send requests currently in the queue awaiting to be processed.
-   */
-  size_t send_queue_count;
-  UV_UDP_PRIVATE_FIELDS
-};
-
-/* uv_udp_send_t is a subclass of uv_req_t. */
-struct uv_udp_send_s {
-  UV_REQ_FIELDS
-  uv_udp_t* handle;
-  uv_udp_send_cb cb;
-  UV_UDP_SEND_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
-UV_EXTERN int uv_udp_init_ex(uv_loop_t*, uv_udp_t* handle, unsigned int flags);
-UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
-UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
-                          const struct sockaddr* addr,
-                          unsigned int flags);
-UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr);
-
-UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle,
-                                 struct sockaddr* name,
-                                 int* namelen);
-UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle,
-                                 struct sockaddr* name,
-                                 int* namelen);
-UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,
-                                    const char* multicast_addr,
-                                    const char* interface_addr,
-                                    uv_membership membership);
-UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on);
-UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);
-UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle,
-                                             const char* interface_addr);
-UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on);
-UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl);
-UV_EXTERN int uv_udp_send(uv_udp_send_t* req,
-                          uv_udp_t* handle,
-                          const uv_buf_t bufs[],
-                          unsigned int nbufs,
-                          const struct sockaddr* addr,
-                          uv_udp_send_cb send_cb);
-UV_EXTERN int uv_udp_try_send(uv_udp_t* handle,
-                              const uv_buf_t bufs[],
-                              unsigned int nbufs,
-                              const struct sockaddr* addr);
-UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
-                                uv_alloc_cb alloc_cb,
-                                uv_udp_recv_cb recv_cb);
-UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
-UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
-UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);
-
-
-/*
- * uv_tty_t is a subclass of uv_stream_t.
- *
- * Representing a stream for the console.
- */
-struct uv_tty_s {
-  UV_HANDLE_FIELDS
-  UV_STREAM_FIELDS
-  UV_TTY_PRIVATE_FIELDS
-};
-
-typedef enum {
-  /* Initial/normal terminal mode */
-  UV_TTY_MODE_NORMAL,
-  /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
-  UV_TTY_MODE_RAW,
-  /* Binary-safe I/O mode for IPC (Unix-only) */
-  UV_TTY_MODE_IO
-} uv_tty_mode_t;
-
-UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable);
-UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode);
-UV_EXTERN int uv_tty_reset_mode(void);
-UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height);
-
-inline int uv_tty_set_mode(uv_tty_t* handle, int mode) {
-  return uv_tty_set_mode(handle, static_cast<uv_tty_mode_t>(mode));
-}
-
-UV_EXTERN uv_handle_type uv_guess_handle(uv_file file);
-
-/*
- * uv_pipe_t is a subclass of uv_stream_t.
- *
- * Representing a pipe stream or pipe server. On Windows this is a Named
- * Pipe. On Unix this is a Unix domain socket.
- */
-struct uv_pipe_s {
-  UV_HANDLE_FIELDS
-  UV_STREAM_FIELDS
-  int ipc; /* non-zero if this pipe is used for passing handles */
-  UV_PIPE_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc);
-UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file);
-UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
-UV_EXTERN void uv_pipe_connect(uv_connect_t* req,
-                               uv_pipe_t* handle,
-                               const char* name,
-                               uv_connect_cb cb);
-UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
-                                  char* buffer,
-                                  size_t* size);
-UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle,
-                                  char* buffer,
-                                  size_t* size);
-UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
-UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle);
-UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
-UV_EXTERN int uv_pipe_chmod(uv_pipe_t* handle, int flags);
-
-
-struct uv_poll_s {
-  UV_HANDLE_FIELDS
-  uv_poll_cb poll_cb;
-  UV_POLL_PRIVATE_FIELDS
-};
-
-enum uv_poll_event {
-  UV_READABLE = 1,
-  UV_WRITABLE = 2,
-  UV_DISCONNECT = 4,
-  UV_PRIORITIZED = 8
-};
-
-UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);
-UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop,
-                                  uv_poll_t* handle,
-                                  uv_os_sock_t socket);
-UV_EXTERN int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb);
-UV_EXTERN int uv_poll_stop(uv_poll_t* handle);
-
-
-struct uv_prepare_s {
-  UV_HANDLE_FIELDS
-  UV_PREPARE_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare);
-UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb);
-UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare);
-
-
-struct uv_check_s {
-  UV_HANDLE_FIELDS
-  UV_CHECK_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check);
-UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb);
-UV_EXTERN int uv_check_stop(uv_check_t* check);
-
-
-struct uv_idle_s {
-  UV_HANDLE_FIELDS
-  UV_IDLE_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle);
-UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb);
-UV_EXTERN int uv_idle_stop(uv_idle_t* idle);
-
-
-struct uv_async_s {
-  UV_HANDLE_FIELDS
-  UV_ASYNC_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_async_init(uv_loop_t*,
-                            uv_async_t* async,
-                            uv_async_cb async_cb);
-UV_EXTERN int uv_async_send(uv_async_t* async);
-
-
-/*
- * uv_timer_t is a subclass of uv_handle_t.
- *
- * Used to get woken up at a specified time in the future.
- */
-struct uv_timer_s {
-  UV_HANDLE_FIELDS
-  UV_TIMER_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle);
-UV_EXTERN int uv_timer_start(uv_timer_t* handle,
-                             uv_timer_cb cb,
-                             uint64_t timeout,
-                             uint64_t repeat);
-UV_EXTERN int uv_timer_stop(uv_timer_t* handle);
-UV_EXTERN int uv_timer_again(uv_timer_t* handle);
-UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat);
-UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle);
-
-
-/*
- * uv_getaddrinfo_t is a subclass of uv_req_t.
- *
- * Request object for uv_getaddrinfo.
- */
-struct uv_getaddrinfo_s {
-  UV_REQ_FIELDS
-  /* read-only */
-  uv_loop_t* loop;
-  /* struct addrinfo* addrinfo is marked as private, but it really isn't. */
-  UV_GETADDRINFO_PRIVATE_FIELDS
-};
-
-
-UV_EXTERN int uv_getaddrinfo(uv_loop_t* loop,
-                             uv_getaddrinfo_t* req,
-                             uv_getaddrinfo_cb getaddrinfo_cb,
-                             const char* node,
-                             const char* service,
-                             const struct addrinfo* hints);
-UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai);
-
-
-/*
-* uv_getnameinfo_t is a subclass of uv_req_t.
-*
-* Request object for uv_getnameinfo.
-*/
-struct uv_getnameinfo_s {
-  UV_REQ_FIELDS
-  /* read-only */
-  uv_loop_t* loop;
-  /* host and service are marked as private, but they really aren't. */
-  UV_GETNAMEINFO_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_getnameinfo(uv_loop_t* loop,
-                             uv_getnameinfo_t* req,
-                             uv_getnameinfo_cb getnameinfo_cb,
-                             const struct sockaddr* addr,
-                             int flags);
-
-
-/* uv_spawn() options. */
-typedef enum {
-  UV_IGNORE         = 0x00,
-  UV_CREATE_PIPE    = 0x01,
-  UV_INHERIT_FD     = 0x02,
-  UV_INHERIT_STREAM = 0x04,
-
-  /*
-   * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE
-   * determine the direction of flow, from the child process' perspective. Both
-   * flags may be specified to create a duplex data stream.
-   */
-  UV_READABLE_PIPE  = 0x10,
-  UV_WRITABLE_PIPE  = 0x20,
-
-  /*
-   * Open the child pipe handle in overlapped mode on Windows.
-   * On Unix it is silently ignored.
-   */
-  UV_OVERLAPPED_PIPE = 0x40
-} uv_stdio_flags;
-
-typedef struct uv_stdio_container_s {
-  uv_stdio_flags flags;
-
-  union {
-    uv_stream_t* stream;
-    int fd;
-  } data;
-} uv_stdio_container_t;
-
-typedef struct uv_process_options_s {
-  uv_exit_cb exit_cb; /* Called after the process exits. */
-  const char* file;   /* Path to program to execute. */
-  /*
-   * Command line arguments. args[0] should be the path to the program. On
-   * Windows this uses CreateProcess which concatenates the arguments into a
-   * string this can cause some strange errors. See the note at
-   * windows_verbatim_arguments.
-   */
-  char** args;
-  /*
-   * This will be set as the environ variable in the subprocess. If this is
-   * NULL then the parents environ will be used.
-   */
-  char** env;
-  /*
-   * If non-null this represents a directory the subprocess should execute
-   * in. Stands for current working directory.
-   */
-  const char* cwd;
-  /*
-   * Various flags that control how uv_spawn() behaves. See the definition of
-   * `enum uv_process_flags` below.
-   */
-  unsigned int flags;
-  /*
-   * The `stdio` field points to an array of uv_stdio_container_t structs that
-   * describe the file descriptors that will be made available to the child
-   * process. The convention is that stdio[0] points to stdin, fd 1 is used for
-   * stdout, and fd 2 is stderr.
-   *
-   * Note that on windows file descriptors greater than 2 are available to the
-   * child process only if the child processes uses the MSVCRT runtime.
-   */
-  int stdio_count;
-  uv_stdio_container_t* stdio;
-  /*
-   * Libuv can change the child process' user/group id. This happens only when
-   * the appropriate bits are set in the flags fields. This is not supported on
-   * windows; uv_spawn() will fail and set the error to UV_ENOTSUP.
-   */
-  uv_uid_t uid;
-  uv_gid_t gid;
-} uv_process_options_t;
-
-/*
- * These are the flags that can be used for the uv_process_options.flags field.
- */
-enum uv_process_flags {
-  /*
-   * Set the child process' user id. The user id is supplied in the `uid` field
-   * of the options struct. This does not work on windows; setting this flag
-   * will cause uv_spawn() to fail.
-   */
-  UV_PROCESS_SETUID = (1 << 0),
-  /*
-   * Set the child process' group id. The user id is supplied in the `gid`
-   * field of the options struct. This does not work on windows; setting this
-   * flag will cause uv_spawn() to fail.
-   */
-  UV_PROCESS_SETGID = (1 << 1),
-  /*
-   * Do not wrap any arguments in quotes, or perform any other escaping, when
-   * converting the argument list into a command line string. This option is
-   * only meaningful on Windows systems. On Unix it is silently ignored.
-   */
-  UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2),
-  /*
-   * Spawn the child process in a detached state - this will make it a process
-   * group leader, and will effectively enable the child to keep running after
-   * the parent exits.  Note that the child process will still keep the
-   * parent's event loop alive unless the parent process calls uv_unref() on
-   * the child's process handle.
-   */
-  UV_PROCESS_DETACHED = (1 << 3),
-  /*
-   * Hide the subprocess window that would normally be created. This option is
-   * only meaningful on Windows systems. On Unix it is silently ignored.
-   */
-  UV_PROCESS_WINDOWS_HIDE = (1 << 4),
-  /*
-   * Hide the subprocess console window that would normally be created. This
-   * option is only meaningful on Windows systems. On Unix it is silently
-   * ignored.
-   */
-  UV_PROCESS_WINDOWS_HIDE_CONSOLE = (1 << 5),
-  /*
-   * Hide the subprocess GUI window that would normally be created. This
-   * option is only meaningful on Windows systems. On Unix it is silently
-   * ignored.
-   */
-  UV_PROCESS_WINDOWS_HIDE_GUI = (1 << 6)
-};
-
-/*
- * uv_process_t is a subclass of uv_handle_t.
- */
-struct uv_process_s {
-  UV_HANDLE_FIELDS
-  uv_exit_cb exit_cb;
-  int pid;
-  UV_PROCESS_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_spawn(uv_loop_t* loop,
-                       uv_process_t* handle,
-                       const uv_process_options_t* options);
-UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
-UV_EXTERN int uv_kill(int pid, int signum);
-UV_EXTERN uv_pid_t uv_process_get_pid(const uv_process_t*);
-
-
-/*
- * uv_work_t is a subclass of uv_req_t.
- */
-struct uv_work_s {
-  UV_REQ_FIELDS
-  uv_loop_t* loop;
-  uv_work_cb work_cb;
-  uv_after_work_cb after_work_cb;
-  UV_WORK_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_queue_work(uv_loop_t* loop,
-                            uv_work_t* req,
-                            uv_work_cb work_cb,
-                            uv_after_work_cb after_work_cb);
-
-UV_EXTERN int uv_cancel(uv_req_t* req);
-
-
-struct uv_cpu_times_s {
-  uint64_t user;
-  uint64_t nice;
-  uint64_t sys;
-  uint64_t idle;
-  uint64_t irq;
-};
-
-struct uv_cpu_info_s {
-  char* model;
-  int speed;
-  struct uv_cpu_times_s cpu_times;
-};
-
-struct uv_interface_address_s {
-  char* name;
-  char phys_addr[6];
-  int is_internal;
-  union {
-    struct sockaddr_in address4;
-    struct sockaddr_in6 address6;
-  } address;
-  union {
-    struct sockaddr_in netmask4;
-    struct sockaddr_in6 netmask6;
-  } netmask;
-};
-
-struct uv_passwd_s {
-  char* username;
-  long uid;
-  long gid;
-  char* shell;
-  char* homedir;
-};
-
-struct uv_utsname_s {
-  char sysname[256];
-  char release[256];
-  char version[256];
-  char machine[256];
-  /* This struct does not contain the nodename and domainname fields present in
-     the utsname type. domainname is a GNU extension. Both fields are referred
-     to as meaningless in the docs. */
-};
-
-typedef enum {
-  UV_DIRENT_UNKNOWN,
-  UV_DIRENT_FILE,
-  UV_DIRENT_DIR,
-  UV_DIRENT_LINK,
-  UV_DIRENT_FIFO,
-  UV_DIRENT_SOCKET,
-  UV_DIRENT_CHAR,
-  UV_DIRENT_BLOCK
-} uv_dirent_type_t;
-
-struct uv_dirent_s {
-  const char* name;
-  uv_dirent_type_t type;
-};
-
-UV_EXTERN char** uv_setup_args(int argc, char** argv);
-UV_EXTERN int uv_get_process_title(char* buffer, size_t size);
-UV_EXTERN int uv_set_process_title(const char* title);
-UV_EXTERN int uv_resident_set_memory(size_t* rss);
-UV_EXTERN int uv_uptime(double* uptime);
-UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
-UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);
-
-typedef struct {
-  long tv_sec;
-  long tv_usec;
-} uv_timeval_t;
-
-typedef struct {
-  int64_t tv_sec;
-  int32_t tv_usec;
-} uv_timeval64_t;
-
-typedef struct {
-   uv_timeval_t ru_utime; /* user CPU time used */
-   uv_timeval_t ru_stime; /* system CPU time used */
-   uint64_t ru_maxrss;    /* maximum resident set size */
-   uint64_t ru_ixrss;     /* integral shared memory size */
-   uint64_t ru_idrss;     /* integral unshared data size */
-   uint64_t ru_isrss;     /* integral unshared stack size */
-   uint64_t ru_minflt;    /* page reclaims (soft page faults) */
-   uint64_t ru_majflt;    /* page faults (hard page faults) */
-   uint64_t ru_nswap;     /* swaps */
-   uint64_t ru_inblock;   /* block input operations */
-   uint64_t ru_oublock;   /* block output operations */
-   uint64_t ru_msgsnd;    /* IPC messages sent */
-   uint64_t ru_msgrcv;    /* IPC messages received */
-   uint64_t ru_nsignals;  /* signals received */
-   uint64_t ru_nvcsw;     /* voluntary context switches */
-   uint64_t ru_nivcsw;    /* involuntary context switches */
-} uv_rusage_t;
-
-UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);
-
-UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
-UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
-UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd);
-UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
-UV_EXTERN uv_pid_t uv_os_getpid(void);
-UV_EXTERN uv_pid_t uv_os_getppid(void);
-
-#define UV_PRIORITY_LOW 19
-#define UV_PRIORITY_BELOW_NORMAL 10
-#define UV_PRIORITY_NORMAL 0
-#define UV_PRIORITY_ABOVE_NORMAL -7
-#define UV_PRIORITY_HIGH -14
-#define UV_PRIORITY_HIGHEST -20
-
-UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority);
-UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority);
-
-UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
-UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
-
-UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
-                                     int* count);
-UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
-                                           int count);
-
-UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
-UV_EXTERN int uv_os_setenv(const char* name, const char* value);
-UV_EXTERN int uv_os_unsetenv(const char* name);
-
-#ifdef MAXHOSTNAMELEN
-# define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1)
-#else
-  /*
-    Fallback for the maximum hostname size, including the null terminator. The
-    Windows gethostname() documentation states that 256 bytes will always be
-    large enough to hold the null-terminated hostname.
-  */
-# define UV_MAXHOSTNAMESIZE 256
-#endif
-
-UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
-
-UV_EXTERN int uv_os_uname(uv_utsname_t* buffer);
-
-
-typedef enum {
-  UV_FS_UNKNOWN = -1,
-  UV_FS_CUSTOM,
-  UV_FS_OPEN,
-  UV_FS_CLOSE,
-  UV_FS_READ,
-  UV_FS_WRITE,
-  UV_FS_SENDFILE,
-  UV_FS_STAT,
-  UV_FS_LSTAT,
-  UV_FS_FSTAT,
-  UV_FS_FTRUNCATE,
-  UV_FS_UTIME,
-  UV_FS_FUTIME,
-  UV_FS_ACCESS,
-  UV_FS_CHMOD,
-  UV_FS_FCHMOD,
-  UV_FS_FSYNC,
-  UV_FS_FDATASYNC,
-  UV_FS_UNLINK,
-  UV_FS_RMDIR,
-  UV_FS_MKDIR,
-  UV_FS_MKDTEMP,
-  UV_FS_RENAME,
-  UV_FS_SCANDIR,
-  UV_FS_LINK,
-  UV_FS_SYMLINK,
-  UV_FS_READLINK,
-  UV_FS_CHOWN,
-  UV_FS_FCHOWN,
-  UV_FS_REALPATH,
-  UV_FS_COPYFILE,
-  UV_FS_LCHOWN,
-  UV_FS_OPENDIR,
-  UV_FS_READDIR,
-  UV_FS_CLOSEDIR
-} uv_fs_type;
-
-struct uv_dir_s {
-  uv_dirent_t* dirents;
-  size_t nentries;
-  void* reserved[4];
-  UV_DIR_PRIVATE_FIELDS
-};
-
-/* uv_fs_t is a subclass of uv_req_t. */
-struct uv_fs_s {
-  UV_REQ_FIELDS
-  uv_fs_type fs_type;
-  uv_loop_t* loop;
-  uv_fs_cb cb;
-  ssize_t result;
-  void* ptr;
-  const char* path;
-  uv_stat_t statbuf;  /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */
-  UV_FS_PRIVATE_FIELDS
-};
-
-UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);
-UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);
-UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);
-UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);
-UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);
-
-UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req);
-UV_EXTERN int uv_fs_close(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          uv_file file,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_open(uv_loop_t* loop,
-                         uv_fs_t* req,
-                         const char* path,
-                         int flags,
-                         int mode,
-                         uv_fs_cb cb);
-UV_EXTERN int uv_fs_read(uv_loop_t* loop,
-                         uv_fs_t* req,
-                         uv_file file,
-                         const uv_buf_t bufs[],
-                         unsigned int nbufs,
-                         int64_t offset,
-                         uv_fs_cb cb);
-UV_EXTERN int uv_fs_unlink(uv_loop_t* loop,
-                           uv_fs_t* req,
-                           const char* path,
-                           uv_fs_cb cb);
-UV_EXTERN int uv_fs_write(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          uv_file file,
-                          const uv_buf_t bufs[],
-                          unsigned int nbufs,
-                          int64_t offset,
-                          uv_fs_cb cb);
-/*
- * This flag can be used with uv_fs_copyfile() to return an error if the
- * destination already exists.
- */
-#define UV_FS_COPYFILE_EXCL   0x0001
-
-/*
- * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
- * If copy-on-write is not supported, a fallback copy mechanism is used.
- */
-#define UV_FS_COPYFILE_FICLONE 0x0002
-
-/*
- * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
- * If copy-on-write is not supported, an error is returned.
- */
-#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004
-
-UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
-                             uv_fs_t* req,
-                             const char* path,
-                             const char* new_path,
-                             int flags,
-                             uv_fs_cb cb);
-UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          const char* path,
-                          int mode,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop,
-                            uv_fs_t* req,
-                            const char* tpl,
-                            uv_fs_cb cb);
-UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          const char* path,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_scandir(uv_loop_t* loop,
-                            uv_fs_t* req,
-                            const char* path,
-                            int flags,
-                            uv_fs_cb cb);
-UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,
-                                 uv_dirent_t* ent);
-UV_EXTERN int uv_fs_opendir(uv_loop_t* loop,
-                            uv_fs_t* req,
-                            const char* path,
-                            uv_fs_cb cb);
-UV_EXTERN int uv_fs_readdir(uv_loop_t* loop,
-                            uv_fs_t* req,
-                            uv_dir_t* dir,
-                            uv_fs_cb cb);
-UV_EXTERN int uv_fs_closedir(uv_loop_t* loop,
-                             uv_fs_t* req,
-                             uv_dir_t* dir,
-                             uv_fs_cb cb);
-UV_EXTERN int uv_fs_stat(uv_loop_t* loop,
-                         uv_fs_t* req,
-                         const char* path,
-                         uv_fs_cb cb);
-UV_EXTERN int uv_fs_fstat(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          uv_file file,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_rename(uv_loop_t* loop,
-                           uv_fs_t* req,
-                           const char* path,
-                           const char* new_path,
-                           uv_fs_cb cb);
-UV_EXTERN int uv_fs_fsync(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          uv_file file,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop,
-                              uv_fs_t* req,
-                              uv_file file,
-                              uv_fs_cb cb);
-UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop,
-                              uv_fs_t* req,
-                              uv_file file,
-                              int64_t offset,
-                              uv_fs_cb cb);
-UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop,
-                             uv_fs_t* req,
-                             uv_file out_fd,
-                             uv_file in_fd,
-                             int64_t in_offset,
-                             size_t length,
-                             uv_fs_cb cb);
-UV_EXTERN int uv_fs_access(uv_loop_t* loop,
-                           uv_fs_t* req,
-                           const char* path,
-                           int mode,
-                           uv_fs_cb cb);
-UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          const char* path,
-                          int mode,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_utime(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          const char* path,
-                          double atime,
-                          double mtime,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_futime(uv_loop_t* loop,
-                           uv_fs_t* req,
-                           uv_file file,
-                           double atime,
-                           double mtime,
-                           uv_fs_cb cb);
-UV_EXTERN int uv_fs_lstat(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          const char* path,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_link(uv_loop_t* loop,
-                         uv_fs_t* req,
-                         const char* path,
-                         const char* new_path,
-                         uv_fs_cb cb);
-
-/*
- * This flag can be used with uv_fs_symlink() on Windows to specify whether
- * path argument points to a directory.
- */
-#define UV_FS_SYMLINK_DIR          0x0001
-
-/*
- * This flag can be used with uv_fs_symlink() on Windows to specify whether
- * the symlink is to be created using junction points.
- */
-#define UV_FS_SYMLINK_JUNCTION     0x0002
-
-UV_EXTERN int uv_fs_symlink(uv_loop_t* loop,
-                            uv_fs_t* req,
-                            const char* path,
-                            const char* new_path,
-                            int flags,
-                            uv_fs_cb cb);
-UV_EXTERN int uv_fs_readlink(uv_loop_t* loop,
-                             uv_fs_t* req,
-                             const char* path,
-                             uv_fs_cb cb);
-UV_EXTERN int uv_fs_realpath(uv_loop_t* loop,
-                             uv_fs_t* req,
-                             const char* path,
-                             uv_fs_cb cb);
-UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop,
-                           uv_fs_t* req,
-                           uv_file file,
-                           int mode,
-                           uv_fs_cb cb);
-UV_EXTERN int uv_fs_chown(uv_loop_t* loop,
-                          uv_fs_t* req,
-                          const char* path,
-                          uv_uid_t uid,
-                          uv_gid_t gid,
-                          uv_fs_cb cb);
-UV_EXTERN int uv_fs_fchown(uv_loop_t* loop,
-                           uv_fs_t* req,
-                           uv_file file,
-                           uv_uid_t uid,
-                           uv_gid_t gid,
-                           uv_fs_cb cb);
-UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
-                           uv_fs_t* req,
-                           const char* path,
-                           uv_uid_t uid,
-                           uv_gid_t gid,
-                           uv_fs_cb cb);
-
-
-enum uv_fs_event {
-  UV_RENAME = 1,
-  UV_CHANGE = 2
-};
-
-
-struct uv_fs_event_s {
-  UV_HANDLE_FIELDS
-  /* private */
-  char* path;
-  UV_FS_EVENT_PRIVATE_FIELDS
-};
-
-
-/*
- * uv_fs_stat() based polling file watcher.
- */
-struct uv_fs_poll_s {
-  UV_HANDLE_FIELDS
-  /* Private, don't touch. */
-  void* poll_ctx;
-};
-
-UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle);
-UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle,
-                               uv_fs_poll_cb poll_cb,
-                               const char* path,
-                               unsigned int interval);
-UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
-UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle,
-                                 char* buffer,
-                                 size_t* size);
-
-
-struct uv_signal_s {
-  UV_HANDLE_FIELDS
-  uv_signal_cb signal_cb;
-  int signum;
-  UV_SIGNAL_PRIVATE_FIELDS
-};
-
-UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle);
-UV_EXTERN int uv_signal_start(uv_signal_t* handle,
-                              uv_signal_cb signal_cb,
-                              int signum);
-UV_EXTERN int uv_signal_start_oneshot(uv_signal_t* handle,
-                                      uv_signal_cb signal_cb,
-                                      int signum);
-UV_EXTERN int uv_signal_stop(uv_signal_t* handle);
-
-UV_EXTERN void uv_loadavg(double avg[3]);
-
-
-/*
- * Flags to be passed to uv_fs_event_start().
- */
-enum uv_fs_event_flags {
-  /*
-   * By default, if the fs event watcher is given a directory name, we will
-   * watch for all events in that directory. This flags overrides this behavior
-   * and makes fs_event report only changes to the directory entry itself. This
-   * flag does not affect individual files watched.
-   * This flag is currently not implemented yet on any backend.
-   */
-  UV_FS_EVENT_WATCH_ENTRY = 1,
-
-  /*
-   * By default uv_fs_event will try to use a kernel interface such as inotify
-   * or kqueue to detect events. This may not work on remote filesystems such
-   * as NFS mounts. This flag makes fs_event fall back to calling stat() on a
-   * regular interval.
-   * This flag is currently not implemented yet on any backend.
-   */
-  UV_FS_EVENT_STAT = 2,
-
-  /*
-   * By default, event watcher, when watching directory, is not registering
-   * (is ignoring) changes in it's subdirectories.
-   * This flag will override this behaviour on platforms that support it.
-   */
-  UV_FS_EVENT_RECURSIVE = 4
-};
-
-
-UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle);
-UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle,
-                                uv_fs_event_cb cb,
-                                const char* path,
-                                unsigned int flags);
-UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle);
-UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle,
-                                  char* buffer,
-                                  size_t* size);
-
-UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr);
-UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr);
-
-UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size);
-UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size);
-
-UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
-UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
-
-#if defined(IF_NAMESIZE)
-# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)
-#elif defined(IFNAMSIZ)
-# define UV_IF_NAMESIZE (IFNAMSIZ + 1)
-#else
-# define UV_IF_NAMESIZE (16 + 1)
-#endif
-
-UV_EXTERN int uv_if_indextoname(unsigned int ifindex,
-                                char* buffer,
-                                size_t* size);
-UV_EXTERN int uv_if_indextoiid(unsigned int ifindex,
-                               char* buffer,
-                               size_t* size);
-
-UV_EXTERN int uv_exepath(char* buffer, size_t* size);
-
-UV_EXTERN int uv_cwd(char* buffer, size_t* size);
-
-UV_EXTERN int uv_chdir(const char* dir);
-
-UV_EXTERN uint64_t uv_get_free_memory(void);
-UV_EXTERN uint64_t uv_get_total_memory(void);
-UV_EXTERN uint64_t uv_get_constrained_memory(void);
-
-UV_EXTERN uint64_t uv_hrtime(void);
-
-UV_EXTERN void uv_disable_stdio_inheritance(void);
-
-UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib);
-UV_EXTERN void uv_dlclose(uv_lib_t* lib);
-UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr);
-UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib);
-
-UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);
-UV_EXTERN int uv_mutex_init_recursive(uv_mutex_t* handle);
-UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);
-UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle);
-UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle);
-UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle);
-
-UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock);
-UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock);
-UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock);
-UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock);
-UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock);
-UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock);
-UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock);
-UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock);
-
-UV_EXTERN int uv_sem_init(uv_sem_t* sem, unsigned int value);
-UV_EXTERN void uv_sem_destroy(uv_sem_t* sem);
-UV_EXTERN void uv_sem_post(uv_sem_t* sem);
-UV_EXTERN void uv_sem_wait(uv_sem_t* sem);
-UV_EXTERN int uv_sem_trywait(uv_sem_t* sem);
-
-UV_EXTERN int uv_cond_init(uv_cond_t* cond);
-UV_EXTERN void uv_cond_destroy(uv_cond_t* cond);
-UV_EXTERN void uv_cond_signal(uv_cond_t* cond);
-UV_EXTERN void uv_cond_broadcast(uv_cond_t* cond);
-
-UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count);
-UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier);
-UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier);
-
-UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex);
-UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond,
-                                uv_mutex_t* mutex,
-                                uint64_t timeout);
-
-UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void));
-
-UV_EXTERN int uv_key_create(uv_key_t* key);
-UV_EXTERN void uv_key_delete(uv_key_t* key);
-UV_EXTERN void* uv_key_get(uv_key_t* key);
-UV_EXTERN void uv_key_set(uv_key_t* key, void* value);
-
-UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
-
-typedef void (*uv_thread_cb)(void* arg);
-
-UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
-
-typedef enum {
-  UV_THREAD_NO_FLAGS = 0x00,
-  UV_THREAD_HAS_STACK_SIZE = 0x01
-} uv_thread_create_flags;
-
-struct uv_thread_options_s {
-  unsigned int flags;
-  size_t stack_size;
-  /* More fields may be added at any time. */
-};
-
-typedef struct uv_thread_options_s uv_thread_options_t;
-
-UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid,
-                                  const uv_thread_options_t* params,
-                                  uv_thread_cb entry,
-                                  void* arg);
-UV_EXTERN uv_thread_t uv_thread_self(void);
-UV_EXTERN int uv_thread_join(uv_thread_t *tid);
-UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);
-
-/* The presence of these unions force similar struct layout. */
-#define XX(_, name) uv_ ## name ## _t name;
-union uv_any_handle {
-  UV_HANDLE_TYPE_MAP(XX)
-};
-
-union uv_any_req {
-  UV_REQ_TYPE_MAP(XX)
-};
-#undef XX
-
-
-struct uv_loop_s {
-  /* User data - use this for whatever. */
-  void* data;
-  /* Loop reference counting. */
-  unsigned int active_handles;
-  void* handle_queue[2];
-  union {
-    void* unused[2];
-    unsigned int count;
-  } active_reqs;
-  /* Internal flag to signal loop stop. */
-  unsigned int stop_flag;
-  UV_LOOP_PRIVATE_FIELDS
-};
-
-UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
-UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
-
-/* Don't export the private CPP symbols. */
-#undef UV_HANDLE_TYPE_PRIVATE
-#undef UV_REQ_TYPE_PRIVATE
-#undef UV_REQ_PRIVATE_FIELDS
-#undef UV_STREAM_PRIVATE_FIELDS
-#undef UV_TCP_PRIVATE_FIELDS
-#undef UV_PREPARE_PRIVATE_FIELDS
-#undef UV_CHECK_PRIVATE_FIELDS
-#undef UV_IDLE_PRIVATE_FIELDS
-#undef UV_ASYNC_PRIVATE_FIELDS
-#undef UV_TIMER_PRIVATE_FIELDS
-#undef UV_GETADDRINFO_PRIVATE_FIELDS
-#undef UV_GETNAMEINFO_PRIVATE_FIELDS
-#undef UV_FS_REQ_PRIVATE_FIELDS
-#undef UV_WORK_PRIVATE_FIELDS
-#undef UV_FS_EVENT_PRIVATE_FIELDS
-#undef UV_SIGNAL_PRIVATE_FIELDS
-#undef UV_LOOP_PRIVATE_FIELDS
-#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS
-#undef UV__ERR
-
-#endif /* UV_H */
diff --git a/wpiutil/src/main/native/libuv/include/uv/android-ifaddrs.h b/wpiutil/src/main/native/libuv/include/uv/android-ifaddrs.h
deleted file mode 100644
index 9cd19fe..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/android-ifaddrs.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1995, 1999
- *	Berkeley Software Design, Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
- */
-
-#ifndef	_IFADDRS_H_
-#define	_IFADDRS_H_
-
-struct ifaddrs {
-	struct ifaddrs  *ifa_next;
-	char		*ifa_name;
-	unsigned int	 ifa_flags;
-	struct sockaddr	*ifa_addr;
-	struct sockaddr	*ifa_netmask;
-	struct sockaddr	*ifa_dstaddr;
-	void		*ifa_data;
-};
-
-/*
- * This may have been defined in <net/if.h>.  Note that if <net/if.h> is
- * to be included it must be included before this header file.
- */
-#ifndef	ifa_broadaddr
-#define	ifa_broadaddr	ifa_dstaddr	/* broadcast address interface */
-#endif
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-extern int getifaddrs(struct ifaddrs **ifap);
-extern void freeifaddrs(struct ifaddrs *ifa);
-__END_DECLS
-
-#endif
diff --git a/wpiutil/src/main/native/libuv/include/uv/bsd.h b/wpiutil/src/main/native/libuv/include/uv/bsd.h
deleted file mode 100644
index 2d72b3d..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/bsd.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_BSD_H
-#define UV_BSD_H
-
-#define UV_PLATFORM_FS_EVENT_FIELDS                                           \
-  uv__io_t event_watcher;                                                     \
-
-#define UV_IO_PRIVATE_PLATFORM_FIELDS                                         \
-  int rcount;                                                                 \
-  int wcount;                                                                 \
-
-#define UV_HAVE_KQUEUE 1
-
-#endif /* UV_BSD_H */
diff --git a/wpiutil/src/main/native/libuv/include/uv/darwin.h b/wpiutil/src/main/native/libuv/include/uv/darwin.h
deleted file mode 100644
index d226415..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/darwin.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_DARWIN_H
-#define UV_DARWIN_H
-
-#if defined(__APPLE__) && defined(__MACH__)
-# include <mach/mach.h>
-# include <mach/task.h>
-# include <mach/semaphore.h>
-# include <TargetConditionals.h>
-# define UV_PLATFORM_SEM_T semaphore_t
-#endif
-
-#define UV_IO_PRIVATE_PLATFORM_FIELDS                                         \
-  int rcount;                                                                 \
-  int wcount;                                                                 \
-
-#define UV_PLATFORM_LOOP_FIELDS                                               \
-  uv_thread_t cf_thread;                                                      \
-  void* _cf_reserved;                                                         \
-  void* cf_state;                                                             \
-  uv_mutex_t cf_mutex;                                                        \
-  uv_sem_t cf_sem;                                                            \
-  void* cf_signals[2];                                                        \
-
-#define UV_PLATFORM_FS_EVENT_FIELDS                                           \
-  uv__io_t event_watcher;                                                     \
-  char* realpath;                                                             \
-  int realpath_len;                                                           \
-  int cf_flags;                                                               \
-  uv_async_t* cf_cb;                                                          \
-  void* cf_events[2];                                                         \
-  void* cf_member[2];                                                         \
-  int cf_error;                                                               \
-  uv_mutex_t cf_mutex;                                                        \
-
-#define UV_STREAM_PRIVATE_PLATFORM_FIELDS                                     \
-  void* select;                                                               \
-
-#define UV_HAVE_KQUEUE 1
-
-#endif /* UV_DARWIN_H */
diff --git a/wpiutil/src/main/native/libuv/include/uv/errno.h b/wpiutil/src/main/native/libuv/include/uv/errno.h
deleted file mode 100644
index 8eeb95d..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/errno.h
+++ /dev/null
@@ -1,443 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_ERRNO_H_
-#define UV_ERRNO_H_
-
-#include <errno.h>
-#if EDOM > 0
-# define UV__ERR(x) (-(x))
-#else
-# define UV__ERR(x) (x)
-#endif
-
-#define UV__EOF     (-4095)
-#define UV__UNKNOWN (-4094)
-
-#define UV__EAI_ADDRFAMILY  (-3000)
-#define UV__EAI_AGAIN       (-3001)
-#define UV__EAI_BADFLAGS    (-3002)
-#define UV__EAI_CANCELED    (-3003)
-#define UV__EAI_FAIL        (-3004)
-#define UV__EAI_FAMILY      (-3005)
-#define UV__EAI_MEMORY      (-3006)
-#define UV__EAI_NODATA      (-3007)
-#define UV__EAI_NONAME      (-3008)
-#define UV__EAI_OVERFLOW    (-3009)
-#define UV__EAI_SERVICE     (-3010)
-#define UV__EAI_SOCKTYPE    (-3011)
-#define UV__EAI_BADHINTS    (-3013)
-#define UV__EAI_PROTOCOL    (-3014)
-
-/* Only map to the system errno on non-Windows platforms. It's apparently
- * a fairly common practice for Windows programmers to redefine errno codes.
- */
-#if defined(E2BIG) && !defined(_WIN32)
-# define UV__E2BIG UV__ERR(E2BIG)
-#else
-# define UV__E2BIG (-4093)
-#endif
-
-#if defined(EACCES) && !defined(_WIN32)
-# define UV__EACCES UV__ERR(EACCES)
-#else
-# define UV__EACCES (-4092)
-#endif
-
-#if defined(EADDRINUSE) && !defined(_WIN32)
-# define UV__EADDRINUSE UV__ERR(EADDRINUSE)
-#else
-# define UV__EADDRINUSE (-4091)
-#endif
-
-#if defined(EADDRNOTAVAIL) && !defined(_WIN32)
-# define UV__EADDRNOTAVAIL UV__ERR(EADDRNOTAVAIL)
-#else
-# define UV__EADDRNOTAVAIL (-4090)
-#endif
-
-#if defined(EAFNOSUPPORT) && !defined(_WIN32)
-# define UV__EAFNOSUPPORT UV__ERR(EAFNOSUPPORT)
-#else
-# define UV__EAFNOSUPPORT (-4089)
-#endif
-
-#if defined(EAGAIN) && !defined(_WIN32)
-# define UV__EAGAIN UV__ERR(EAGAIN)
-#else
-# define UV__EAGAIN (-4088)
-#endif
-
-#if defined(EALREADY) && !defined(_WIN32)
-# define UV__EALREADY UV__ERR(EALREADY)
-#else
-# define UV__EALREADY (-4084)
-#endif
-
-#if defined(EBADF) && !defined(_WIN32)
-# define UV__EBADF UV__ERR(EBADF)
-#else
-# define UV__EBADF (-4083)
-#endif
-
-#if defined(EBUSY) && !defined(_WIN32)
-# define UV__EBUSY UV__ERR(EBUSY)
-#else
-# define UV__EBUSY (-4082)
-#endif
-
-#if defined(ECANCELED) && !defined(_WIN32)
-# define UV__ECANCELED UV__ERR(ECANCELED)
-#else
-# define UV__ECANCELED (-4081)
-#endif
-
-#if defined(ECHARSET) && !defined(_WIN32)
-# define UV__ECHARSET UV__ERR(ECHARSET)
-#else
-# define UV__ECHARSET (-4080)
-#endif
-
-#if defined(ECONNABORTED) && !defined(_WIN32)
-# define UV__ECONNABORTED UV__ERR(ECONNABORTED)
-#else
-# define UV__ECONNABORTED (-4079)
-#endif
-
-#if defined(ECONNREFUSED) && !defined(_WIN32)
-# define UV__ECONNREFUSED UV__ERR(ECONNREFUSED)
-#else
-# define UV__ECONNREFUSED (-4078)
-#endif
-
-#if defined(ECONNRESET) && !defined(_WIN32)
-# define UV__ECONNRESET UV__ERR(ECONNRESET)
-#else
-# define UV__ECONNRESET (-4077)
-#endif
-
-#if defined(EDESTADDRREQ) && !defined(_WIN32)
-# define UV__EDESTADDRREQ UV__ERR(EDESTADDRREQ)
-#else
-# define UV__EDESTADDRREQ (-4076)
-#endif
-
-#if defined(EEXIST) && !defined(_WIN32)
-# define UV__EEXIST UV__ERR(EEXIST)
-#else
-# define UV__EEXIST (-4075)
-#endif
-
-#if defined(EFAULT) && !defined(_WIN32)
-# define UV__EFAULT UV__ERR(EFAULT)
-#else
-# define UV__EFAULT (-4074)
-#endif
-
-#if defined(EHOSTUNREACH) && !defined(_WIN32)
-# define UV__EHOSTUNREACH UV__ERR(EHOSTUNREACH)
-#else
-# define UV__EHOSTUNREACH (-4073)
-#endif
-
-#if defined(EINTR) && !defined(_WIN32)
-# define UV__EINTR UV__ERR(EINTR)
-#else
-# define UV__EINTR (-4072)
-#endif
-
-#if defined(EINVAL) && !defined(_WIN32)
-# define UV__EINVAL UV__ERR(EINVAL)
-#else
-# define UV__EINVAL (-4071)
-#endif
-
-#if defined(EIO) && !defined(_WIN32)
-# define UV__EIO UV__ERR(EIO)
-#else
-# define UV__EIO (-4070)
-#endif
-
-#if defined(EISCONN) && !defined(_WIN32)
-# define UV__EISCONN UV__ERR(EISCONN)
-#else
-# define UV__EISCONN (-4069)
-#endif
-
-#if defined(EISDIR) && !defined(_WIN32)
-# define UV__EISDIR UV__ERR(EISDIR)
-#else
-# define UV__EISDIR (-4068)
-#endif
-
-#if defined(ELOOP) && !defined(_WIN32)
-# define UV__ELOOP UV__ERR(ELOOP)
-#else
-# define UV__ELOOP (-4067)
-#endif
-
-#if defined(EMFILE) && !defined(_WIN32)
-# define UV__EMFILE UV__ERR(EMFILE)
-#else
-# define UV__EMFILE (-4066)
-#endif
-
-#if defined(EMSGSIZE) && !defined(_WIN32)
-# define UV__EMSGSIZE UV__ERR(EMSGSIZE)
-#else
-# define UV__EMSGSIZE (-4065)
-#endif
-
-#if defined(ENAMETOOLONG) && !defined(_WIN32)
-# define UV__ENAMETOOLONG UV__ERR(ENAMETOOLONG)
-#else
-# define UV__ENAMETOOLONG (-4064)
-#endif
-
-#if defined(ENETDOWN) && !defined(_WIN32)
-# define UV__ENETDOWN UV__ERR(ENETDOWN)
-#else
-# define UV__ENETDOWN (-4063)
-#endif
-
-#if defined(ENETUNREACH) && !defined(_WIN32)
-# define UV__ENETUNREACH UV__ERR(ENETUNREACH)
-#else
-# define UV__ENETUNREACH (-4062)
-#endif
-
-#if defined(ENFILE) && !defined(_WIN32)
-# define UV__ENFILE UV__ERR(ENFILE)
-#else
-# define UV__ENFILE (-4061)
-#endif
-
-#if defined(ENOBUFS) && !defined(_WIN32)
-# define UV__ENOBUFS UV__ERR(ENOBUFS)
-#else
-# define UV__ENOBUFS (-4060)
-#endif
-
-#if defined(ENODEV) && !defined(_WIN32)
-# define UV__ENODEV UV__ERR(ENODEV)
-#else
-# define UV__ENODEV (-4059)
-#endif
-
-#if defined(ENOENT) && !defined(_WIN32)
-# define UV__ENOENT UV__ERR(ENOENT)
-#else
-# define UV__ENOENT (-4058)
-#endif
-
-#if defined(ENOMEM) && !defined(_WIN32)
-# define UV__ENOMEM UV__ERR(ENOMEM)
-#else
-# define UV__ENOMEM (-4057)
-#endif
-
-#if defined(ENONET) && !defined(_WIN32)
-# define UV__ENONET UV__ERR(ENONET)
-#else
-# define UV__ENONET (-4056)
-#endif
-
-#if defined(ENOSPC) && !defined(_WIN32)
-# define UV__ENOSPC UV__ERR(ENOSPC)
-#else
-# define UV__ENOSPC (-4055)
-#endif
-
-#if defined(ENOSYS) && !defined(_WIN32)
-# define UV__ENOSYS UV__ERR(ENOSYS)
-#else
-# define UV__ENOSYS (-4054)
-#endif
-
-#if defined(ENOTCONN) && !defined(_WIN32)
-# define UV__ENOTCONN UV__ERR(ENOTCONN)
-#else
-# define UV__ENOTCONN (-4053)
-#endif
-
-#if defined(ENOTDIR) && !defined(_WIN32)
-# define UV__ENOTDIR UV__ERR(ENOTDIR)
-#else
-# define UV__ENOTDIR (-4052)
-#endif
-
-#if defined(ENOTEMPTY) && !defined(_WIN32)
-# define UV__ENOTEMPTY UV__ERR(ENOTEMPTY)
-#else
-# define UV__ENOTEMPTY (-4051)
-#endif
-
-#if defined(ENOTSOCK) && !defined(_WIN32)
-# define UV__ENOTSOCK UV__ERR(ENOTSOCK)
-#else
-# define UV__ENOTSOCK (-4050)
-#endif
-
-#if defined(ENOTSUP) && !defined(_WIN32)
-# define UV__ENOTSUP UV__ERR(ENOTSUP)
-#else
-# define UV__ENOTSUP (-4049)
-#endif
-
-#if defined(EPERM) && !defined(_WIN32)
-# define UV__EPERM UV__ERR(EPERM)
-#else
-# define UV__EPERM (-4048)
-#endif
-
-#if defined(EPIPE) && !defined(_WIN32)
-# define UV__EPIPE UV__ERR(EPIPE)
-#else
-# define UV__EPIPE (-4047)
-#endif
-
-#if defined(EPROTO) && !defined(_WIN32)
-# define UV__EPROTO UV__ERR(EPROTO)
-#else
-# define UV__EPROTO UV__ERR(4046)
-#endif
-
-#if defined(EPROTONOSUPPORT) && !defined(_WIN32)
-# define UV__EPROTONOSUPPORT UV__ERR(EPROTONOSUPPORT)
-#else
-# define UV__EPROTONOSUPPORT (-4045)
-#endif
-
-#if defined(EPROTOTYPE) && !defined(_WIN32)
-# define UV__EPROTOTYPE UV__ERR(EPROTOTYPE)
-#else
-# define UV__EPROTOTYPE (-4044)
-#endif
-
-#if defined(EROFS) && !defined(_WIN32)
-# define UV__EROFS UV__ERR(EROFS)
-#else
-# define UV__EROFS (-4043)
-#endif
-
-#if defined(ESHUTDOWN) && !defined(_WIN32)
-# define UV__ESHUTDOWN UV__ERR(ESHUTDOWN)
-#else
-# define UV__ESHUTDOWN (-4042)
-#endif
-
-#if defined(ESPIPE) && !defined(_WIN32)
-# define UV__ESPIPE UV__ERR(ESPIPE)
-#else
-# define UV__ESPIPE (-4041)
-#endif
-
-#if defined(ESRCH) && !defined(_WIN32)
-# define UV__ESRCH UV__ERR(ESRCH)
-#else
-# define UV__ESRCH (-4040)
-#endif
-
-#if defined(ETIMEDOUT) && !defined(_WIN32)
-# define UV__ETIMEDOUT UV__ERR(ETIMEDOUT)
-#else
-# define UV__ETIMEDOUT (-4039)
-#endif
-
-#if defined(ETXTBSY) && !defined(_WIN32)
-# define UV__ETXTBSY UV__ERR(ETXTBSY)
-#else
-# define UV__ETXTBSY (-4038)
-#endif
-
-#if defined(EXDEV) && !defined(_WIN32)
-# define UV__EXDEV UV__ERR(EXDEV)
-#else
-# define UV__EXDEV (-4037)
-#endif
-
-#if defined(EFBIG) && !defined(_WIN32)
-# define UV__EFBIG UV__ERR(EFBIG)
-#else
-# define UV__EFBIG (-4036)
-#endif
-
-#if defined(ENOPROTOOPT) && !defined(_WIN32)
-# define UV__ENOPROTOOPT UV__ERR(ENOPROTOOPT)
-#else
-# define UV__ENOPROTOOPT (-4035)
-#endif
-
-#if defined(ERANGE) && !defined(_WIN32)
-# define UV__ERANGE UV__ERR(ERANGE)
-#else
-# define UV__ERANGE (-4034)
-#endif
-
-#if defined(ENXIO) && !defined(_WIN32)
-# define UV__ENXIO UV__ERR(ENXIO)
-#else
-# define UV__ENXIO (-4033)
-#endif
-
-#if defined(EMLINK) && !defined(_WIN32)
-# define UV__EMLINK UV__ERR(EMLINK)
-#else
-# define UV__EMLINK (-4032)
-#endif
-
-/* EHOSTDOWN is not visible on BSD-like systems when _POSIX_C_SOURCE is
- * defined. Fortunately, its value is always 64 so it's possible albeit
- * icky to hard-code it.
- */
-#if defined(EHOSTDOWN) && !defined(_WIN32)
-# define UV__EHOSTDOWN UV__ERR(EHOSTDOWN)
-#elif defined(__APPLE__) || \
-      defined(__DragonFly__) || \
-      defined(__FreeBSD__) || \
-      defined(__FreeBSD_kernel__) || \
-      defined(__NetBSD__) || \
-      defined(__OpenBSD__)
-# define UV__EHOSTDOWN (-64)
-#else
-# define UV__EHOSTDOWN (-4031)
-#endif
-
-#if defined(EREMOTEIO) && !defined(_WIN32)
-# define UV__EREMOTEIO UV__ERR(EREMOTEIO)
-#else
-# define UV__EREMOTEIO (-4030)
-#endif
-
-#if defined(ENOTTY) && !defined(_WIN32)
-# define UV__ENOTTY UV__ERR(ENOTTY)
-#else
-# define UV__ENOTTY (-4029)
-#endif
-
-#if defined(EFTYPE) && !defined(_WIN32)
-# define UV__EFTYPE UV__ERR(EFTYPE)
-#else
-# define UV__EFTYPE (-4028)
-#endif
-
-
-#endif /* UV_ERRNO_H_ */
diff --git a/wpiutil/src/main/native/libuv/include/uv/linux.h b/wpiutil/src/main/native/libuv/include/uv/linux.h
deleted file mode 100644
index 9b38405..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/linux.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_LINUX_H
-#define UV_LINUX_H
-
-#define UV_PLATFORM_LOOP_FIELDS                                               \
-  uv__io_t inotify_read_watcher;                                              \
-  void* inotify_watchers;                                                     \
-  int inotify_fd;                                                             \
-
-#define UV_PLATFORM_FS_EVENT_FIELDS                                           \
-  void* watchers[2];                                                          \
-  int wd;                                                                     \
-
-#endif /* UV_LINUX_H */
diff --git a/wpiutil/src/main/native/libuv/include/uv/posix.h b/wpiutil/src/main/native/libuv/include/uv/posix.h
deleted file mode 100644
index 9a96634..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/posix.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_POSIX_H
-#define UV_POSIX_H
-
-#define UV_PLATFORM_LOOP_FIELDS                                               \
-  struct pollfd* poll_fds;                                                    \
-  size_t poll_fds_used;                                                       \
-  size_t poll_fds_size;                                                       \
-  unsigned char poll_fds_iterating;                                           \
-
-#endif /* UV_POSIX_H */
diff --git a/wpiutil/src/main/native/libuv/include/uv/threadpool.h b/wpiutil/src/main/native/libuv/include/uv/threadpool.h
deleted file mode 100644
index 9708ebd..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/threadpool.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/*
- * This file is private to libuv. It provides common functionality to both
- * Windows and Unix backends.
- */
-
-#ifndef UV_THREADPOOL_H_
-#define UV_THREADPOOL_H_
-
-struct uv__work {
-  void (*work)(struct uv__work *w);
-  void (*done)(struct uv__work *w, int status);
-  struct uv_loop_s* loop;
-  void* wq[2];
-};
-
-#endif /* UV_THREADPOOL_H_ */
diff --git a/wpiutil/src/main/native/libuv/include/uv/tree.h b/wpiutil/src/main/native/libuv/include/uv/tree.h
deleted file mode 100644
index f936416..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/tree.h
+++ /dev/null
@@ -1,768 +0,0 @@
-/*-
- * Copyright 2002 Niels Provos <provos@citi.umich.edu>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef  UV_TREE_H_
-#define  UV_TREE_H_
-
-#ifndef UV__UNUSED
-# if __GNUC__
-#  define UV__UNUSED __attribute__((unused))
-# else
-#  define UV__UNUSED
-# endif
-#endif
-
-/*
- * This file defines data structures for different types of trees:
- * splay trees and red-black trees.
- *
- * A splay tree is a self-organizing data structure.  Every operation
- * on the tree causes a splay to happen.  The splay moves the requested
- * node to the root of the tree and partly rebalances it.
- *
- * This has the benefit that request locality causes faster lookups as
- * the requested nodes move to the top of the tree.  On the other hand,
- * every lookup causes memory writes.
- *
- * The Balance Theorem bounds the total access time for m operations
- * and n inserts on an initially empty tree as O((m + n)lg n).  The
- * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
- *
- * A red-black tree is a binary search tree with the node color as an
- * extra attribute.  It fulfills a set of conditions:
- *  - every search path from the root to a leaf consists of the
- *    same number of black nodes,
- *  - each red node (except for the root) has a black parent,
- *  - each leaf node is black.
- *
- * Every operation on a red-black tree is bounded as O(lg n).
- * The maximum height of a red-black tree is 2lg (n+1).
- */
-
-#define SPLAY_HEAD(name, type)                                                \
-struct name {                                                                 \
-  struct type *sph_root; /* root of the tree */                               \
-}
-
-#define SPLAY_INITIALIZER(root)                                               \
-  { NULL }
-
-#define SPLAY_INIT(root) do {                                                 \
-  (root)->sph_root = NULL;                                                    \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_ENTRY(type)                                                     \
-struct {                                                                      \
-  struct type *spe_left;          /* left element */                          \
-  struct type *spe_right;         /* right element */                         \
-}
-
-#define SPLAY_LEFT(elm, field)    (elm)->field.spe_left
-#define SPLAY_RIGHT(elm, field)   (elm)->field.spe_right
-#define SPLAY_ROOT(head)          (head)->sph_root
-#define SPLAY_EMPTY(head)         (SPLAY_ROOT(head) == NULL)
-
-/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
-#define SPLAY_ROTATE_RIGHT(head, tmp, field) do {                             \
-  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);              \
-  SPLAY_RIGHT(tmp, field) = (head)->sph_root;                                 \
-  (head)->sph_root = tmp;                                                     \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_ROTATE_LEFT(head, tmp, field) do {                              \
-  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);              \
-  SPLAY_LEFT(tmp, field) = (head)->sph_root;                                  \
-  (head)->sph_root = tmp;                                                     \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_LINKLEFT(head, tmp, field) do {                                 \
-  SPLAY_LEFT(tmp, field) = (head)->sph_root;                                  \
-  tmp = (head)->sph_root;                                                     \
-  (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);                     \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_LINKRIGHT(head, tmp, field) do {                                \
-  SPLAY_RIGHT(tmp, field) = (head)->sph_root;                                 \
-  tmp = (head)->sph_root;                                                     \
-  (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);                    \
-} while (/*CONSTCOND*/ 0)
-
-#define SPLAY_ASSEMBLE(head, node, left, right, field) do {                   \
-  SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field);             \
-  SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);            \
-  SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field);             \
-  SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field);             \
-} while (/*CONSTCOND*/ 0)
-
-/* Generates prototypes and inline functions */
-
-#define SPLAY_PROTOTYPE(name, type, field, cmp)                               \
-void name##_SPLAY(struct name *, struct type *);                              \
-void name##_SPLAY_MINMAX(struct name *, int);                                 \
-struct type *name##_SPLAY_INSERT(struct name *, struct type *);               \
-struct type *name##_SPLAY_REMOVE(struct name *, struct type *);               \
-                                                                              \
-/* Finds the node with the same key as elm */                                 \
-static __inline struct type *                                                 \
-name##_SPLAY_FIND(struct name *head, struct type *elm)                        \
-{                                                                             \
-  if (SPLAY_EMPTY(head))                                                      \
-    return(NULL);                                                             \
-  name##_SPLAY(head, elm);                                                    \
-  if ((cmp)(elm, (head)->sph_root) == 0)                                      \
-    return (head->sph_root);                                                  \
-  return (NULL);                                                              \
-}                                                                             \
-                                                                              \
-static __inline struct type *                                                 \
-name##_SPLAY_NEXT(struct name *head, struct type *elm)                        \
-{                                                                             \
-  name##_SPLAY(head, elm);                                                    \
-  if (SPLAY_RIGHT(elm, field) != NULL) {                                      \
-    elm = SPLAY_RIGHT(elm, field);                                            \
-    while (SPLAY_LEFT(elm, field) != NULL) {                                  \
-      elm = SPLAY_LEFT(elm, field);                                           \
-    }                                                                         \
-  } else                                                                      \
-    elm = NULL;                                                               \
-  return (elm);                                                               \
-}                                                                             \
-                                                                              \
-static __inline struct type *                                                 \
-name##_SPLAY_MIN_MAX(struct name *head, int val)                              \
-{                                                                             \
-  name##_SPLAY_MINMAX(head, val);                                             \
-  return (SPLAY_ROOT(head));                                                  \
-}
-
-/* Main splay operation.
- * Moves node close to the key of elm to top
- */
-#define SPLAY_GENERATE(name, type, field, cmp)                                \
-struct type *                                                                 \
-name##_SPLAY_INSERT(struct name *head, struct type *elm)                      \
-{                                                                             \
-    if (SPLAY_EMPTY(head)) {                                                  \
-      SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;                \
-    } else {                                                                  \
-      int __comp;                                                             \
-      name##_SPLAY(head, elm);                                                \
-      __comp = (cmp)(elm, (head)->sph_root);                                  \
-      if(__comp < 0) {                                                        \
-        SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);         \
-        SPLAY_RIGHT(elm, field) = (head)->sph_root;                           \
-        SPLAY_LEFT((head)->sph_root, field) = NULL;                           \
-      } else if (__comp > 0) {                                                \
-        SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);       \
-        SPLAY_LEFT(elm, field) = (head)->sph_root;                            \
-        SPLAY_RIGHT((head)->sph_root, field) = NULL;                          \
-      } else                                                                  \
-        return ((head)->sph_root);                                            \
-    }                                                                         \
-    (head)->sph_root = (elm);                                                 \
-    return (NULL);                                                            \
-}                                                                             \
-                                                                              \
-struct type *                                                                 \
-name##_SPLAY_REMOVE(struct name *head, struct type *elm)                      \
-{                                                                             \
-  struct type *__tmp;                                                         \
-  if (SPLAY_EMPTY(head))                                                      \
-    return (NULL);                                                            \
-  name##_SPLAY(head, elm);                                                    \
-  if ((cmp)(elm, (head)->sph_root) == 0) {                                    \
-    if (SPLAY_LEFT((head)->sph_root, field) == NULL) {                        \
-      (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);                \
-    } else {                                                                  \
-      __tmp = SPLAY_RIGHT((head)->sph_root, field);                           \
-      (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);                 \
-      name##_SPLAY(head, elm);                                                \
-      SPLAY_RIGHT((head)->sph_root, field) = __tmp;                           \
-    }                                                                         \
-    return (elm);                                                             \
-  }                                                                           \
-  return (NULL);                                                              \
-}                                                                             \
-                                                                              \
-void                                                                          \
-name##_SPLAY(struct name *head, struct type *elm)                             \
-{                                                                             \
-  struct type __node, *__left, *__right, *__tmp;                              \
-  int __comp;                                                                 \
-                                                                              \
-  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;            \
-  __left = __right = &__node;                                                 \
-                                                                              \
-  while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) {                      \
-    if (__comp < 0) {                                                         \
-      __tmp = SPLAY_LEFT((head)->sph_root, field);                            \
-      if (__tmp == NULL)                                                      \
-        break;                                                                \
-      if ((cmp)(elm, __tmp) < 0){                                             \
-        SPLAY_ROTATE_RIGHT(head, __tmp, field);                               \
-        if (SPLAY_LEFT((head)->sph_root, field) == NULL)                      \
-          break;                                                              \
-      }                                                                       \
-      SPLAY_LINKLEFT(head, __right, field);                                   \
-    } else if (__comp > 0) {                                                  \
-      __tmp = SPLAY_RIGHT((head)->sph_root, field);                           \
-      if (__tmp == NULL)                                                      \
-        break;                                                                \
-      if ((cmp)(elm, __tmp) > 0){                                             \
-        SPLAY_ROTATE_LEFT(head, __tmp, field);                                \
-        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)                     \
-          break;                                                              \
-      }                                                                       \
-      SPLAY_LINKRIGHT(head, __left, field);                                   \
-    }                                                                         \
-  }                                                                           \
-  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);                      \
-}                                                                             \
-                                                                              \
-/* Splay with either the minimum or the maximum element                       \
- * Used to find minimum or maximum element in tree.                           \
- */                                                                           \
-void name##_SPLAY_MINMAX(struct name *head, int __comp)                       \
-{                                                                             \
-  struct type __node, *__left, *__right, *__tmp;                              \
-                                                                              \
-  SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;            \
-  __left = __right = &__node;                                                 \
-                                                                              \
-  while (1) {                                                                 \
-    if (__comp < 0) {                                                         \
-      __tmp = SPLAY_LEFT((head)->sph_root, field);                            \
-      if (__tmp == NULL)                                                      \
-        break;                                                                \
-      if (__comp < 0){                                                        \
-        SPLAY_ROTATE_RIGHT(head, __tmp, field);                               \
-        if (SPLAY_LEFT((head)->sph_root, field) == NULL)                      \
-          break;                                                              \
-      }                                                                       \
-      SPLAY_LINKLEFT(head, __right, field);                                   \
-    } else if (__comp > 0) {                                                  \
-      __tmp = SPLAY_RIGHT((head)->sph_root, field);                           \
-      if (__tmp == NULL)                                                      \
-        break;                                                                \
-      if (__comp > 0) {                                                       \
-        SPLAY_ROTATE_LEFT(head, __tmp, field);                                \
-        if (SPLAY_RIGHT((head)->sph_root, field) == NULL)                     \
-          break;                                                              \
-      }                                                                       \
-      SPLAY_LINKRIGHT(head, __left, field);                                   \
-    }                                                                         \
-  }                                                                           \
-  SPLAY_ASSEMBLE(head, &__node, __left, __right, field);                      \
-}
-
-#define SPLAY_NEGINF  -1
-#define SPLAY_INF     1
-
-#define SPLAY_INSERT(name, x, y)  name##_SPLAY_INSERT(x, y)
-#define SPLAY_REMOVE(name, x, y)  name##_SPLAY_REMOVE(x, y)
-#define SPLAY_FIND(name, x, y)    name##_SPLAY_FIND(x, y)
-#define SPLAY_NEXT(name, x, y)    name##_SPLAY_NEXT(x, y)
-#define SPLAY_MIN(name, x)        (SPLAY_EMPTY(x) ? NULL                      \
-                                  : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
-#define SPLAY_MAX(name, x)        (SPLAY_EMPTY(x) ? NULL                      \
-                                  : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
-
-#define SPLAY_FOREACH(x, name, head)                                          \
-  for ((x) = SPLAY_MIN(name, head);                                           \
-       (x) != NULL;                                                           \
-       (x) = SPLAY_NEXT(name, head, x))
-
-/* Macros that define a red-black tree */
-#define RB_HEAD(name, type)                                                   \
-struct name {                                                                 \
-  struct type *rbh_root; /* root of the tree */                               \
-}
-
-#define RB_INITIALIZER(root)                                                  \
-  { NULL }
-
-#define RB_INIT(root) do {                                                    \
-  (root)->rbh_root = NULL;                                                    \
-} while (/*CONSTCOND*/ 0)
-
-#define RB_BLACK  0
-#define RB_RED    1
-#define RB_ENTRY(type)                                                        \
-struct {                                                                      \
-  struct type *rbe_left;        /* left element */                            \
-  struct type *rbe_right;       /* right element */                           \
-  struct type *rbe_parent;      /* parent element */                          \
-  int rbe_color;                /* node color */                              \
-}
-
-#define RB_LEFT(elm, field)     (elm)->field.rbe_left
-#define RB_RIGHT(elm, field)    (elm)->field.rbe_right
-#define RB_PARENT(elm, field)   (elm)->field.rbe_parent
-#define RB_COLOR(elm, field)    (elm)->field.rbe_color
-#define RB_ROOT(head)           (head)->rbh_root
-#define RB_EMPTY(head)          (RB_ROOT(head) == NULL)
-
-#define RB_SET(elm, parent, field) do {                                       \
-  RB_PARENT(elm, field) = parent;                                             \
-  RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;                          \
-  RB_COLOR(elm, field) = RB_RED;                                              \
-} while (/*CONSTCOND*/ 0)
-
-#define RB_SET_BLACKRED(black, red, field) do {                               \
-  RB_COLOR(black, field) = RB_BLACK;                                          \
-  RB_COLOR(red, field) = RB_RED;                                              \
-} while (/*CONSTCOND*/ 0)
-
-#ifndef RB_AUGMENT
-#define RB_AUGMENT(x)  do {} while (0)
-#endif
-
-#define RB_ROTATE_LEFT(head, elm, tmp, field) do {                            \
-  (tmp) = RB_RIGHT(elm, field);                                               \
-  if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) {                 \
-    RB_PARENT(RB_LEFT(tmp, field), field) = (elm);                            \
-  }                                                                           \
-  RB_AUGMENT(elm);                                                            \
-  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) {              \
-    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))                       \
-      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);                          \
-    else                                                                      \
-      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp);                         \
-  } else                                                                      \
-    (head)->rbh_root = (tmp);                                                 \
-  RB_LEFT(tmp, field) = (elm);                                                \
-  RB_PARENT(elm, field) = (tmp);                                              \
-  RB_AUGMENT(tmp);                                                            \
-  if ((RB_PARENT(tmp, field)))                                                \
-    RB_AUGMENT(RB_PARENT(tmp, field));                                        \
-} while (/*CONSTCOND*/ 0)
-
-#define RB_ROTATE_RIGHT(head, elm, tmp, field) do {                           \
-  (tmp) = RB_LEFT(elm, field);                                                \
-  if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) {                 \
-    RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);                           \
-  }                                                                           \
-  RB_AUGMENT(elm);                                                            \
-  if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) {              \
-    if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))                       \
-      RB_LEFT(RB_PARENT(elm, field), field) = (tmp);                          \
-    else                                                                      \
-      RB_RIGHT(RB_PARENT(elm, field), field) = (tmp);                         \
-  } else                                                                      \
-    (head)->rbh_root = (tmp);                                                 \
-  RB_RIGHT(tmp, field) = (elm);                                               \
-  RB_PARENT(elm, field) = (tmp);                                              \
-  RB_AUGMENT(tmp);                                                            \
-  if ((RB_PARENT(tmp, field)))                                                \
-    RB_AUGMENT(RB_PARENT(tmp, field));                                        \
-} while (/*CONSTCOND*/ 0)
-
-/* Generates prototypes and inline functions */
-#define  RB_PROTOTYPE(name, type, field, cmp)                                 \
-  RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
-#define  RB_PROTOTYPE_STATIC(name, type, field, cmp)                          \
-  RB_PROTOTYPE_INTERNAL(name, type, field, cmp, UV__UNUSED static)
-#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr)                   \
-attr void name##_RB_INSERT_COLOR(struct name *, struct type *);               \
-attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
-attr struct type *name##_RB_REMOVE(struct name *, struct type *);             \
-attr struct type *name##_RB_INSERT(struct name *, struct type *);             \
-attr struct type *name##_RB_FIND(struct name *, struct type *);               \
-attr struct type *name##_RB_NFIND(struct name *, struct type *);              \
-attr struct type *name##_RB_NEXT(struct type *);                              \
-attr struct type *name##_RB_PREV(struct type *);                              \
-attr struct type *name##_RB_MINMAX(struct name *, int);                       \
-                                                                              \
-
-/* Main rb operation.
- * Moves node close to the key of elm to top
- */
-#define  RB_GENERATE(name, type, field, cmp)                                  \
-  RB_GENERATE_INTERNAL(name, type, field, cmp,)
-#define  RB_GENERATE_STATIC(name, type, field, cmp)                           \
-  RB_GENERATE_INTERNAL(name, type, field, cmp, UV__UNUSED static)
-#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr)                    \
-attr void                                                                     \
-name##_RB_INSERT_COLOR(struct name *head, struct type *elm)                   \
-{                                                                             \
-  struct type *parent, *gparent, *tmp;                                        \
-  while ((parent = RB_PARENT(elm, field)) != NULL &&                          \
-      RB_COLOR(parent, field) == RB_RED) {                                    \
-    gparent = RB_PARENT(parent, field);                                       \
-    if (parent == RB_LEFT(gparent, field)) {                                  \
-      tmp = RB_RIGHT(gparent, field);                                         \
-      if (tmp && RB_COLOR(tmp, field) == RB_RED) {                            \
-        RB_COLOR(tmp, field) = RB_BLACK;                                      \
-        RB_SET_BLACKRED(parent, gparent, field);                              \
-        elm = gparent;                                                        \
-        continue;                                                             \
-      }                                                                       \
-      if (RB_RIGHT(parent, field) == elm) {                                   \
-        RB_ROTATE_LEFT(head, parent, tmp, field);                             \
-        tmp = parent;                                                         \
-        parent = elm;                                                         \
-        elm = tmp;                                                            \
-      }                                                                       \
-      RB_SET_BLACKRED(parent, gparent, field);                                \
-      RB_ROTATE_RIGHT(head, gparent, tmp, field);                             \
-    } else {                                                                  \
-      tmp = RB_LEFT(gparent, field);                                          \
-      if (tmp && RB_COLOR(tmp, field) == RB_RED) {                            \
-        RB_COLOR(tmp, field) = RB_BLACK;                                      \
-        RB_SET_BLACKRED(parent, gparent, field);                              \
-        elm = gparent;                                                        \
-        continue;                                                             \
-      }                                                                       \
-      if (RB_LEFT(parent, field) == elm) {                                    \
-        RB_ROTATE_RIGHT(head, parent, tmp, field);                            \
-        tmp = parent;                                                         \
-        parent = elm;                                                         \
-        elm = tmp;                                                            \
-      }                                                                       \
-      RB_SET_BLACKRED(parent, gparent, field);                                \
-      RB_ROTATE_LEFT(head, gparent, tmp, field);                              \
-    }                                                                         \
-  }                                                                           \
-  RB_COLOR(head->rbh_root, field) = RB_BLACK;                                 \
-}                                                                             \
-                                                                              \
-attr void                                                                     \
-name##_RB_REMOVE_COLOR(struct name *head, struct type *parent,                \
-    struct type *elm)                                                         \
-{                                                                             \
-  struct type *tmp;                                                           \
-  while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) &&                 \
-      elm != RB_ROOT(head)) {                                                 \
-    if (RB_LEFT(parent, field) == elm) {                                      \
-      tmp = RB_RIGHT(parent, field);                                          \
-      if (RB_COLOR(tmp, field) == RB_RED) {                                   \
-        RB_SET_BLACKRED(tmp, parent, field);                                  \
-        RB_ROTATE_LEFT(head, parent, tmp, field);                             \
-        tmp = RB_RIGHT(parent, field);                                        \
-      }                                                                       \
-      if ((RB_LEFT(tmp, field) == NULL ||                                     \
-          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&                \
-          (RB_RIGHT(tmp, field) == NULL ||                                    \
-          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {               \
-        RB_COLOR(tmp, field) = RB_RED;                                        \
-        elm = parent;                                                         \
-        parent = RB_PARENT(elm, field);                                       \
-      } else {                                                                \
-        if (RB_RIGHT(tmp, field) == NULL ||                                   \
-            RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {              \
-          struct type *oleft;                                                 \
-          if ((oleft = RB_LEFT(tmp, field))                                   \
-              != NULL)                                                        \
-            RB_COLOR(oleft, field) = RB_BLACK;                                \
-          RB_COLOR(tmp, field) = RB_RED;                                      \
-          RB_ROTATE_RIGHT(head, tmp, oleft, field);                           \
-          tmp = RB_RIGHT(parent, field);                                      \
-        }                                                                     \
-        RB_COLOR(tmp, field) = RB_COLOR(parent, field);                       \
-        RB_COLOR(parent, field) = RB_BLACK;                                   \
-        if (RB_RIGHT(tmp, field))                                             \
-          RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;                   \
-        RB_ROTATE_LEFT(head, parent, tmp, field);                             \
-        elm = RB_ROOT(head);                                                  \
-        break;                                                                \
-      }                                                                       \
-    } else {                                                                  \
-      tmp = RB_LEFT(parent, field);                                           \
-      if (RB_COLOR(tmp, field) == RB_RED) {                                   \
-        RB_SET_BLACKRED(tmp, parent, field);                                  \
-        RB_ROTATE_RIGHT(head, parent, tmp, field);                            \
-        tmp = RB_LEFT(parent, field);                                         \
-      }                                                                       \
-      if ((RB_LEFT(tmp, field) == NULL ||                                     \
-          RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&                \
-          (RB_RIGHT(tmp, field) == NULL ||                                    \
-          RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {               \
-        RB_COLOR(tmp, field) = RB_RED;                                        \
-        elm = parent;                                                         \
-        parent = RB_PARENT(elm, field);                                       \
-      } else {                                                                \
-        if (RB_LEFT(tmp, field) == NULL ||                                    \
-            RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {               \
-          struct type *oright;                                                \
-          if ((oright = RB_RIGHT(tmp, field))                                 \
-              != NULL)                                                        \
-            RB_COLOR(oright, field) = RB_BLACK;                               \
-          RB_COLOR(tmp, field) = RB_RED;                                      \
-          RB_ROTATE_LEFT(head, tmp, oright, field);                           \
-          tmp = RB_LEFT(parent, field);                                       \
-        }                                                                     \
-        RB_COLOR(tmp, field) = RB_COLOR(parent, field);                       \
-        RB_COLOR(parent, field) = RB_BLACK;                                   \
-        if (RB_LEFT(tmp, field))                                              \
-          RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;                    \
-        RB_ROTATE_RIGHT(head, parent, tmp, field);                            \
-        elm = RB_ROOT(head);                                                  \
-        break;                                                                \
-      }                                                                       \
-    }                                                                         \
-  }                                                                           \
-  if (elm)                                                                    \
-    RB_COLOR(elm, field) = RB_BLACK;                                          \
-}                                                                             \
-                                                                              \
-attr struct type *                                                            \
-name##_RB_REMOVE(struct name *head, struct type *elm)                         \
-{                                                                             \
-  struct type *child, *parent, *old = elm;                                    \
-  int color;                                                                  \
-  if (RB_LEFT(elm, field) == NULL)                                            \
-    child = RB_RIGHT(elm, field);                                             \
-  else if (RB_RIGHT(elm, field) == NULL)                                      \
-    child = RB_LEFT(elm, field);                                              \
-  else {                                                                      \
-    struct type *left;                                                        \
-    elm = RB_RIGHT(elm, field);                                               \
-    while ((left = RB_LEFT(elm, field)) != NULL)                              \
-      elm = left;                                                             \
-    child = RB_RIGHT(elm, field);                                             \
-    parent = RB_PARENT(elm, field);                                           \
-    color = RB_COLOR(elm, field);                                             \
-    if (child)                                                                \
-      RB_PARENT(child, field) = parent;                                       \
-    if (parent) {                                                             \
-      if (RB_LEFT(parent, field) == elm)                                      \
-        RB_LEFT(parent, field) = child;                                       \
-      else                                                                    \
-        RB_RIGHT(parent, field) = child;                                      \
-      RB_AUGMENT(parent);                                                     \
-    } else                                                                    \
-      RB_ROOT(head) = child;                                                  \
-    if (RB_PARENT(elm, field) == old)                                         \
-      parent = elm;                                                           \
-    (elm)->field = (old)->field;                                              \
-    if (RB_PARENT(old, field)) {                                              \
-      if (RB_LEFT(RB_PARENT(old, field), field) == old)                       \
-        RB_LEFT(RB_PARENT(old, field), field) = elm;                          \
-      else                                                                    \
-        RB_RIGHT(RB_PARENT(old, field), field) = elm;                         \
-      RB_AUGMENT(RB_PARENT(old, field));                                      \
-    } else                                                                    \
-      RB_ROOT(head) = elm;                                                    \
-    RB_PARENT(RB_LEFT(old, field), field) = elm;                              \
-    if (RB_RIGHT(old, field))                                                 \
-      RB_PARENT(RB_RIGHT(old, field), field) = elm;                           \
-    if (parent) {                                                             \
-      left = parent;                                                          \
-      do {                                                                    \
-        RB_AUGMENT(left);                                                     \
-      } while ((left = RB_PARENT(left, field)) != NULL);                      \
-    }                                                                         \
-    goto color;                                                               \
-  }                                                                           \
-  parent = RB_PARENT(elm, field);                                             \
-  color = RB_COLOR(elm, field);                                               \
-  if (child)                                                                  \
-    RB_PARENT(child, field) = parent;                                         \
-  if (parent) {                                                               \
-    if (RB_LEFT(parent, field) == elm)                                        \
-      RB_LEFT(parent, field) = child;                                         \
-    else                                                                      \
-      RB_RIGHT(parent, field) = child;                                        \
-    RB_AUGMENT(parent);                                                       \
-  } else                                                                      \
-    RB_ROOT(head) = child;                                                    \
-color:                                                                        \
-  if (color == RB_BLACK)                                                      \
-    name##_RB_REMOVE_COLOR(head, parent, child);                              \
-  return (old);                                                               \
-}                                                                             \
-                                                                              \
-/* Inserts a node into the RB tree */                                         \
-attr struct type *                                                            \
-name##_RB_INSERT(struct name *head, struct type *elm)                         \
-{                                                                             \
-  struct type *tmp;                                                           \
-  struct type *parent = NULL;                                                 \
-  int comp = 0;                                                               \
-  tmp = RB_ROOT(head);                                                        \
-  while (tmp) {                                                               \
-    parent = tmp;                                                             \
-    comp = (cmp)(elm, parent);                                                \
-    if (comp < 0)                                                             \
-      tmp = RB_LEFT(tmp, field);                                              \
-    else if (comp > 0)                                                        \
-      tmp = RB_RIGHT(tmp, field);                                             \
-    else                                                                      \
-      return (tmp);                                                           \
-  }                                                                           \
-  RB_SET(elm, parent, field);                                                 \
-  if (parent != NULL) {                                                       \
-    if (comp < 0)                                                             \
-      RB_LEFT(parent, field) = elm;                                           \
-    else                                                                      \
-      RB_RIGHT(parent, field) = elm;                                          \
-    RB_AUGMENT(parent);                                                       \
-  } else                                                                      \
-    RB_ROOT(head) = elm;                                                      \
-  name##_RB_INSERT_COLOR(head, elm);                                          \
-  return (NULL);                                                              \
-}                                                                             \
-                                                                              \
-/* Finds the node with the same key as elm */                                 \
-attr struct type *                                                            \
-name##_RB_FIND(struct name *head, struct type *elm)                           \
-{                                                                             \
-  struct type *tmp = RB_ROOT(head);                                           \
-  int comp;                                                                   \
-  while (tmp) {                                                               \
-    comp = cmp(elm, tmp);                                                     \
-    if (comp < 0)                                                             \
-      tmp = RB_LEFT(tmp, field);                                              \
-    else if (comp > 0)                                                        \
-      tmp = RB_RIGHT(tmp, field);                                             \
-    else                                                                      \
-      return (tmp);                                                           \
-  }                                                                           \
-  return (NULL);                                                              \
-}                                                                             \
-                                                                              \
-/* Finds the first node greater than or equal to the search key */            \
-attr struct type *                                                            \
-name##_RB_NFIND(struct name *head, struct type *elm)                          \
-{                                                                             \
-  struct type *tmp = RB_ROOT(head);                                           \
-  struct type *res = NULL;                                                    \
-  int comp;                                                                   \
-  while (tmp) {                                                               \
-    comp = cmp(elm, tmp);                                                     \
-    if (comp < 0) {                                                           \
-      res = tmp;                                                              \
-      tmp = RB_LEFT(tmp, field);                                              \
-    }                                                                         \
-    else if (comp > 0)                                                        \
-      tmp = RB_RIGHT(tmp, field);                                             \
-    else                                                                      \
-      return (tmp);                                                           \
-  }                                                                           \
-  return (res);                                                               \
-}                                                                             \
-                                                                              \
-/* ARGSUSED */                                                                \
-attr struct type *                                                            \
-name##_RB_NEXT(struct type *elm)                                              \
-{                                                                             \
-  if (RB_RIGHT(elm, field)) {                                                 \
-    elm = RB_RIGHT(elm, field);                                               \
-    while (RB_LEFT(elm, field))                                               \
-      elm = RB_LEFT(elm, field);                                              \
-  } else {                                                                    \
-    if (RB_PARENT(elm, field) &&                                              \
-        (elm == RB_LEFT(RB_PARENT(elm, field), field)))                       \
-      elm = RB_PARENT(elm, field);                                            \
-    else {                                                                    \
-      while (RB_PARENT(elm, field) &&                                         \
-          (elm == RB_RIGHT(RB_PARENT(elm, field), field)))                    \
-        elm = RB_PARENT(elm, field);                                          \
-      elm = RB_PARENT(elm, field);                                            \
-    }                                                                         \
-  }                                                                           \
-  return (elm);                                                               \
-}                                                                             \
-                                                                              \
-/* ARGSUSED */                                                                \
-attr struct type *                                                            \
-name##_RB_PREV(struct type *elm)                                              \
-{                                                                             \
-  if (RB_LEFT(elm, field)) {                                                  \
-    elm = RB_LEFT(elm, field);                                                \
-    while (RB_RIGHT(elm, field))                                              \
-      elm = RB_RIGHT(elm, field);                                             \
-  } else {                                                                    \
-    if (RB_PARENT(elm, field) &&                                              \
-        (elm == RB_RIGHT(RB_PARENT(elm, field), field)))                      \
-      elm = RB_PARENT(elm, field);                                            \
-    else {                                                                    \
-      while (RB_PARENT(elm, field) &&                                         \
-          (elm == RB_LEFT(RB_PARENT(elm, field), field)))                     \
-        elm = RB_PARENT(elm, field);                                          \
-      elm = RB_PARENT(elm, field);                                            \
-    }                                                                         \
-  }                                                                           \
-  return (elm);                                                               \
-}                                                                             \
-                                                                              \
-attr struct type *                                                            \
-name##_RB_MINMAX(struct name *head, int val)                                  \
-{                                                                             \
-  struct type *tmp = RB_ROOT(head);                                           \
-  struct type *parent = NULL;                                                 \
-  while (tmp) {                                                               \
-    parent = tmp;                                                             \
-    if (val < 0)                                                              \
-      tmp = RB_LEFT(tmp, field);                                              \
-    else                                                                      \
-      tmp = RB_RIGHT(tmp, field);                                             \
-  }                                                                           \
-  return (parent);                                                            \
-}
-
-#define RB_NEGINF   -1
-#define RB_INF      1
-
-#define RB_INSERT(name, x, y)   name##_RB_INSERT(x, y)
-#define RB_REMOVE(name, x, y)   name##_RB_REMOVE(x, y)
-#define RB_FIND(name, x, y)     name##_RB_FIND(x, y)
-#define RB_NFIND(name, x, y)    name##_RB_NFIND(x, y)
-#define RB_NEXT(name, x, y)     name##_RB_NEXT(y)
-#define RB_PREV(name, x, y)     name##_RB_PREV(y)
-#define RB_MIN(name, x)         name##_RB_MINMAX(x, RB_NEGINF)
-#define RB_MAX(name, x)         name##_RB_MINMAX(x, RB_INF)
-
-#define RB_FOREACH(x, name, head)                                             \
-  for ((x) = RB_MIN(name, head);                                              \
-       (x) != NULL;                                                           \
-       (x) = name##_RB_NEXT(x))
-
-#define RB_FOREACH_FROM(x, name, y)                                           \
-  for ((x) = (y);                                                             \
-      ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL);                \
-       (x) = (y))
-
-#define RB_FOREACH_SAFE(x, name, head, y)                                     \
-  for ((x) = RB_MIN(name, head);                                              \
-      ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL);                \
-       (x) = (y))
-
-#define RB_FOREACH_REVERSE(x, name, head)                                     \
-  for ((x) = RB_MAX(name, head);                                              \
-       (x) != NULL;                                                           \
-       (x) = name##_RB_PREV(x))
-
-#define RB_FOREACH_REVERSE_FROM(x, name, y)                                   \
-  for ((x) = (y);                                                             \
-      ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL);                \
-       (x) = (y))
-
-#define RB_FOREACH_REVERSE_SAFE(x, name, head, y)                             \
-  for ((x) = RB_MAX(name, head);                                              \
-      ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL);                \
-       (x) = (y))
-
-#endif  /* UV_TREE_H_ */
diff --git a/wpiutil/src/main/native/libuv/include/uv/unix.h b/wpiutil/src/main/native/libuv/include/uv/unix.h
deleted file mode 100644
index 504bab7..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/unix.h
+++ /dev/null
@@ -1,483 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_UNIX_H
-#define UV_UNIX_H
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>  /* MAXHOSTNAMELEN on Solaris */
-
-#include <termios.h>
-#include <pwd.h>
-
-#if !defined(__MVS__)
-#include <semaphore.h>
-#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
-#endif
-#include <pthread.h>
-#include <signal.h>
-
-#include "uv/threadpool.h"
-
-#if defined(__linux__)
-# include "uv/linux.h"
-#elif defined(__APPLE__)
-# include "uv/darwin.h"
-#elif defined(__DragonFly__)       || \
-      defined(__FreeBSD__)         || \
-      defined(__FreeBSD_kernel__)  || \
-      defined(__OpenBSD__)         || \
-      defined(__NetBSD__)
-# include "uv/bsd.h"
-#elif defined(__PASE__)   || \
-      defined(__CYGWIN__) || \
-      defined(__MSYS__)   || \
-      defined(__GNU__)
-# include "uv/posix.h"
-#elif defined(__HAIKU__)
-# include "uv/posix.h"
-#endif
-
-#ifndef NI_MAXHOST
-# define NI_MAXHOST 1025
-#endif
-
-#ifndef NI_MAXSERV
-# define NI_MAXSERV 32
-#endif
-
-#ifndef UV_IO_PRIVATE_PLATFORM_FIELDS
-# define UV_IO_PRIVATE_PLATFORM_FIELDS /* empty */
-#endif
-
-struct uv__io_s;
-struct uv_loop_s;
-
-typedef void (*uv__io_cb)(struct uv_loop_s* loop,
-                          struct uv__io_s* w,
-                          unsigned int events);
-typedef struct uv__io_s uv__io_t;
-
-struct uv__io_s {
-  uv__io_cb cb;
-  void* pending_queue[2];
-  void* watcher_queue[2];
-  unsigned int pevents; /* Pending event mask i.e. mask at next tick. */
-  unsigned int events;  /* Current event mask. */
-  int fd;
-  UV_IO_PRIVATE_PLATFORM_FIELDS
-};
-
-#ifndef UV_PLATFORM_SEM_T
-# define UV_PLATFORM_SEM_T sem_t
-#endif
-
-#ifndef UV_PLATFORM_LOOP_FIELDS
-# define UV_PLATFORM_LOOP_FIELDS /* empty */
-#endif
-
-#ifndef UV_PLATFORM_FS_EVENT_FIELDS
-# define UV_PLATFORM_FS_EVENT_FIELDS /* empty */
-#endif
-
-#ifndef UV_STREAM_PRIVATE_PLATFORM_FIELDS
-# define UV_STREAM_PRIVATE_PLATFORM_FIELDS /* empty */
-#endif
-
-/* Note: May be cast to struct iovec. See writev(2). */
-typedef struct uv_buf_t {
-  char* base;
-  size_t len;
-} uv_buf_t;
-
-typedef int uv_file;
-typedef int uv_os_sock_t;
-typedef int uv_os_fd_t;
-typedef pid_t uv_pid_t;
-
-#define UV_ONCE_INIT PTHREAD_ONCE_INIT
-
-typedef pthread_once_t uv_once_t;
-typedef pthread_t uv_thread_t;
-typedef pthread_mutex_t uv_mutex_t;
-typedef pthread_rwlock_t uv_rwlock_t;
-typedef UV_PLATFORM_SEM_T uv_sem_t;
-typedef pthread_cond_t uv_cond_t;
-typedef pthread_key_t uv_key_t;
-
-/* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */
-#if defined(_AIX) || \
-    defined(__OpenBSD__) || \
-    !defined(PTHREAD_BARRIER_SERIAL_THREAD)
-/* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */
-struct _uv_barrier {
-  uv_mutex_t mutex;
-  uv_cond_t cond;
-  unsigned threshold;
-  unsigned in;
-  unsigned out;
-};
-
-typedef struct {
-  struct _uv_barrier* b;
-# if defined(PTHREAD_BARRIER_SERIAL_THREAD)
-  /* TODO(bnoordhuis) Remove padding in v2. */
-  char pad[sizeof(pthread_barrier_t) - sizeof(struct _uv_barrier*)];
-# endif
-} uv_barrier_t;
-#else
-typedef pthread_barrier_t uv_barrier_t;
-#endif
-
-/* Platform-specific definitions for uv_spawn support. */
-typedef gid_t uv_gid_t;
-typedef uid_t uv_uid_t;
-
-typedef struct dirent uv__dirent_t;
-
-#define UV_DIR_PRIVATE_FIELDS \
-  DIR* dir;
-
-#if defined(DT_UNKNOWN)
-# define HAVE_DIRENT_TYPES
-# if defined(DT_REG)
-#  define UV__DT_FILE DT_REG
-# else
-#  define UV__DT_FILE -1
-# endif
-# if defined(DT_DIR)
-#  define UV__DT_DIR DT_DIR
-# else
-#  define UV__DT_DIR -2
-# endif
-# if defined(DT_LNK)
-#  define UV__DT_LINK DT_LNK
-# else
-#  define UV__DT_LINK -3
-# endif
-# if defined(DT_FIFO)
-#  define UV__DT_FIFO DT_FIFO
-# else
-#  define UV__DT_FIFO -4
-# endif
-# if defined(DT_SOCK)
-#  define UV__DT_SOCKET DT_SOCK
-# else
-#  define UV__DT_SOCKET -5
-# endif
-# if defined(DT_CHR)
-#  define UV__DT_CHAR DT_CHR
-# else
-#  define UV__DT_CHAR -6
-# endif
-# if defined(DT_BLK)
-#  define UV__DT_BLOCK DT_BLK
-# else
-#  define UV__DT_BLOCK -7
-# endif
-#endif
-
-/* Platform-specific definitions for uv_dlopen support. */
-#define UV_DYNAMIC /* empty */
-
-typedef struct {
-  void* handle;
-  char* errmsg;
-} uv_lib_t;
-
-#define UV_LOOP_PRIVATE_FIELDS                                                \
-  unsigned long flags;                                                        \
-  int backend_fd;                                                             \
-  void* pending_queue[2];                                                     \
-  void* watcher_queue[2];                                                     \
-  void** watchers;                                                            \
-  unsigned int nwatchers;                                                     \
-  unsigned int nfds;                                                          \
-  void* wq[2];                                                                \
-  uv_mutex_t wq_mutex;                                                        \
-  uv_async_t wq_async;                                                        \
-  uv_rwlock_t cloexec_lock;                                                   \
-  uv_handle_t* closing_handles;                                               \
-  void* process_handles[2];                                                   \
-  void* prepare_handles[2];                                                   \
-  void* check_handles[2];                                                     \
-  void* idle_handles[2];                                                      \
-  void* async_handles[2];                                                     \
-  void (*async_unused)(void);  /* TODO(bnoordhuis) Remove in libuv v2. */     \
-  uv__io_t async_io_watcher;                                                  \
-  int async_wfd;                                                              \
-  struct {                                                                    \
-    void* min;                                                                \
-    unsigned int nelts;                                                       \
-  } timer_heap;                                                               \
-  uint64_t timer_counter;                                                     \
-  uint64_t time;                                                              \
-  int signal_pipefd[2];                                                       \
-  uv__io_t signal_io_watcher;                                                 \
-  uv_signal_t child_watcher;                                                  \
-  int emfile_fd;                                                              \
-  UV_PLATFORM_LOOP_FIELDS                                                     \
-
-#define UV_REQ_TYPE_PRIVATE /* empty */
-
-#define UV_REQ_PRIVATE_FIELDS  /* empty */
-
-#define UV_PRIVATE_REQ_TYPES /* empty */
-
-#define UV_WRITE_PRIVATE_FIELDS                                               \
-  void* queue[2];                                                             \
-  unsigned int write_index;                                                   \
-  uv_buf_t* bufs;                                                             \
-  unsigned int nbufs;                                                         \
-  int error;                                                                  \
-  uv_buf_t bufsml[4];                                                         \
-
-#define UV_CONNECT_PRIVATE_FIELDS                                             \
-  void* queue[2];                                                             \
-
-#define UV_SHUTDOWN_PRIVATE_FIELDS /* empty */
-
-#define UV_UDP_SEND_PRIVATE_FIELDS                                            \
-  void* queue[2];                                                             \
-  struct sockaddr_storage addr;                                               \
-  unsigned int nbufs;                                                         \
-  uv_buf_t* bufs;                                                             \
-  ssize_t status;                                                             \
-  uv_udp_send_cb send_cb;                                                     \
-  uv_buf_t bufsml[4];                                                         \
-
-#define UV_HANDLE_PRIVATE_FIELDS                                              \
-  uv_handle_t* next_closing;                                                  \
-  unsigned int flags;                                                         \
-
-#define UV_STREAM_PRIVATE_FIELDS                                              \
-  uv_connect_t *connect_req;                                                  \
-  uv_shutdown_t *shutdown_req;                                                \
-  uv__io_t io_watcher;                                                        \
-  void* write_queue[2];                                                       \
-  void* write_completed_queue[2];                                             \
-  uv_connection_cb connection_cb;                                             \
-  int delayed_error;                                                          \
-  int accepted_fd;                                                            \
-  void* queued_fds;                                                           \
-  UV_STREAM_PRIVATE_PLATFORM_FIELDS                                           \
-
-#define UV_TCP_PRIVATE_FIELDS /* empty */
-
-#define UV_UDP_PRIVATE_FIELDS                                                 \
-  uv_alloc_cb alloc_cb;                                                       \
-  uv_udp_recv_cb recv_cb;                                                     \
-  uv__io_t io_watcher;                                                        \
-  void* write_queue[2];                                                       \
-  void* write_completed_queue[2];                                             \
-
-#define UV_PIPE_PRIVATE_FIELDS                                                \
-  const char* pipe_fname; /* strdup'ed */
-
-#define UV_POLL_PRIVATE_FIELDS                                                \
-  uv__io_t io_watcher;
-
-#define UV_PREPARE_PRIVATE_FIELDS                                             \
-  uv_prepare_cb prepare_cb;                                                   \
-  void* queue[2];                                                             \
-
-#define UV_CHECK_PRIVATE_FIELDS                                               \
-  uv_check_cb check_cb;                                                       \
-  void* queue[2];                                                             \
-
-#define UV_IDLE_PRIVATE_FIELDS                                                \
-  uv_idle_cb idle_cb;                                                         \
-  void* queue[2];                                                             \
-
-#define UV_ASYNC_PRIVATE_FIELDS                                               \
-  uv_async_cb async_cb;                                                       \
-  void* queue[2];                                                             \
-  int pending;                                                                \
-
-#define UV_TIMER_PRIVATE_FIELDS                                               \
-  uv_timer_cb timer_cb;                                                       \
-  void* heap_node[3];                                                         \
-  uint64_t timeout;                                                           \
-  uint64_t repeat;                                                            \
-  uint64_t start_id;
-
-#define UV_GETADDRINFO_PRIVATE_FIELDS                                         \
-  struct uv__work work_req;                                                   \
-  uv_getaddrinfo_cb cb;                                                       \
-  struct addrinfo* hints;                                                     \
-  char* hostname;                                                             \
-  char* service;                                                              \
-  struct addrinfo* addrinfo;                                                  \
-  int retcode;
-
-#define UV_GETNAMEINFO_PRIVATE_FIELDS                                         \
-  struct uv__work work_req;                                                   \
-  uv_getnameinfo_cb getnameinfo_cb;                                           \
-  struct sockaddr_storage storage;                                            \
-  int flags;                                                                  \
-  char host[NI_MAXHOST];                                                      \
-  char service[NI_MAXSERV];                                                   \
-  int retcode;
-
-#define UV_PROCESS_PRIVATE_FIELDS                                             \
-  void* queue[2];                                                             \
-  int status;                                                                 \
-
-#define UV_FS_PRIVATE_FIELDS                                                  \
-  const char *new_path;                                                       \
-  uv_file file;                                                               \
-  int flags;                                                                  \
-  mode_t mode;                                                                \
-  unsigned int nbufs;                                                         \
-  uv_buf_t* bufs;                                                             \
-  off_t off;                                                                  \
-  uv_uid_t uid;                                                               \
-  uv_gid_t gid;                                                               \
-  double atime;                                                               \
-  double mtime;                                                               \
-  struct uv__work work_req;                                                   \
-  uv_buf_t bufsml[4];                                                         \
-
-#define UV_WORK_PRIVATE_FIELDS                                                \
-  struct uv__work work_req;
-
-#define UV_TTY_PRIVATE_FIELDS                                                 \
-  struct termios orig_termios;                                                \
-  int mode;
-
-#define UV_SIGNAL_PRIVATE_FIELDS                                              \
-  /* RB_ENTRY(uv_signal_s) tree_entry; */                                     \
-  struct {                                                                    \
-    struct uv_signal_s* rbe_left;                                             \
-    struct uv_signal_s* rbe_right;                                            \
-    struct uv_signal_s* rbe_parent;                                           \
-    int rbe_color;                                                            \
-  } tree_entry;                                                               \
-  /* Use two counters here so we don have to fiddle with atomics. */          \
-  unsigned int caught_signals;                                                \
-  unsigned int dispatched_signals;
-
-#define UV_FS_EVENT_PRIVATE_FIELDS                                            \
-  uv_fs_event_cb cb;                                                          \
-  UV_PLATFORM_FS_EVENT_FIELDS                                                 \
-
-/* fs open() flags supported on this platform: */
-#if defined(O_APPEND)
-# define UV_FS_O_APPEND       O_APPEND
-#else
-# define UV_FS_O_APPEND       0
-#endif
-#if defined(O_CREAT)
-# define UV_FS_O_CREAT        O_CREAT
-#else
-# define UV_FS_O_CREAT        0
-#endif
-#if defined(O_DIRECT)
-# define UV_FS_O_DIRECT       O_DIRECT
-#else
-# define UV_FS_O_DIRECT       0
-#endif
-#if defined(O_DIRECTORY)
-# define UV_FS_O_DIRECTORY    O_DIRECTORY
-#else
-# define UV_FS_O_DIRECTORY    0
-#endif
-#if defined(O_DSYNC)
-# define UV_FS_O_DSYNC        O_DSYNC
-#else
-# define UV_FS_O_DSYNC        0
-#endif
-#if defined(O_EXCL)
-# define UV_FS_O_EXCL         O_EXCL
-#else
-# define UV_FS_O_EXCL         0
-#endif
-#if defined(O_EXLOCK)
-# define UV_FS_O_EXLOCK       O_EXLOCK
-#else
-# define UV_FS_O_EXLOCK       0
-#endif
-#if defined(O_NOATIME)
-# define UV_FS_O_NOATIME      O_NOATIME
-#else
-# define UV_FS_O_NOATIME      0
-#endif
-#if defined(O_NOCTTY)
-# define UV_FS_O_NOCTTY       O_NOCTTY
-#else
-# define UV_FS_O_NOCTTY       0
-#endif
-#if defined(O_NOFOLLOW)
-# define UV_FS_O_NOFOLLOW     O_NOFOLLOW
-#else
-# define UV_FS_O_NOFOLLOW     0
-#endif
-#if defined(O_NONBLOCK)
-# define UV_FS_O_NONBLOCK     O_NONBLOCK
-#else
-# define UV_FS_O_NONBLOCK     0
-#endif
-#if defined(O_RDONLY)
-# define UV_FS_O_RDONLY       O_RDONLY
-#else
-# define UV_FS_O_RDONLY       0
-#endif
-#if defined(O_RDWR)
-# define UV_FS_O_RDWR         O_RDWR
-#else
-# define UV_FS_O_RDWR         0
-#endif
-#if defined(O_SYMLINK)
-# define UV_FS_O_SYMLINK      O_SYMLINK
-#else
-# define UV_FS_O_SYMLINK      0
-#endif
-#if defined(O_SYNC)
-# define UV_FS_O_SYNC         O_SYNC
-#else
-# define UV_FS_O_SYNC         0
-#endif
-#if defined(O_TRUNC)
-# define UV_FS_O_TRUNC        O_TRUNC
-#else
-# define UV_FS_O_TRUNC        0
-#endif
-#if defined(O_WRONLY)
-# define UV_FS_O_WRONLY       O_WRONLY
-#else
-# define UV_FS_O_WRONLY       0
-#endif
-
-/* fs open() flags supported on other platforms: */
-#define UV_FS_O_RANDOM        0
-#define UV_FS_O_SHORT_LIVED   0
-#define UV_FS_O_SEQUENTIAL    0
-#define UV_FS_O_TEMPORARY     0
-
-#endif /* UV_UNIX_H */
diff --git a/wpiutil/src/main/native/libuv/include/uv/version.h b/wpiutil/src/main/native/libuv/include/uv/version.h
deleted file mode 100644
index bf992d2..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/version.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_VERSION_H
-#define UV_VERSION_H
-
- /*
- * Versions with the same major number are ABI stable. API is allowed to
- * evolve between minor releases, but only in a backwards compatible way.
- * Make sure you update the -soname directives in configure.ac
- * and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
- * not UV_VERSION_PATCH.)
- */
-
-#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 30
-#define UV_VERSION_PATCH 1
-#define UV_VERSION_IS_RELEASE 1
-#define UV_VERSION_SUFFIX ""
-
-#define UV_VERSION_HEX  ((UV_VERSION_MAJOR << 16) | \
-                         (UV_VERSION_MINOR <<  8) | \
-                         (UV_VERSION_PATCH))
-
-#endif /* UV_VERSION_H */
diff --git a/wpiutil/src/main/native/libuv/include/uv/win.h b/wpiutil/src/main/native/libuv/include/uv/win.h
deleted file mode 100644
index ca5242f..0000000
--- a/wpiutil/src/main/native/libuv/include/uv/win.h
+++ /dev/null
@@ -1,691 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef _WIN32_WINNT
-# define _WIN32_WINNT   0x0600
-#endif
-
-#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
-typedef intptr_t ssize_t;
-# define SSIZE_MAX INTPTR_MAX
-# define _SSIZE_T_
-# define _SSIZE_T_DEFINED
-#endif
-
-#include <winsock2.h>
-
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-typedef struct pollfd {
-  SOCKET fd;
-  short  events;
-  short  revents;
-} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
-#endif
-
-#ifndef LOCALE_INVARIANT
-# define LOCALE_INVARIANT 0x007f
-#endif
-
-#include <mswsock.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-
-#include <process.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#include <stdint.h>
-
-#include "uv/tree.h"
-#include "uv/threadpool.h"
-
-#define MAX_PIPENAME_LEN 256
-
-#ifndef S_IFLNK
-# define S_IFLNK 0xA000
-#endif
-
-/* Additional signals supported by uv_signal and or uv_kill. The CRT defines
- * the following signals already:
- *
- *   #define SIGINT           2
- *   #define SIGILL           4
- *   #define SIGABRT_COMPAT   6
- *   #define SIGFPE           8
- *   #define SIGSEGV         11
- *   #define SIGTERM         15
- *   #define SIGBREAK        21
- *   #define SIGABRT         22
- *
- * The additional signals have values that are common on other Unix
- * variants (Linux and Darwin)
- */
-#define SIGHUP                1
-#define SIGKILL               9
-#define SIGWINCH             28
-
-/* Redefine NSIG to take SIGWINCH into consideration */
-#if defined(NSIG) && NSIG <= SIGWINCH
-# undef NSIG
-#endif
-#ifndef NSIG
-# define NSIG SIGWINCH + 1
-#endif
-
-/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like
- * platforms. However MinGW doesn't define it, so we do. */
-#ifndef SIGABRT_COMPAT
-# define SIGABRT_COMPAT       6
-#endif
-
-/*
- * Guids and typedefs for winsock extension functions
- * Mingw32 doesn't have these :-(
- */
-#ifndef WSAID_ACCEPTEX
-# define WSAID_ACCEPTEX                                                       \
-         {0xb5367df1, 0xcbac, 0x11cf,                                         \
-         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
-
-# define WSAID_CONNECTEX                                                      \
-         {0x25a207b9, 0xddf3, 0x4660,                                         \
-         {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}}
-
-# define WSAID_GETACCEPTEXSOCKADDRS                                           \
-         {0xb5367df2, 0xcbac, 0x11cf,                                         \
-         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
-
-# define WSAID_DISCONNECTEX                                                   \
-         {0x7fda2e11, 0x8630, 0x436f,                                         \
-         {0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}}
-
-# define WSAID_TRANSMITFILE                                                   \
-         {0xb5367df0, 0xcbac, 0x11cf,                                         \
-         {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
-
-  typedef BOOL (PASCAL *LPFN_ACCEPTEX)
-                      (SOCKET sListenSocket,
-                       SOCKET sAcceptSocket,
-                       PVOID lpOutputBuffer,
-                       DWORD dwReceiveDataLength,
-                       DWORD dwLocalAddressLength,
-                       DWORD dwRemoteAddressLength,
-                       LPDWORD lpdwBytesReceived,
-                       LPOVERLAPPED lpOverlapped);
-
-  typedef BOOL (PASCAL *LPFN_CONNECTEX)
-                      (SOCKET s,
-                       const struct sockaddr* name,
-                       int namelen,
-                       PVOID lpSendBuffer,
-                       DWORD dwSendDataLength,
-                       LPDWORD lpdwBytesSent,
-                       LPOVERLAPPED lpOverlapped);
-
-  typedef void (PASCAL *LPFN_GETACCEPTEXSOCKADDRS)
-                      (PVOID lpOutputBuffer,
-                       DWORD dwReceiveDataLength,
-                       DWORD dwLocalAddressLength,
-                       DWORD dwRemoteAddressLength,
-                       LPSOCKADDR* LocalSockaddr,
-                       LPINT LocalSockaddrLength,
-                       LPSOCKADDR* RemoteSockaddr,
-                       LPINT RemoteSockaddrLength);
-
-  typedef BOOL (PASCAL *LPFN_DISCONNECTEX)
-                      (SOCKET hSocket,
-                       LPOVERLAPPED lpOverlapped,
-                       DWORD dwFlags,
-                       DWORD reserved);
-
-  typedef BOOL (PASCAL *LPFN_TRANSMITFILE)
-                      (SOCKET hSocket,
-                       HANDLE hFile,
-                       DWORD nNumberOfBytesToWrite,
-                       DWORD nNumberOfBytesPerSend,
-                       LPOVERLAPPED lpOverlapped,
-                       LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers,
-                       DWORD dwFlags);
-
-  typedef PVOID RTL_SRWLOCK;
-  typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
-#endif
-
-typedef int (WSAAPI* LPFN_WSARECV)
-            (SOCKET socket,
-             LPWSABUF buffers,
-             DWORD buffer_count,
-             LPDWORD bytes,
-             LPDWORD flags,
-             LPWSAOVERLAPPED overlapped,
-             LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
-
-typedef int (WSAAPI* LPFN_WSARECVFROM)
-            (SOCKET socket,
-             LPWSABUF buffers,
-             DWORD buffer_count,
-             LPDWORD bytes,
-             LPDWORD flags,
-             struct sockaddr* addr,
-             LPINT addr_len,
-             LPWSAOVERLAPPED overlapped,
-             LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
-
-#pragma warning(push)
-#pragma warning(disable : 28251)
-
-#ifndef _NTDEF_
-  typedef LONG NTSTATUS;
-  typedef NTSTATUS *PNTSTATUS;
-#endif
-
-#pragma warning(pop)
-
-#ifndef RTL_CONDITION_VARIABLE_INIT
-  typedef PVOID CONDITION_VARIABLE, *PCONDITION_VARIABLE;
-#endif
-
-typedef struct _AFD_POLL_HANDLE_INFO {
-  HANDLE Handle;
-  ULONG Events;
-  NTSTATUS Status;
-} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO;
-
-typedef struct _AFD_POLL_INFO {
-  LARGE_INTEGER Timeout;
-  ULONG NumberOfHandles;
-  ULONG Exclusive;
-  AFD_POLL_HANDLE_INFO Handles[1];
-} AFD_POLL_INFO, *PAFD_POLL_INFO;
-
-#define UV_MSAFD_PROVIDER_COUNT 3
-
-
-/**
- * It should be possible to cast uv_buf_t[] to WSABUF[]
- * see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx
- */
-typedef struct uv_buf_t {
-  ULONG len;
-  char* base;
-} uv_buf_t;
-
-typedef int uv_file;
-typedef SOCKET uv_os_sock_t;
-typedef HANDLE uv_os_fd_t;
-typedef int uv_pid_t;
-
-typedef HANDLE uv_thread_t;
-
-typedef HANDLE uv_sem_t;
-
-typedef CRITICAL_SECTION uv_mutex_t;
-
-/* This condition variable implementation is based on the SetEvent solution
- * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
- * We could not use the SignalObjectAndWait solution (section 3.4) because
- * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and
- * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs.
- */
-
-typedef union {
-  CONDITION_VARIABLE cond_var;
-  struct {
-    unsigned int waiters_count;
-    CRITICAL_SECTION waiters_count_lock;
-    HANDLE signal_event;
-    HANDLE broadcast_event;
-  } unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */
-} uv_cond_t;
-
-typedef union {
-  struct {
-    unsigned int num_readers_;
-    CRITICAL_SECTION num_readers_lock_;
-    HANDLE write_semaphore_;
-  } state_;
-  /* TODO: remove me in v2.x. */
-  struct {
-    SRWLOCK unused_;
-  } unused1_;
-  /* TODO: remove me in v2.x. */
-  struct {
-    uv_mutex_t unused1_;
-    uv_mutex_t unused2_;
-  } unused2_;
-} uv_rwlock_t;
-
-typedef struct {
-  unsigned int n;
-  unsigned int count;
-  uv_mutex_t mutex;
-  uv_sem_t turnstile1;
-  uv_sem_t turnstile2;
-} uv_barrier_t;
-
-typedef struct {
-  DWORD tls_index;
-} uv_key_t;
-
-#define UV_ONCE_INIT { 0, NULL }
-
-typedef struct uv_once_s {
-  unsigned char ran;
-  HANDLE event;
-} uv_once_t;
-
-/* Platform-specific definitions for uv_spawn support. */
-typedef unsigned char uv_uid_t;
-typedef unsigned char uv_gid_t;
-
-typedef struct uv__dirent_s {
-  int d_type;
-  char d_name[1];
-} uv__dirent_t;
-
-#define UV_DIR_PRIVATE_FIELDS \
-  HANDLE dir_handle;          \
-  WIN32_FIND_DATAW find_data; \
-  BOOL need_find_call;
-
-#define HAVE_DIRENT_TYPES
-#define UV__DT_DIR     UV_DIRENT_DIR
-#define UV__DT_FILE    UV_DIRENT_FILE
-#define UV__DT_LINK    UV_DIRENT_LINK
-#define UV__DT_FIFO    UV_DIRENT_FIFO
-#define UV__DT_SOCKET  UV_DIRENT_SOCKET
-#define UV__DT_CHAR    UV_DIRENT_CHAR
-#define UV__DT_BLOCK   UV_DIRENT_BLOCK
-
-/* Platform-specific definitions for uv_dlopen support. */
-#define UV_DYNAMIC FAR WINAPI
-typedef struct {
-  HMODULE handle;
-  char* errmsg;
-} uv_lib_t;
-
-#define UV_LOOP_PRIVATE_FIELDS                                                \
-    /* The loop's I/O completion port */                                      \
-  HANDLE iocp;                                                                \
-  /* The current time according to the event loop. in msecs. */               \
-  uint64_t time;                                                              \
-  /* Tail of a single-linked circular queue of pending reqs. If the queue */  \
-  /* is empty, tail_ is NULL. If there is only one item, */                   \
-  /* tail_->next_req == tail_ */                                              \
-  uv_req_t* pending_reqs_tail;                                                \
-  /* Head of a single-linked list of closed handles */                        \
-  uv_handle_t* endgame_handles;                                               \
-  /* TODO(bnoordhuis) Stop heap-allocating |timer_heap| in libuv v2.x. */     \
-  void* timer_heap;                                                           \
-    /* Lists of active loop (prepare / check / idle) watchers */              \
-  uv_prepare_t* prepare_handles;                                              \
-  uv_check_t* check_handles;                                                  \
-  uv_idle_t* idle_handles;                                                    \
-  /* This pointer will refer to the prepare/check/idle handle whose */        \
-  /* callback is scheduled to be called next. This is needed to allow */      \
-  /* safe removal from one of the lists above while that list being */        \
-  /* iterated over. */                                                        \
-  uv_prepare_t* next_prepare_handle;                                          \
-  uv_check_t* next_check_handle;                                              \
-  uv_idle_t* next_idle_handle;                                                \
-  /* This handle holds the peer sockets for the fast variant of uv_poll_t */  \
-  SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT];                          \
-  /* Counter to keep track of active tcp streams */                           \
-  unsigned int active_tcp_streams;                                            \
-  /* Counter to keep track of active udp streams */                           \
-  unsigned int active_udp_streams;                                            \
-  /* Counter to started timer */                                              \
-  uint64_t timer_counter;                                                     \
-  /* Threadpool */                                                            \
-  void* wq[2];                                                                \
-  uv_mutex_t wq_mutex;                                                        \
-  uv_async_t wq_async;
-
-#define UV_REQ_TYPE_PRIVATE                                                   \
-  /* TODO: remove the req suffix */                                           \
-  UV_ACCEPT,                                                                  \
-  UV_FS_EVENT_REQ,                                                            \
-  UV_POLL_REQ,                                                                \
-  UV_PROCESS_EXIT,                                                            \
-  UV_READ,                                                                    \
-  UV_UDP_RECV,                                                                \
-  UV_WAKEUP,                                                                  \
-  UV_SIGNAL_REQ,
-
-#define UV_REQ_PRIVATE_FIELDS                                                 \
-  union {                                                                     \
-    /* Used by I/O operations */                                              \
-    struct {                                                                  \
-      OVERLAPPED overlapped;                                                  \
-      size_t queued_bytes;                                                    \
-    } io;                                                                     \
-  } u;                                                                        \
-  struct uv_req_s* next_req;
-
-#define UV_WRITE_PRIVATE_FIELDS \
-  int coalesced;                \
-  uv_buf_t write_buffer;        \
-  HANDLE event_handle;          \
-  HANDLE wait_handle;
-
-#define UV_CONNECT_PRIVATE_FIELDS                                             \
-  /* empty */
-
-#define UV_SHUTDOWN_PRIVATE_FIELDS                                            \
-  /* empty */
-
-#define UV_UDP_SEND_PRIVATE_FIELDS                                            \
-  /* empty */
-
-#define UV_PRIVATE_REQ_TYPES                                                  \
-  typedef struct uv_pipe_accept_s {                                           \
-    UV_REQ_FIELDS                                                             \
-    HANDLE pipeHandle;                                                        \
-    struct uv_pipe_accept_s* next_pending;                                    \
-  } uv_pipe_accept_t;                                                         \
-                                                                              \
-  typedef struct uv_tcp_accept_s {                                            \
-    UV_REQ_FIELDS                                                             \
-    SOCKET accept_socket;                                                     \
-    char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32];             \
-    HANDLE event_handle;                                                      \
-    HANDLE wait_handle;                                                       \
-    struct uv_tcp_accept_s* next_pending;                                     \
-  } uv_tcp_accept_t;                                                          \
-                                                                              \
-  typedef struct uv_read_s {                                                  \
-    UV_REQ_FIELDS                                                             \
-    HANDLE event_handle;                                                      \
-    HANDLE wait_handle;                                                       \
-  } uv_read_t;
-
-#define uv_stream_connection_fields                                           \
-  unsigned int write_reqs_pending;                                            \
-  uv_shutdown_t* shutdown_req;
-
-#define uv_stream_server_fields                                               \
-  uv_connection_cb connection_cb;
-
-#define UV_STREAM_PRIVATE_FIELDS                                              \
-  unsigned int reqs_pending;                                                  \
-  int activecnt;                                                              \
-  uv_read_t read_req;                                                         \
-  union {                                                                     \
-    struct { uv_stream_connection_fields } conn;                              \
-    struct { uv_stream_server_fields     } serv;                              \
-  } stream;
-
-#define uv_tcp_server_fields                                                  \
-  uv_tcp_accept_t* accept_reqs;                                               \
-  unsigned int processed_accepts;                                             \
-  uv_tcp_accept_t* pending_accepts;                                           \
-  LPFN_ACCEPTEX func_acceptex;
-
-#define uv_tcp_connection_fields                                              \
-  uv_buf_t read_buffer;                                                       \
-  LPFN_CONNECTEX func_connectex;
-
-#define UV_TCP_PRIVATE_FIELDS                                                 \
-  SOCKET socket;                                                              \
-  int delayed_error;                                                          \
-  union {                                                                     \
-    struct { uv_tcp_server_fields } serv;                                     \
-    struct { uv_tcp_connection_fields } conn;                                 \
-  } tcp;
-
-#define UV_UDP_PRIVATE_FIELDS                                                 \
-  SOCKET socket;                                                              \
-  unsigned int reqs_pending;                                                  \
-  int activecnt;                                                              \
-  uv_req_t recv_req;                                                          \
-  uv_buf_t recv_buffer;                                                       \
-  struct sockaddr_storage recv_from;                                          \
-  int recv_from_len;                                                          \
-  uv_udp_recv_cb recv_cb;                                                     \
-  uv_alloc_cb alloc_cb;                                                       \
-  LPFN_WSARECV func_wsarecv;                                                  \
-  LPFN_WSARECVFROM func_wsarecvfrom;
-
-#define uv_pipe_server_fields                                                 \
-  int pending_instances;                                                      \
-  uv_pipe_accept_t* accept_reqs;                                              \
-  uv_pipe_accept_t* pending_accepts;
-
-#define uv_pipe_connection_fields                                             \
-  uv_timer_t* eof_timer;                                                      \
-  uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
-  DWORD ipc_remote_pid;                                                       \
-  union {                                                                     \
-    uint32_t payload_remaining;                                               \
-    uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \
-  } ipc_data_frame;                                                           \
-  void* ipc_xfer_queue[2];                                                    \
-  int ipc_xfer_queue_length;                                                  \
-  uv_write_t* non_overlapped_writes_tail;                                     \
-  CRITICAL_SECTION readfile_thread_lock;                                      \
-  volatile HANDLE readfile_thread_handle;
-
-#define UV_PIPE_PRIVATE_FIELDS                                                \
-  HANDLE handle;                                                              \
-  WCHAR* name;                                                                \
-  union {                                                                     \
-    struct { uv_pipe_server_fields } serv;                                    \
-    struct { uv_pipe_connection_fields } conn;                                \
-  } pipe;
-
-/* TODO: put the parser states in an union - TTY handles are always half-duplex
- * so read-state can safely overlap write-state. */
-#define UV_TTY_PRIVATE_FIELDS                                                 \
-  HANDLE handle;                                                              \
-  union {                                                                     \
-    struct {                                                                  \
-      /* Used for readable TTY handles */                                     \
-      /* TODO: remove me in v2.x. */                                          \
-      HANDLE unused_;                                                         \
-      uv_buf_t read_line_buffer;                                              \
-      HANDLE read_raw_wait;                                                   \
-      /* Fields used for translating win keystrokes into vt100 characters */  \
-      char last_key[8];                                                       \
-      unsigned char last_key_offset;                                          \
-      unsigned char last_key_len;                                             \
-      WCHAR last_utf16_high_surrogate;                                        \
-      INPUT_RECORD last_input_record;                                         \
-    } rd;                                                                     \
-    struct {                                                                  \
-      /* Used for writable TTY handles */                                     \
-      /* utf8-to-utf16 conversion state */                                    \
-      unsigned int utf8_codepoint;                                            \
-      unsigned char utf8_bytes_left;                                          \
-      /* eol conversion state */                                              \
-      unsigned char previous_eol;                                             \
-      /* ansi parser state */                                                 \
-      unsigned char ansi_parser_state;                                        \
-      unsigned char ansi_csi_argc;                                            \
-      unsigned short ansi_csi_argv[4];                                        \
-      COORD saved_position;                                                   \
-      WORD saved_attributes;                                                  \
-    } wr;                                                                     \
-  } tty;
-
-#define UV_POLL_PRIVATE_FIELDS                                                \
-  SOCKET socket;                                                              \
-  /* Used in fast mode */                                                     \
-  SOCKET peer_socket;                                                         \
-  AFD_POLL_INFO afd_poll_info_1;                                              \
-  AFD_POLL_INFO afd_poll_info_2;                                              \
-  /* Used in fast and slow mode. */                                           \
-  uv_req_t poll_req_1;                                                        \
-  uv_req_t poll_req_2;                                                        \
-  unsigned char submitted_events_1;                                           \
-  unsigned char submitted_events_2;                                           \
-  unsigned char mask_events_1;                                                \
-  unsigned char mask_events_2;                                                \
-  unsigned char events;
-
-#define UV_TIMER_PRIVATE_FIELDS                                               \
-  void* heap_node[3];                                                         \
-  int unused;                                                                 \
-  uint64_t timeout;                                                           \
-  uint64_t repeat;                                                            \
-  uint64_t start_id;                                                          \
-  uv_timer_cb timer_cb;
-
-#define UV_ASYNC_PRIVATE_FIELDS                                               \
-  struct uv_req_s async_req;                                                  \
-  uv_async_cb async_cb;                                                       \
-  /* char to avoid alignment issues */                                        \
-  char volatile async_sent;
-
-#define UV_PREPARE_PRIVATE_FIELDS                                             \
-  uv_prepare_t* prepare_prev;                                                 \
-  uv_prepare_t* prepare_next;                                                 \
-  uv_prepare_cb prepare_cb;
-
-#define UV_CHECK_PRIVATE_FIELDS                                               \
-  uv_check_t* check_prev;                                                     \
-  uv_check_t* check_next;                                                     \
-  uv_check_cb check_cb;
-
-#define UV_IDLE_PRIVATE_FIELDS                                                \
-  uv_idle_t* idle_prev;                                                       \
-  uv_idle_t* idle_next;                                                       \
-  uv_idle_cb idle_cb;
-
-#define UV_HANDLE_PRIVATE_FIELDS                                              \
-  uv_handle_t* endgame_next;                                                  \
-  unsigned int flags;
-
-#define UV_GETADDRINFO_PRIVATE_FIELDS                                         \
-  struct uv__work work_req;                                                   \
-  uv_getaddrinfo_cb getaddrinfo_cb;                                           \
-  void* alloc;                                                                \
-  WCHAR* node;                                                                \
-  WCHAR* service;                                                             \
-  /* The addrinfoW field is used to store a pointer to the hints, and    */   \
-  /* later on to store the result of GetAddrInfoW. The final result will */   \
-  /* be converted to struct addrinfo* and stored in the addrinfo field.  */   \
-  struct addrinfoW* addrinfow;                                                \
-  struct addrinfo* addrinfo;                                                  \
-  int retcode;
-
-#define UV_GETNAMEINFO_PRIVATE_FIELDS                                         \
-  struct uv__work work_req;                                                   \
-  uv_getnameinfo_cb getnameinfo_cb;                                           \
-  struct sockaddr_storage storage;                                            \
-  int flags;                                                                  \
-  char host[NI_MAXHOST];                                                      \
-  char service[NI_MAXSERV];                                                   \
-  int retcode;
-
-#define UV_PROCESS_PRIVATE_FIELDS                                             \
-  struct uv_process_exit_s {                                                  \
-    UV_REQ_FIELDS                                                             \
-  } exit_req;                                                                 \
-  BYTE* child_stdio_buffer;                                                   \
-  int exit_signal;                                                            \
-  HANDLE wait_handle;                                                         \
-  HANDLE process_handle;                                                      \
-  volatile char exit_cb_pending;
-
-#define UV_FS_PRIVATE_FIELDS                                                  \
-  struct uv__work work_req;                                                   \
-  int flags;                                                                  \
-  DWORD sys_errno_;                                                           \
-  union {                                                                     \
-    /* TODO: remove me in 0.9. */                                             \
-    WCHAR* pathw;                                                             \
-    int fd;                                                                   \
-  } file;                                                                     \
-  union {                                                                     \
-    struct {                                                                  \
-      int mode;                                                               \
-      WCHAR* new_pathw;                                                       \
-      int file_flags;                                                         \
-      int fd_out;                                                             \
-      unsigned int nbufs;                                                     \
-      uv_buf_t* bufs;                                                         \
-      int64_t offset;                                                         \
-      uv_buf_t bufsml[4];                                                     \
-    } info;                                                                   \
-    struct {                                                                  \
-      double atime;                                                           \
-      double mtime;                                                           \
-    } time;                                                                   \
-  } fs;
-
-#define UV_WORK_PRIVATE_FIELDS                                                \
-  struct uv__work work_req;
-
-#define UV_FS_EVENT_PRIVATE_FIELDS                                            \
-  struct uv_fs_event_req_s {                                                  \
-    UV_REQ_FIELDS                                                             \
-  } req;                                                                      \
-  HANDLE dir_handle;                                                          \
-  int req_pending;                                                            \
-  uv_fs_event_cb cb;                                                          \
-  WCHAR* filew;                                                               \
-  WCHAR* short_filew;                                                         \
-  WCHAR* dirw;                                                                \
-  char* buffer;
-
-#define UV_SIGNAL_PRIVATE_FIELDS                                              \
-  RB_ENTRY(uv_signal_s) tree_entry;                                           \
-  struct uv_req_s signal_req;                                                 \
-  unsigned long pending_signum;
-
-#ifndef F_OK
-#define F_OK 0
-#endif
-#ifndef R_OK
-#define R_OK 4
-#endif
-#ifndef W_OK
-#define W_OK 2
-#endif
-#ifndef X_OK
-#define X_OK 1
-#endif
-
-/* fs open() flags supported on this platform: */
-#define UV_FS_O_APPEND       _O_APPEND
-#define UV_FS_O_CREAT        _O_CREAT
-#define UV_FS_O_EXCL         _O_EXCL
-#define UV_FS_O_RANDOM       _O_RANDOM
-#define UV_FS_O_RDONLY       _O_RDONLY
-#define UV_FS_O_RDWR         _O_RDWR
-#define UV_FS_O_SEQUENTIAL   _O_SEQUENTIAL
-#define UV_FS_O_SHORT_LIVED  _O_SHORT_LIVED
-#define UV_FS_O_TEMPORARY    _O_TEMPORARY
-#define UV_FS_O_TRUNC        _O_TRUNC
-#define UV_FS_O_WRONLY       _O_WRONLY
-
-/* fs open() flags supported on other platforms (or mapped on this platform): */
-#define UV_FS_O_DIRECT       0x02000000 /* FILE_FLAG_NO_BUFFERING */
-#define UV_FS_O_DIRECTORY    0
-#define UV_FS_O_DSYNC        0x04000000 /* FILE_FLAG_WRITE_THROUGH */
-#define UV_FS_O_EXLOCK       0x10000000 /* EXCLUSIVE SHARING MODE */
-#define UV_FS_O_NOATIME      0
-#define UV_FS_O_NOCTTY       0
-#define UV_FS_O_NOFOLLOW     0
-#define UV_FS_O_NONBLOCK     0
-#define UV_FS_O_SYMLINK      0
-#define UV_FS_O_SYNC         0x08000000 /* FILE_FLAG_WRITE_THROUGH */
diff --git a/wpiutil/src/main/native/libuv/src/fs-poll.cpp b/wpiutil/src/main/native/libuv/src/fs-poll.cpp
deleted file mode 100644
index 14d64de..0000000
--- a/wpiutil/src/main/native/libuv/src/fs-poll.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "uv-common.h"
-
-#ifdef _WIN32
-#include "win/internal.h"
-#include "win/handle-inl.h"
-#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h))
-#else
-#include "unix/internal.h"
-#endif
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-struct poll_ctx {
-  uv_fs_poll_t* parent_handle;
-  int busy_polling;
-  unsigned int interval;
-  uint64_t start_time;
-  uv_loop_t* loop;
-  uv_fs_poll_cb poll_cb;
-  uv_timer_t timer_handle;
-  uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */
-  uv_stat_t statbuf;
-  struct poll_ctx* previous; /* context from previous start()..stop() period */
-  char path[1]; /* variable length */
-};
-
-static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b);
-static void poll_cb(uv_fs_t* req);
-static void timer_cb(uv_timer_t* timer);
-static void timer_close_cb(uv_handle_t* handle);
-
-static uv_stat_t zero_statbuf;
-
-
-int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) {
-  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL);
-  handle->poll_ctx = NULL;
-  return 0;
-}
-
-
-int uv_fs_poll_start(uv_fs_poll_t* handle,
-                     uv_fs_poll_cb cb,
-                     const char* path,
-                     unsigned int interval) {
-  struct poll_ctx* ctx;
-  uv_loop_t* loop;
-  size_t len;
-  int err;
-
-  if (uv_is_active((uv_handle_t*)handle))
-    return 0;
-
-  loop = handle->loop;
-  len = strlen(path);
-  ctx = (struct poll_ctx*)uv__calloc(1, sizeof(*ctx) + len);
-
-  if (ctx == NULL)
-    return UV_ENOMEM;
-
-  ctx->loop = loop;
-  ctx->poll_cb = cb;
-  ctx->interval = interval ? interval : 1;
-  ctx->start_time = uv_now(loop);
-  ctx->parent_handle = handle;
-  memcpy(ctx->path, path, len + 1);
-
-  err = uv_timer_init(loop, &ctx->timer_handle);
-  if (err < 0)
-    goto error;
-
-  ctx->timer_handle.flags |= UV_HANDLE_INTERNAL;
-  uv__handle_unref(&ctx->timer_handle);
-
-  err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb);
-  if (err < 0)
-    goto error;
-
-  if (handle->poll_ctx != NULL)
-    ctx->previous = (struct poll_ctx*)handle->poll_ctx;
-  handle->poll_ctx = ctx;
-  uv__handle_start(handle);
-
-  return 0;
-
-error:
-  uv__free(ctx);
-  return err;
-}
-
-
-int uv_fs_poll_stop(uv_fs_poll_t* handle) {
-  struct poll_ctx* ctx;
-
-  if (!uv_is_active((uv_handle_t*)handle))
-    return 0;
-
-  ctx = (struct poll_ctx*)handle->poll_ctx;
-  assert(ctx != NULL);
-  assert(ctx->parent_handle == handle);
-
-  /* Close the timer if it's active. If it's inactive, there's a stat request
-   * in progress and poll_cb will take care of the cleanup.
-   */
-  if (uv_is_active((uv_handle_t*)&ctx->timer_handle))
-    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
-
-  uv__handle_stop(handle);
-
-  return 0;
-}
-
-
-int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) {
-  struct poll_ctx* ctx;
-  size_t required_len;
-
-  if (!uv_is_active((uv_handle_t*)handle)) {
-    *size = 0;
-    return UV_EINVAL;
-  }
-
-  ctx = (struct poll_ctx*)handle->poll_ctx;
-  assert(ctx != NULL);
-
-  required_len = strlen(ctx->path);
-  if (required_len >= *size) {
-    *size = required_len + 1;
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, ctx->path, required_len);
-  *size = required_len;
-  buffer[required_len] = '\0';
-
-  return 0;
-}
-
-
-void uv__fs_poll_close(uv_fs_poll_t* handle) {
-  uv_fs_poll_stop(handle);
-
-  if (handle->poll_ctx == NULL)
-    uv__make_close_pending((uv_handle_t*)handle);
-}
-
-
-static void timer_cb(uv_timer_t* timer) {
-  struct poll_ctx* ctx;
-
-  ctx = container_of(timer, struct poll_ctx, timer_handle);
-  assert(ctx->parent_handle != NULL);
-  assert(ctx->parent_handle->poll_ctx == ctx);
-  ctx->start_time = uv_now(ctx->loop);
-
-  if (uv_fs_stat(ctx->loop, &ctx->fs_req, ctx->path, poll_cb))
-    abort();
-}
-
-
-static void poll_cb(uv_fs_t* req) {
-  uv_stat_t* statbuf;
-  struct poll_ctx* ctx;
-  uint64_t interval;
-  uv_fs_poll_t* handle;
-
-  ctx = container_of(req, struct poll_ctx, fs_req);
-  handle = ctx->parent_handle;
-
-  if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle))
-    goto out;
-
-  if (req->result != 0) {
-    if (ctx->busy_polling != req->result) {
-      ctx->poll_cb(ctx->parent_handle,
-                   req->result,
-                   &ctx->statbuf,
-                   &zero_statbuf);
-      ctx->busy_polling = req->result;
-    }
-    goto out;
-  }
-
-  statbuf = &req->statbuf;
-
-  if (ctx->busy_polling != 0)
-    if (ctx->busy_polling < 0 || !statbuf_eq(&ctx->statbuf, statbuf))
-      ctx->poll_cb(ctx->parent_handle, 0, &ctx->statbuf, statbuf);
-
-  ctx->statbuf = *statbuf;
-  ctx->busy_polling = 1;
-
-out:
-  uv_fs_req_cleanup(req);
-
-  if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle)) {
-    uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb);
-    return;
-  }
-
-  /* Reschedule timer, subtract the delay from doing the stat(). */
-  interval = ctx->interval;
-  interval -= (uv_now(ctx->loop) - ctx->start_time) % interval;
-
-  if (uv_timer_start(&ctx->timer_handle, timer_cb, interval, 0))
-    abort();
-}
-
-
-static void timer_close_cb(uv_handle_t* timer) {
-  struct poll_ctx* ctx;
-  struct poll_ctx* it;
-  struct poll_ctx* last;
-  uv_fs_poll_t* handle;
-
-  ctx = container_of(timer, struct poll_ctx, timer_handle);
-  handle = ctx->parent_handle;
-  if (ctx == handle->poll_ctx) {
-    handle->poll_ctx = ctx->previous;
-    if (handle->poll_ctx == NULL && uv__is_closing(handle))
-      uv__make_close_pending((uv_handle_t*)handle);
-  } else {
-    for (last = (struct poll_ctx*)handle->poll_ctx, it = last->previous;
-         it != ctx;
-         last = it, it = it->previous) {
-      assert(last->previous != NULL);
-    }
-    last->previous = ctx->previous;
-  }
-  uv__free(ctx);
-}
-
-
-static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) {
-  return a->st_ctim.tv_nsec == b->st_ctim.tv_nsec
-      && a->st_mtim.tv_nsec == b->st_mtim.tv_nsec
-      && a->st_birthtim.tv_nsec == b->st_birthtim.tv_nsec
-      && a->st_ctim.tv_sec == b->st_ctim.tv_sec
-      && a->st_mtim.tv_sec == b->st_mtim.tv_sec
-      && a->st_birthtim.tv_sec == b->st_birthtim.tv_sec
-      && a->st_size == b->st_size
-      && a->st_mode == b->st_mode
-      && a->st_uid == b->st_uid
-      && a->st_gid == b->st_gid
-      && a->st_ino == b->st_ino
-      && a->st_dev == b->st_dev
-      && a->st_flags == b->st_flags
-      && a->st_gen == b->st_gen;
-}
-
-
-#if defined(_WIN32)
-
-#include "win/internal.h"
-#include "win/handle-inl.h"
-
-void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) {
-  assert(handle->flags & UV_HANDLE_CLOSING);
-  assert(!(handle->flags & UV_HANDLE_CLOSED));
-  uv__handle_close(handle);
-}
-
-#endif /* _WIN32 */
diff --git a/wpiutil/src/main/native/libuv/src/heap-inl.h b/wpiutil/src/main/native/libuv/src/heap-inl.h
deleted file mode 100644
index 1e2ed60..0000000
--- a/wpiutil/src/main/native/libuv/src/heap-inl.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef UV_SRC_HEAP_H_
-#define UV_SRC_HEAP_H_
-
-#include <stddef.h>  /* NULL */
-
-#if defined(__GNUC__)
-# define HEAP_EXPORT(declaration) __attribute__((unused)) static declaration
-#else
-# define HEAP_EXPORT(declaration) static declaration
-#endif
-
-struct heap_node {
-  struct heap_node* left;
-  struct heap_node* right;
-  struct heap_node* parent;
-};
-
-/* A binary min heap.  The usual properties hold: the root is the lowest
- * element in the set, the height of the tree is at most log2(nodes) and
- * it's always a complete binary tree.
- *
- * The heap function try hard to detect corrupted tree nodes at the cost
- * of a minor reduction in performance.  Compile with -DNDEBUG to disable.
- */
-struct heap {
-  struct heap_node* min;
-  unsigned int nelts;
-};
-
-/* Return non-zero if a < b. */
-typedef int (*heap_compare_fn)(const struct heap_node* a,
-                               const struct heap_node* b);
-
-/* Public functions. */
-HEAP_EXPORT(void heap_init(struct heap* heap));
-HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap));
-HEAP_EXPORT(void heap_insert(struct heap* heap,
-                             struct heap_node* newnode,
-                             heap_compare_fn less_than));
-HEAP_EXPORT(void heap_remove(struct heap* heap,
-                             struct heap_node* node,
-                             heap_compare_fn less_than));
-HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than));
-
-/* Implementation follows. */
-
-HEAP_EXPORT(void heap_init(struct heap* heap)) {
-  heap->min = NULL;
-  heap->nelts = 0;
-}
-
-HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)) {
-  return heap->min;
-}
-
-/* Swap parent with child. Child moves closer to the root, parent moves away. */
-static void heap_node_swap(struct heap* heap,
-                           struct heap_node* parent,
-                           struct heap_node* child) {
-  struct heap_node* sibling;
-  struct heap_node t;
-
-  t = *parent;
-  *parent = *child;
-  *child = t;
-
-  parent->parent = child;
-  if (child->left == child) {
-    child->left = parent;
-    sibling = child->right;
-  } else {
-    child->right = parent;
-    sibling = child->left;
-  }
-  if (sibling != NULL)
-    sibling->parent = child;
-
-  if (parent->left != NULL)
-    parent->left->parent = parent;
-  if (parent->right != NULL)
-    parent->right->parent = parent;
-
-  if (child->parent == NULL)
-    heap->min = child;
-  else if (child->parent->left == parent)
-    child->parent->left = child;
-  else
-    child->parent->right = child;
-}
-
-HEAP_EXPORT(void heap_insert(struct heap* heap,
-                             struct heap_node* newnode,
-                             heap_compare_fn less_than)) {
-  struct heap_node** parent;
-  struct heap_node** child;
-  unsigned int path;
-  unsigned int n;
-  unsigned int k;
-
-  newnode->left = NULL;
-  newnode->right = NULL;
-  newnode->parent = NULL;
-
-  /* Calculate the path from the root to the insertion point.  This is a min
-   * heap so we always insert at the left-most free node of the bottom row.
-   */
-  path = 0;
-  for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2)
-    path = (path << 1) | (n & 1);
-
-  /* Now traverse the heap using the path we calculated in the previous step. */
-  parent = child = &heap->min;
-  while (k > 0) {
-    parent = child;
-    if (path & 1)
-      child = &(*child)->right;
-    else
-      child = &(*child)->left;
-    path >>= 1;
-    k -= 1;
-  }
-
-  /* Insert the new node. */
-  newnode->parent = *parent;
-  *child = newnode;
-  heap->nelts += 1;
-
-  /* Walk up the tree and check at each node if the heap property holds.
-   * It's a min heap so parent < child must be true.
-   */
-  while (newnode->parent != NULL && less_than(newnode, newnode->parent))
-    heap_node_swap(heap, newnode->parent, newnode);
-}
-
-HEAP_EXPORT(void heap_remove(struct heap* heap,
-                             struct heap_node* node,
-                             heap_compare_fn less_than)) {
-  struct heap_node* smallest;
-  struct heap_node** max;
-  struct heap_node* child;
-  unsigned int path;
-  unsigned int k;
-  unsigned int n;
-
-  if (heap->nelts == 0)
-    return;
-
-  /* Calculate the path from the min (the root) to the max, the left-most node
-   * of the bottom row.
-   */
-  path = 0;
-  for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2)
-    path = (path << 1) | (n & 1);
-
-  /* Now traverse the heap using the path we calculated in the previous step. */
-  max = &heap->min;
-  while (k > 0) {
-    if (path & 1)
-      max = &(*max)->right;
-    else
-      max = &(*max)->left;
-    path >>= 1;
-    k -= 1;
-  }
-
-  heap->nelts -= 1;
-
-  /* Unlink the max node. */
-  child = *max;
-  *max = NULL;
-
-  if (child == node) {
-    /* We're removing either the max or the last node in the tree. */
-    if (child == heap->min) {
-      heap->min = NULL;
-    }
-    return;
-  }
-
-  /* Replace the to be deleted node with the max node. */
-  child->left = node->left;
-  child->right = node->right;
-  child->parent = node->parent;
-
-  if (child->left != NULL) {
-    child->left->parent = child;
-  }
-
-  if (child->right != NULL) {
-    child->right->parent = child;
-  }
-
-  if (node->parent == NULL) {
-    heap->min = child;
-  } else if (node->parent->left == node) {
-    node->parent->left = child;
-  } else {
-    node->parent->right = child;
-  }
-
-  /* Walk down the subtree and check at each node if the heap property holds.
-   * It's a min heap so parent < child must be true.  If the parent is bigger,
-   * swap it with the smallest child.
-   */
-  for (;;) {
-    smallest = child;
-    if (child->left != NULL && less_than(child->left, smallest))
-      smallest = child->left;
-    if (child->right != NULL && less_than(child->right, smallest))
-      smallest = child->right;
-    if (smallest == child)
-      break;
-    heap_node_swap(heap, child, smallest);
-  }
-
-  /* Walk up the subtree and check that each parent is less than the node
-   * this is required, because `max` node is not guaranteed to be the
-   * actual maximum in tree
-   */
-  while (child->parent != NULL && less_than(child, child->parent))
-    heap_node_swap(heap, child->parent, child);
-}
-
-HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)) {
-  heap_remove(heap, heap->min, less_than);
-}
-
-#undef HEAP_EXPORT
-
-#endif  /* UV_SRC_HEAP_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/idna.cpp b/wpiutil/src/main/native/libuv/src/idna.cpp
deleted file mode 100644
index 6b2406c..0000000
--- a/wpiutil/src/main/native/libuv/src/idna.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* Derived from https://github.com/bnoordhuis/punycode
- * but updated to support IDNA 2008.
- */
-
-#include "uv.h"
-#include "idna.h"
-#include <string.h>
-
-static unsigned uv__utf8_decode1_slow(const char** p,
-                                      const char* pe,
-                                      unsigned a) {
-  unsigned b;
-  unsigned c;
-  unsigned d;
-  unsigned min;
-
-  if (a > 0xF7)
-    return -1;
-
-  switch (*p - pe) {
-  default:
-    if (a > 0xEF) {
-      min = 0x10000;
-      a = a & 7;
-      b = (unsigned char) *(*p)++;
-      c = (unsigned char) *(*p)++;
-      d = (unsigned char) *(*p)++;
-      break;
-    }
-    /* Fall through. */
-  case 2:
-    if (a > 0xDF) {
-      min = 0x800;
-      b = 0x80 | (a & 15);
-      c = (unsigned char) *(*p)++;
-      d = (unsigned char) *(*p)++;
-      a = 0;
-      break;
-    }
-    /* Fall through. */
-  case 1:
-    if (a > 0xBF) {
-      min = 0x80;
-      b = 0x80;
-      c = 0x80 | (a & 31);
-      d = (unsigned char) *(*p)++;
-      a = 0;
-      break;
-    }
-    return -1;  /* Invalid continuation byte. */
-  }
-
-  if (0x80 != (0xC0 & (b ^ c ^ d)))
-    return -1;  /* Invalid sequence. */
-
-  b &= 63;
-  c &= 63;
-  d &= 63;
-  a = (a << 18) | (b << 12) | (c << 6) | d;
-
-  if (a < min)
-    return -1;  /* Overlong sequence. */
-
-  if (a > 0x10FFFF)
-    return -1;  /* Four-byte sequence > U+10FFFF. */
-
-  if (a >= 0xD800 && a <= 0xDFFF)
-    return -1;  /* Surrogate pair. */
-
-  return a;
-}
-
-unsigned uv__utf8_decode1(const char** p, const char* pe) {
-  unsigned a;
-
-  a = (unsigned char) *(*p)++;
-
-  if (a < 128)
-    return a;  /* ASCII, common case. */
-
-  return uv__utf8_decode1_slow(p, pe, a);
-}
-
-#define foreach_codepoint(c, p, pe) \
-  for (; (void) (*p <= pe && (c = uv__utf8_decode1(p, pe))), *p <= pe;)
-
-static int uv__idna_toascii_label(const char* s, const char* se,
-                                  char** d, char* de) {
-  static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
-  const char* ss;
-  unsigned c = 0;
-  unsigned h;
-  unsigned k;
-  unsigned n;
-  unsigned m;
-  unsigned q;
-  unsigned t;
-  unsigned x;
-  unsigned y;
-  unsigned bias;
-  unsigned delta;
-  unsigned todo;
-  int first;
-
-  h = 0;
-  ss = s;
-  todo = 0;
-
-  foreach_codepoint(c, &s, se) {
-    if (c < 128)
-      h++;
-    else if (c == (unsigned) -1)
-      return UV_EINVAL;
-    else
-      todo++;
-  }
-
-  if (todo > 0) {
-    if (*d < de) *(*d)++ = 'x';
-    if (*d < de) *(*d)++ = 'n';
-    if (*d < de) *(*d)++ = '-';
-    if (*d < de) *(*d)++ = '-';
-  }
-
-  x = 0;
-  s = ss;
-  foreach_codepoint(c, &s, se) {
-    if (c > 127)
-      continue;
-
-    if (*d < de)
-      *(*d)++ = c;
-
-    if (++x == h)
-      break;  /* Visited all ASCII characters. */
-  }
-
-  if (todo == 0)
-    return h;
-
-  /* Only write separator when we've written ASCII characters first. */
-  if (h > 0)
-    if (*d < de)
-      *(*d)++ = '-';
-
-  n = 128;
-  bias = 72;
-  delta = 0;
-  first = 1;
-
-  while (todo > 0) {
-    m = -1;
-    s = ss;
-    foreach_codepoint(c, &s, se)
-      if (c >= n)
-        if (c < m)
-          m = c;
-
-    x = m - n;
-    y = h + 1;
-
-    if (x > ~delta / y)
-      return UV_E2BIG;  /* Overflow. */
-
-    delta += x * y;
-    n = m;
-
-    s = ss;
-    foreach_codepoint(c, &s, se) {
-      if (c < n)
-        if (++delta == 0)
-          return UV_E2BIG;  /* Overflow. */
-
-      if (c != n)
-        continue;
-
-      for (k = 36, q = delta; /* empty */; k += 36) {
-        t = 1;
-
-        if (k > bias)
-          t = k - bias;
-
-        if (t > 26)
-          t = 26;
-
-        if (q < t)
-          break;
-
-        /* TODO(bnoordhuis) Since 1 <= t <= 26 and therefore
-         * 10 <= y <= 35, we can optimize the long division
-         * into a table-based reciprocal multiplication.
-         */
-        x = q - t;
-        y = 36 - t;  /* 10 <= y <= 35 since 1 <= t <= 26. */
-        q = x / y;
-        t = t + x % y;  /* 1 <= t <= 35 because of y. */
-
-        if (*d < de)
-          *(*d)++ = alphabet[t];
-      }
-
-      if (*d < de)
-        *(*d)++ = alphabet[q];
-
-      delta /= 2;
-
-      if (first) {
-        delta /= 350;
-        first = 0;
-      }
-
-      /* No overflow check is needed because |delta| was just
-       * divided by 2 and |delta+delta >= delta + delta/h|.
-       */
-      h++;
-      delta += delta / h;
-
-      for (bias = 0; delta > 35 * 26 / 2; bias += 36)
-        delta /= 35;
-
-      bias += 36 * delta / (delta + 38);
-      delta = 0;
-      todo--;
-    }
-
-    delta++;
-    n++;
-  }
-
-  return 0;
-}
-
-#undef foreach_codepoint
-
-long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
-  const char* si;
-  const char* st;
-  unsigned c;
-  char* ds;
-  int rc;
-
-  ds = d;
-
-  for (si = s; si < se; /* empty */) {
-    st = si;
-    c = uv__utf8_decode1(&si, se);
-
-    if (c != '.')
-      if (c != 0x3002)  /* 。 */
-        if (c != 0xFF0E)  /* . */
-          if (c != 0xFF61)  /* 。 */
-            continue;
-
-    rc = uv__idna_toascii_label(s, st, &d, de);
-
-    if (rc < 0)
-      return rc;
-
-    if (d < de)
-      *d++ = '.';
-
-    s = si;
-  }
-
-  if (s < se) {
-    rc = uv__idna_toascii_label(s, se, &d, de);
-
-    if (rc < 0)
-      return rc;
-  }
-
-  if (d < de)
-    *d++ = '\0';
-
-  return d - ds;  /* Number of bytes written. */
-}
diff --git a/wpiutil/src/main/native/libuv/src/idna.h b/wpiutil/src/main/native/libuv/src/idna.h
deleted file mode 100644
index 8e0c592..0000000
--- a/wpiutil/src/main/native/libuv/src/idna.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef UV_SRC_IDNA_H_
-#define UV_SRC_IDNA_H_
-
-/* Decode a single codepoint. Returns the codepoint or UINT32_MAX on error.
- * |p| is updated on success _and_ error, i.e., bad multi-byte sequences are
- * skipped in their entirety, not just the first bad byte.
- */
-unsigned uv__utf8_decode1(const char** p, const char* pe);
-
-/* Convert a UTF-8 domain name to IDNA 2008 / Punycode. A return value >= 0
- * is the number of bytes written to |d|, including the trailing nul byte.
- * A return value < 0 is a libuv error code. |s| and |d| can not overlap.
- */
-long uv__idna_toascii(const char* s, const char* se, char* d, char* de);
-
-#endif  /* UV_SRC_IDNA_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/inet.cpp b/wpiutil/src/main/native/libuv/src/inet.cpp
deleted file mode 100644
index 167ec11..0000000
--- a/wpiutil/src/main/native/libuv/src/inet.cpp
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1996-1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "uv/stdint-msvc2008.h"
-#else
-# include <stdint.h>
-#endif
-
-#include "uv.h"
-#include "uv-common.h"
-
-#ifdef _WIN32
-#pragma warning(disable : 6001)
-#endif
-
-#define UV__INET_ADDRSTRLEN         16
-#define UV__INET6_ADDRSTRLEN        46
-
-
-static int inet_ntop4(const unsigned char *src, char *dst, size_t size);
-static int inet_ntop6(const unsigned char *src, char *dst, size_t size);
-static int inet_pton4(const char *src, unsigned char *dst);
-static int inet_pton6(const char *src, unsigned char *dst);
-
-
-int uv_inet_ntop(int af, const void* src, char* dst, size_t size) {
-  switch (af) {
-  case AF_INET:
-    return (inet_ntop4((const unsigned char*)src, dst, size));
-  case AF_INET6:
-    return (inet_ntop6((const unsigned char*)src, dst, size));
-  default:
-    return UV_EAFNOSUPPORT;
-  }
-  /* NOTREACHED */
-}
-
-
-static int inet_ntop4(const unsigned char *src, char *dst, size_t size) {
-  static const char fmt[] = "%u.%u.%u.%u";
-  char tmp[UV__INET_ADDRSTRLEN];
-  int l;
-
-  l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
-  if (l <= 0 || (size_t) l >= size) {
-    return UV_ENOSPC;
-  }
-  uv__strscpy(dst, tmp, size);
-  return 0;
-}
-
-
-static int inet_ntop6(const unsigned char *src, char *dst, size_t size) {
-  /*
-   * Note that int32_t and int16_t need only be "at least" large enough
-   * to contain a value of the specified size.  On some systems, like
-   * Crays, there is no such thing as an integer variable with 16 bits.
-   * Keep this in mind if you think this function should have been coded
-   * to use pointer overlays.  All the world's not a VAX.
-   */
-  char tmp[UV__INET6_ADDRSTRLEN], *tp;
-  struct { int base, len; } best, cur;
-  unsigned int words[sizeof(struct in6_addr) / sizeof(uint16_t)];
-  int i;
-
-  /*
-   * Preprocess:
-   *  Copy the input (bytewise) array into a wordwise array.
-   *  Find the longest run of 0x00's in src[] for :: shorthanding.
-   */
-  memset(words, '\0', sizeof words);
-  for (i = 0; i < (int) sizeof(struct in6_addr); i++)
-    words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
-  best.base = -1;
-  best.len = 0;
-  cur.base = -1;
-  cur.len = 0;
-  for (i = 0; i < (int) ARRAY_SIZE(words); i++) {
-    if (words[i] == 0) {
-      if (cur.base == -1)
-        cur.base = i, cur.len = 1;
-      else
-        cur.len++;
-    } else {
-      if (cur.base != -1) {
-        if (best.base == -1 || cur.len > best.len)
-          best = cur;
-        cur.base = -1;
-      }
-    }
-  }
-  if (cur.base != -1) {
-    if (best.base == -1 || cur.len > best.len)
-      best = cur;
-  }
-  if (best.base != -1 && best.len < 2)
-    best.base = -1;
-
-  /*
-   * Format the result.
-   */
-  tp = tmp;
-  for (i = 0; i < (int) ARRAY_SIZE(words); i++) {
-    /* Are we inside the best run of 0x00's? */
-    if (best.base != -1 && i >= best.base &&
-        i < (best.base + best.len)) {
-      if (i == best.base)
-        *tp++ = ':';
-      continue;
-    }
-    /* Are we following an initial run of 0x00s or any real hex? */
-    if (i != 0)
-      *tp++ = ':';
-    /* Is this address an encapsulated IPv4? */
-    if (i == 6 && best.base == 0 && (best.len == 6 ||
-        (best.len == 7 && words[7] != 0x0001) ||
-        (best.len == 5 && words[5] == 0xffff))) {
-      int err = inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp));
-      if (err)
-        return err;
-      tp += strlen(tp);
-      break;
-    }
-    tp += sprintf(tp, "%x", words[i]);
-  }
-  /* Was it a trailing run of 0x00's? */
-  if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words))
-    *tp++ = ':';
-  *tp++ = '\0';
-  if (UV_E2BIG == uv__strscpy(dst, tmp, size))
-    return UV_ENOSPC;
-  return 0;
-}
-
-
-int uv_inet_pton(int af, const char* src, void* dst) {
-  if (src == NULL || dst == NULL)
-    return UV_EINVAL;
-
-  switch (af) {
-  case AF_INET:
-    return (inet_pton4(src, (unsigned char*)dst));
-  case AF_INET6: {
-    int len;
-    char tmp[UV__INET6_ADDRSTRLEN], *s;
-    const char *p;
-    s = (char*) src;
-    p = strchr(src, '%');
-    if (p != NULL) {
-      s = tmp;
-      len = p - src;
-      if (len > UV__INET6_ADDRSTRLEN-1)
-        return UV_EINVAL;
-      memcpy(s, src, len);
-      s[len] = '\0';
-    }
-    return inet_pton6(s, (unsigned char*)dst);
-  }
-  default:
-    return UV_EAFNOSUPPORT;
-  }
-  /* NOTREACHED */
-}
-
-
-static int inet_pton4(const char *src, unsigned char *dst) {
-  static const char digits[] = "0123456789";
-  int saw_digit, octets, ch;
-  unsigned char tmp[sizeof(struct in_addr)], *tp;
-
-  saw_digit = 0;
-  octets = 0;
-  *(tp = tmp) = 0;
-  while ((ch = *src++) != '\0') {
-    const char *pch;
-
-    if ((pch = strchr(digits, ch)) != NULL) {
-      unsigned int nw = *tp * 10 + (pch - digits);
-
-      if (saw_digit && *tp == 0)
-        return UV_EINVAL;
-      if (nw > 255)
-        return UV_EINVAL;
-      *tp = nw;
-      if (!saw_digit) {
-        if (++octets > 4)
-          return UV_EINVAL;
-        saw_digit = 1;
-      }
-    } else if (ch == '.' && saw_digit) {
-      if (octets == 4)
-        return UV_EINVAL;
-      *++tp = 0;
-      saw_digit = 0;
-    } else
-      return UV_EINVAL;
-  }
-  if (octets < 4)
-    return UV_EINVAL;
-  memcpy(dst, tmp, sizeof(struct in_addr));
-  return 0;
-}
-
-
-static int inet_pton6(const char *src, unsigned char *dst) {
-  static const char xdigits_l[] = "0123456789abcdef",
-                    xdigits_u[] = "0123456789ABCDEF";
-  unsigned char tmp[sizeof(struct in6_addr)], *tp, *endp, *colonp;
-  const char *xdigits, *curtok;
-  int ch, seen_xdigits;
-  unsigned int val;
-
-  memset((tp = tmp), '\0', sizeof tmp);
-  endp = tp + sizeof tmp;
-  colonp = NULL;
-  /* Leading :: requires some special handling. */
-  if (*src == ':')
-    if (*++src != ':')
-      return UV_EINVAL;
-  curtok = src;
-  seen_xdigits = 0;
-  val = 0;
-  while ((ch = *src++) != '\0') {
-    const char *pch;
-
-    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
-      pch = strchr((xdigits = xdigits_u), ch);
-    if (pch != NULL) {
-      val <<= 4;
-      val |= (pch - xdigits);
-      if (++seen_xdigits > 4)
-        return UV_EINVAL;
-      continue;
-    }
-    if (ch == ':') {
-      curtok = src;
-      if (!seen_xdigits) {
-        if (colonp)
-          return UV_EINVAL;
-        colonp = tp;
-        continue;
-      } else if (*src == '\0') {
-        return UV_EINVAL;
-      }
-      if (tp + sizeof(uint16_t) > endp)
-        return UV_EINVAL;
-      *tp++ = (unsigned char) (val >> 8) & 0xff;
-      *tp++ = (unsigned char) val & 0xff;
-      seen_xdigits = 0;
-      val = 0;
-      continue;
-    }
-    if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) {
-      int err = inet_pton4(curtok, tp);
-      if (err == 0) {
-        tp += sizeof(struct in_addr);
-        seen_xdigits = 0;
-        break;  /*%< '\\0' was seen by inet_pton4(). */
-      }
-    }
-    return UV_EINVAL;
-  }
-  if (seen_xdigits) {
-    if (tp + sizeof(uint16_t) > endp)
-      return UV_EINVAL;
-    *tp++ = (unsigned char) (val >> 8) & 0xff;
-    *tp++ = (unsigned char) val & 0xff;
-  }
-  if (colonp != NULL) {
-    /*
-     * Since some memmove()'s erroneously fail to handle
-     * overlapping regions, we'll do the shift by hand.
-     */
-    const int n = tp - colonp;
-    int i;
-
-    if (tp == endp)
-      return UV_EINVAL;
-    for (i = 1; i <= n; i++) {
-      endp[- i] = colonp[n - i];
-      colonp[n - i] = 0;
-    }
-    tp = endp;
-  }
-  if (tp != endp)
-    return UV_EINVAL;
-  memcpy(dst, tmp, sizeof tmp);
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/queue.h b/wpiutil/src/main/native/libuv/src/queue.h
deleted file mode 100644
index ff3540a..0000000
--- a/wpiutil/src/main/native/libuv/src/queue.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef QUEUE_H_
-#define QUEUE_H_
-
-#include <stddef.h>
-
-typedef void *QUEUE[2];
-
-/* Private macros. */
-#define QUEUE_NEXT(q)       (*(QUEUE **) &((*(q))[0]))
-#define QUEUE_PREV(q)       (*(QUEUE **) &((*(q))[1]))
-#define QUEUE_PREV_NEXT(q)  (QUEUE_NEXT(QUEUE_PREV(q)))
-#define QUEUE_NEXT_PREV(q)  (QUEUE_PREV(QUEUE_NEXT(q)))
-
-/* Public macros. */
-#define QUEUE_DATA(ptr, type, field)                                          \
-  ((type *) ((char *) (ptr) - offsetof(type, field)))
-
-/* Important note: mutating the list while QUEUE_FOREACH is
- * iterating over its elements results in undefined behavior.
- */
-#define QUEUE_FOREACH(q, h)                                                   \
-  for ((q) = QUEUE_NEXT(h); (q) != (h); (q) = QUEUE_NEXT(q))
-
-#define QUEUE_EMPTY(q)                                                        \
-  ((const QUEUE *) (q) == (const QUEUE *) QUEUE_NEXT(q))
-
-#define QUEUE_HEAD(q)                                                         \
-  (QUEUE_NEXT(q))
-
-#define QUEUE_INIT(q)                                                         \
-  do {                                                                        \
-    QUEUE_NEXT(q) = (q);                                                      \
-    QUEUE_PREV(q) = (q);                                                      \
-  }                                                                           \
-  while (0)
-
-#define QUEUE_ADD(h, n)                                                       \
-  do {                                                                        \
-    QUEUE_PREV_NEXT(h) = QUEUE_NEXT(n);                                       \
-    QUEUE_NEXT_PREV(n) = QUEUE_PREV(h);                                       \
-    QUEUE_PREV(h) = QUEUE_PREV(n);                                            \
-    QUEUE_PREV_NEXT(h) = (h);                                                 \
-  }                                                                           \
-  while (0)
-
-#define QUEUE_SPLIT(h, q, n)                                                  \
-  do {                                                                        \
-    QUEUE_PREV(n) = QUEUE_PREV(h);                                            \
-    QUEUE_PREV_NEXT(n) = (n);                                                 \
-    QUEUE_NEXT(n) = (q);                                                      \
-    QUEUE_PREV(h) = QUEUE_PREV(q);                                            \
-    QUEUE_PREV_NEXT(h) = (h);                                                 \
-    QUEUE_PREV(q) = (n);                                                      \
-  }                                                                           \
-  while (0)
-
-#define QUEUE_MOVE(h, n)                                                      \
-  do {                                                                        \
-    if (QUEUE_EMPTY(h))                                                       \
-      QUEUE_INIT(n);                                                          \
-    else {                                                                    \
-      QUEUE* q = QUEUE_HEAD(h);                                               \
-      QUEUE_SPLIT(h, q, n);                                                   \
-    }                                                                         \
-  }                                                                           \
-  while (0)
-
-#define QUEUE_INSERT_HEAD(h, q)                                               \
-  do {                                                                        \
-    QUEUE_NEXT(q) = QUEUE_NEXT(h);                                            \
-    QUEUE_PREV(q) = (h);                                                      \
-    QUEUE_NEXT_PREV(q) = (q);                                                 \
-    QUEUE_NEXT(h) = (q);                                                      \
-  }                                                                           \
-  while (0)
-
-#define QUEUE_INSERT_TAIL(h, q)                                               \
-  do {                                                                        \
-    QUEUE_NEXT(q) = (h);                                                      \
-    QUEUE_PREV(q) = QUEUE_PREV(h);                                            \
-    QUEUE_PREV_NEXT(q) = (q);                                                 \
-    QUEUE_PREV(h) = (q);                                                      \
-  }                                                                           \
-  while (0)
-
-#define QUEUE_REMOVE(q)                                                       \
-  do {                                                                        \
-    QUEUE_PREV_NEXT(q) = QUEUE_NEXT(q);                                       \
-    QUEUE_NEXT_PREV(q) = QUEUE_PREV(q);                                       \
-  }                                                                           \
-  while (0)
-
-#endif /* QUEUE_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/strscpy.cpp b/wpiutil/src/main/native/libuv/src/strscpy.cpp
deleted file mode 100644
index 4a9e863..0000000
--- a/wpiutil/src/main/native/libuv/src/strscpy.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "strscpy.h"
-#include <limits.h>  /* SSIZE_MAX */
-
-ssize_t uv__strscpy(char* d, const char* s, size_t n) {
-  size_t i;
-
-  for (i = 0; i < n; i++)
-    if ('\0' == (d[i] = s[i]))
-      return i > SSIZE_MAX ? (ssize_t) UV_E2BIG : (ssize_t) i;
-
-  if (i == 0)
-    return 0;
-
-  d[--i] = '\0';
-
-  return UV_E2BIG;
-}
diff --git a/wpiutil/src/main/native/libuv/src/strscpy.h b/wpiutil/src/main/native/libuv/src/strscpy.h
deleted file mode 100644
index fbe0a39..0000000
--- a/wpiutil/src/main/native/libuv/src/strscpy.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef UV_STRSCPY_H_
-#define UV_STRSCPY_H_
-
-/* Include uv.h for its definitions of size_t and ssize_t.
- * size_t can be obtained directly from <stddef.h> but ssize_t requires
- * some hoop jumping on Windows that I didn't want to duplicate here.
- */
-#include "uv.h"
-
-/* Copies up to |n-1| bytes from |d| to |s| and always zero-terminates
- * the result, except when |n==0|. Returns the number of bytes copied
- * or UV_E2BIG if |d| is too small.
- *
- * See https://www.kernel.org/doc/htmldocs/kernel-api/API-strscpy.html
- */
-ssize_t uv__strscpy(char* d, const char* s, size_t n);
-
-#endif  /* UV_STRSCPY_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/threadpool.cpp b/wpiutil/src/main/native/libuv/src/threadpool.cpp
deleted file mode 100644
index 515bf40..0000000
--- a/wpiutil/src/main/native/libuv/src/threadpool.cpp
+++ /dev/null
@@ -1,388 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv-common.h"
-
-#if !defined(_WIN32)
-# include "unix/internal.h"
-#endif
-
-#include <stdlib.h>
-
-#ifdef _WIN32
-#pragma warning(disable: 6001 6011)
-#endif
-
-#define MAX_THREADPOOL_SIZE 1024
-
-static uv_once_t once = UV_ONCE_INIT;
-static uv_cond_t cond;
-static uv_mutex_t mutex;
-static unsigned int idle_threads;
-static unsigned int slow_io_work_running;
-static unsigned int nthreads;
-static uv_thread_t* threads;
-static uv_thread_t default_threads[4];
-static QUEUE exit_message;
-static QUEUE wq;
-static QUEUE run_slow_work_message;
-static QUEUE slow_io_pending_wq;
-
-static unsigned int slow_work_thread_threshold(void) {
-  return (nthreads + 1) / 2;
-}
-
-static void uv__cancelled(struct uv__work* w) {
-  abort();
-}
-
-
-/* To avoid deadlock with uv_cancel() it's crucial that the worker
- * never holds the global mutex and the loop-local mutex at the same time.
- */
-static void worker(void* arg) {
-  struct uv__work* w;
-  QUEUE* q;
-  int is_slow_work;
-
-  uv_sem_post((uv_sem_t*) arg);
-  arg = NULL;
-
-  uv_mutex_lock(&mutex);
-  for (;;) {
-    /* `mutex` should always be locked at this point. */
-
-    /* Keep waiting while either no work is present or only slow I/O
-       and we're at the threshold for that. */
-    while (QUEUE_EMPTY(&wq) ||
-           (QUEUE_HEAD(&wq) == &run_slow_work_message &&
-            QUEUE_NEXT(&run_slow_work_message) == &wq &&
-            slow_io_work_running >= slow_work_thread_threshold())) {
-      idle_threads += 1;
-      uv_cond_wait(&cond, &mutex);
-      idle_threads -= 1;
-    }
-
-    q = QUEUE_HEAD(&wq);
-    if (q == &exit_message) {
-      uv_cond_signal(&cond);
-      uv_mutex_unlock(&mutex);
-      break;
-    }
-
-    QUEUE_REMOVE(q);
-    QUEUE_INIT(q);  /* Signal uv_cancel() that the work req is executing. */
-
-    is_slow_work = 0;
-    if (q == &run_slow_work_message) {
-      /* If we're at the slow I/O threshold, re-schedule until after all
-         other work in the queue is done. */
-      if (slow_io_work_running >= slow_work_thread_threshold()) {
-        QUEUE_INSERT_TAIL(&wq, q);
-        continue;
-      }
-
-      /* If we encountered a request to run slow I/O work but there is none
-         to run, that means it's cancelled => Start over. */
-      if (QUEUE_EMPTY(&slow_io_pending_wq))
-        continue;
-
-      is_slow_work = 1;
-      slow_io_work_running++;
-
-      q = QUEUE_HEAD(&slow_io_pending_wq);
-      QUEUE_REMOVE(q);
-      QUEUE_INIT(q);
-
-      /* If there is more slow I/O work, schedule it to be run as well. */
-      if (!QUEUE_EMPTY(&slow_io_pending_wq)) {
-        QUEUE_INSERT_TAIL(&wq, &run_slow_work_message);
-        if (idle_threads > 0)
-          uv_cond_signal(&cond);
-      }
-    }
-
-    uv_mutex_unlock(&mutex);
-
-    w = QUEUE_DATA(q, struct uv__work, wq);
-    w->work(w);
-
-    uv_mutex_lock(&w->loop->wq_mutex);
-    w->work = NULL;  /* Signal uv_cancel() that the work req is done
-                        executing. */
-    QUEUE_INSERT_TAIL(&w->loop->wq, &w->wq);
-    uv_async_send(&w->loop->wq_async);
-    uv_mutex_unlock(&w->loop->wq_mutex);
-
-    /* Lock `mutex` since that is expected at the start of the next
-     * iteration. */
-    uv_mutex_lock(&mutex);
-    if (is_slow_work) {
-      /* `slow_io_work_running` is protected by `mutex`. */
-      slow_io_work_running--;
-    }
-  }
-}
-
-
-static void post(QUEUE* q, enum uv__work_kind kind) {
-  uv_mutex_lock(&mutex);
-  if (kind == UV__WORK_SLOW_IO) {
-    /* Insert into a separate queue. */
-    QUEUE_INSERT_TAIL(&slow_io_pending_wq, q);
-    if (!QUEUE_EMPTY(&run_slow_work_message)) {
-      /* Running slow I/O tasks is already scheduled => Nothing to do here.
-         The worker that runs said other task will schedule this one as well. */
-      uv_mutex_unlock(&mutex);
-      return;
-    }
-    q = &run_slow_work_message;
-  }
-
-  QUEUE_INSERT_TAIL(&wq, q);
-  if (idle_threads > 0)
-    uv_cond_signal(&cond);
-  uv_mutex_unlock(&mutex);
-}
-
-
-#ifndef _WIN32
-UV_DESTRUCTOR(static void cleanup(void)) {
-  unsigned int i;
-
-  if (nthreads == 0)
-    return;
-
-  post(&exit_message, UV__WORK_CPU);
-
-  for (i = 0; i < nthreads; i++)
-    if (uv_thread_join(threads + i))
-      abort();
-
-  if (threads != default_threads)
-    uv__free(threads);
-
-  uv_mutex_destroy(&mutex);
-  uv_cond_destroy(&cond);
-
-  threads = NULL;
-  nthreads = 0;
-}
-#endif
-
-
-static void init_threads(void) {
-  unsigned int i;
-  const char* val;
-  uv_sem_t sem;
-
-  nthreads = ARRAY_SIZE(default_threads);
-  val = getenv("UV_THREADPOOL_SIZE");
-  if (val != NULL)
-    nthreads = atoi(val);
-  if (nthreads == 0)
-    nthreads = 1;
-  if (nthreads > MAX_THREADPOOL_SIZE)
-    nthreads = MAX_THREADPOOL_SIZE;
-
-  threads = default_threads;
-  if (nthreads > ARRAY_SIZE(default_threads)) {
-    threads = (uv_thread_t*)uv__malloc(nthreads * sizeof(threads[0]));
-    if (threads == NULL) {
-      nthreads = ARRAY_SIZE(default_threads);
-      threads = default_threads;
-    }
-  }
-
-  if (uv_cond_init(&cond))
-    abort();
-
-  if (uv_mutex_init(&mutex))
-    abort();
-
-  QUEUE_INIT(&wq);
-  QUEUE_INIT(&slow_io_pending_wq);
-  QUEUE_INIT(&run_slow_work_message);
-
-  if (uv_sem_init(&sem, 0))
-    abort();
-
-  for (i = 0; i < nthreads; i++)
-    if (uv_thread_create(threads + i, worker, &sem))
-      abort();
-
-  for (i = 0; i < nthreads; i++)
-    uv_sem_wait(&sem);
-
-  uv_sem_destroy(&sem);
-}
-
-
-#ifndef _WIN32
-static void reset_once(void) {
-  uv_once_t child_once = UV_ONCE_INIT;
-  memcpy(&once, &child_once, sizeof(child_once));
-}
-#endif
-
-
-static void init_once(void) {
-#ifndef _WIN32
-  /* Re-initialize the threadpool after fork.
-   * Note that this discards the global mutex and condition as well
-   * as the work queue.
-   */
-  if (pthread_atfork(NULL, NULL, &reset_once))
-    abort();
-#endif
-  init_threads();
-}
-
-
-void uv__work_submit(uv_loop_t* loop,
-                     struct uv__work* w,
-                     enum uv__work_kind kind,
-                     void (*work)(struct uv__work* w),
-                     void (*done)(struct uv__work* w, int status)) {
-  uv_once(&once, init_once);
-  w->loop = loop;
-  w->work = work;
-  w->done = done;
-  post(&w->wq, kind);
-}
-
-
-static int uv__work_cancel(uv_loop_t* loop, uv_req_t* req, struct uv__work* w) {
-  int cancelled;
-
-  uv_mutex_lock(&mutex);
-  uv_mutex_lock(&w->loop->wq_mutex);
-
-  cancelled = !QUEUE_EMPTY(&w->wq) && w->work != NULL;
-  if (cancelled)
-    QUEUE_REMOVE(&w->wq);
-
-  uv_mutex_unlock(&w->loop->wq_mutex);
-  uv_mutex_unlock(&mutex);
-
-  if (!cancelled)
-    return UV_EBUSY;
-
-  w->work = uv__cancelled;
-  uv_mutex_lock(&loop->wq_mutex);
-  QUEUE_INSERT_TAIL(&loop->wq, &w->wq);
-  uv_async_send(&loop->wq_async);
-  uv_mutex_unlock(&loop->wq_mutex);
-
-  return 0;
-}
-
-
-void uv__work_done(uv_async_t* handle) {
-  struct uv__work* w;
-  uv_loop_t* loop;
-  QUEUE* q;
-  QUEUE wq;
-  int err;
-
-  loop = container_of(handle, uv_loop_t, wq_async);
-  uv_mutex_lock(&loop->wq_mutex);
-  QUEUE_MOVE(&loop->wq, &wq);
-  uv_mutex_unlock(&loop->wq_mutex);
-
-  while (!QUEUE_EMPTY(&wq)) {
-    q = QUEUE_HEAD(&wq);
-    QUEUE_REMOVE(q);
-
-    w = container_of(q, struct uv__work, wq);
-    err = (w->work == uv__cancelled) ? UV_ECANCELED : 0;
-    w->done(w, err);
-  }
-}
-
-
-static void uv__queue_work(struct uv__work* w) {
-  uv_work_t* req = container_of(w, uv_work_t, work_req);
-
-  req->work_cb(req);
-}
-
-
-static void uv__queue_done(struct uv__work* w, int err) {
-  uv_work_t* req;
-
-  req = container_of(w, uv_work_t, work_req);
-  uv__req_unregister(req->loop, req);
-
-  if (req->after_work_cb == NULL)
-    return;
-
-  req->after_work_cb(req, err);
-}
-
-
-int uv_queue_work(uv_loop_t* loop,
-                  uv_work_t* req,
-                  uv_work_cb work_cb,
-                  uv_after_work_cb after_work_cb) {
-  if (work_cb == NULL)
-    return UV_EINVAL;
-
-  uv__req_init(loop, req, UV_WORK);
-  req->loop = loop;
-  req->work_cb = work_cb;
-  req->after_work_cb = after_work_cb;
-  uv__work_submit(loop,
-                  &req->work_req,
-                  UV__WORK_CPU,
-                  uv__queue_work,
-                  uv__queue_done);
-  return 0;
-}
-
-
-int uv_cancel(uv_req_t* req) {
-  struct uv__work* wreq;
-  uv_loop_t* loop;
-
-  switch (req->type) {
-  case UV_FS:
-    loop =  ((uv_fs_t*) req)->loop;
-    wreq = &((uv_fs_t*) req)->work_req;
-    break;
-  case UV_GETADDRINFO:
-    loop =  ((uv_getaddrinfo_t*) req)->loop;
-    wreq = &((uv_getaddrinfo_t*) req)->work_req;
-    break;
-  case UV_GETNAMEINFO:
-    loop = ((uv_getnameinfo_t*) req)->loop;
-    wreq = &((uv_getnameinfo_t*) req)->work_req;
-    break;
-  case UV_WORK:
-    loop =  ((uv_work_t*) req)->loop;
-    wreq = &((uv_work_t*) req)->work_req;
-    break;
-  default:
-    return UV_EINVAL;
-  }
-
-  return uv__work_cancel(loop, req, wreq);
-}
diff --git a/wpiutil/src/main/native/libuv/src/timer.cpp b/wpiutil/src/main/native/libuv/src/timer.cpp
deleted file mode 100644
index dd78bcb..0000000
--- a/wpiutil/src/main/native/libuv/src/timer.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "uv-common.h"
-#include "heap-inl.h"
-
-#include <assert.h>
-#include <limits.h>
-
-
-static struct heap *timer_heap(const uv_loop_t* loop) {
-#ifdef _WIN32
-  return (struct heap*) loop->timer_heap;
-#else
-  return (struct heap*) &loop->timer_heap;
-#endif
-}
-
-
-static int timer_less_than(const struct heap_node* ha,
-                           const struct heap_node* hb) {
-  const uv_timer_t* a;
-  const uv_timer_t* b;
-
-  a = container_of(ha, uv_timer_t, heap_node);
-  b = container_of(hb, uv_timer_t, heap_node);
-
-  if (a->timeout < b->timeout)
-    return 1;
-  if (b->timeout < a->timeout)
-    return 0;
-
-  /* Compare start_id when both have the same timeout. start_id is
-   * allocated with loop->timer_counter in uv_timer_start().
-   */
-  if (a->start_id < b->start_id)
-    return 1;
-  if (b->start_id < a->start_id)
-    return 0;
-
-  return 0;
-}
-
-
-int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
-  uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
-  handle->timer_cb = NULL;
-  handle->repeat = 0;
-  return 0;
-}
-
-
-int uv_timer_start(uv_timer_t* handle,
-                   uv_timer_cb cb,
-                   uint64_t timeout,
-                   uint64_t repeat) {
-  uint64_t clamped_timeout;
-
-  if (cb == NULL)
-    return UV_EINVAL;
-
-  if (uv__is_active(handle))
-    uv_timer_stop(handle);
-
-  clamped_timeout = handle->loop->time + timeout;
-  if (clamped_timeout < timeout)
-    clamped_timeout = (uint64_t) -1;
-
-  handle->timer_cb = cb;
-  handle->timeout = clamped_timeout;
-  handle->repeat = repeat;
-  /* start_id is the second index to be compared in uv__timer_cmp() */
-  handle->start_id = handle->loop->timer_counter++;
-
-  heap_insert(timer_heap(handle->loop),
-              (struct heap_node*) &handle->heap_node,
-              timer_less_than);
-  uv__handle_start(handle);
-
-  return 0;
-}
-
-
-int uv_timer_stop(uv_timer_t* handle) {
-  if (!uv__is_active(handle))
-    return 0;
-
-  heap_remove(timer_heap(handle->loop),
-              (struct heap_node*) &handle->heap_node,
-              timer_less_than);
-  uv__handle_stop(handle);
-
-  return 0;
-}
-
-
-int uv_timer_again(uv_timer_t* handle) {
-  if (handle->timer_cb == NULL)
-    return UV_EINVAL;
-
-  if (handle->repeat) {
-    uv_timer_stop(handle);
-    uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat);
-  }
-
-  return 0;
-}
-
-
-void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) {
-  handle->repeat = repeat;
-}
-
-
-uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
-  return handle->repeat;
-}
-
-
-int uv__next_timeout(const uv_loop_t* loop) {
-  const struct heap_node* heap_node;
-  const uv_timer_t* handle;
-  uint64_t diff;
-
-  heap_node = heap_min(timer_heap(loop));
-  if (heap_node == NULL)
-    return -1; /* block indefinitely */
-
-  handle = container_of(heap_node, uv_timer_t, heap_node);
-  if (handle->timeout <= loop->time)
-    return 0;
-
-  diff = handle->timeout - loop->time;
-  if (diff > INT_MAX)
-    diff = INT_MAX;
-
-  return (int) diff;
-}
-
-
-void uv__run_timers(uv_loop_t* loop) {
-  struct heap_node* heap_node;
-  uv_timer_t* handle;
-
-  for (;;) {
-    heap_node = heap_min(timer_heap(loop));
-    if (heap_node == NULL)
-      break;
-
-    handle = container_of(heap_node, uv_timer_t, heap_node);
-    if (handle->timeout > loop->time)
-      break;
-
-    uv_timer_stop(handle);
-    uv_timer_again(handle);
-    handle->timer_cb(handle);
-  }
-}
-
-
-void uv__timer_close(uv_timer_t* handle) {
-  uv_timer_stop(handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/android-ifaddrs.cpp b/wpiutil/src/main/native/libuv/src/unix/android-ifaddrs.cpp
deleted file mode 100644
index ab6b029..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/android-ifaddrs.cpp
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
-Copyright (c) 2013, Kenneth MacKay
-Copyright (c) 2014, Emergya (Cloud4all, FP7/2007-2013 grant agreement #289016)
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "uv/android-ifaddrs.h"
-#include "uv-common.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <net/if_arp.h>
-#include <netinet/in.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
-typedef struct NetlinkList
-{
-    struct NetlinkList *m_next;
-    struct nlmsghdr *m_data;
-    unsigned int m_size;
-} NetlinkList;
-
-static int netlink_socket(pid_t *p_pid)
-{
-    struct sockaddr_nl l_addr;
-    socklen_t l_len;
-
-    int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-    if(l_socket < 0)
-    {
-        return -1;
-    }
-
-    memset(&l_addr, 0, sizeof(l_addr));
-    l_addr.nl_family = AF_NETLINK;
-    if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
-    {
-        close(l_socket);
-        return -1;
-    }
-
-    l_len = sizeof(l_addr);
-    if(getsockname(l_socket, (struct sockaddr *)&l_addr, &l_len) < 0)
-    {
-        close(l_socket);
-        return -1;
-    }
-    *p_pid = l_addr.nl_pid;
-
-    return l_socket;
-}
-
-static int netlink_send(int p_socket, int p_request)
-{
-    char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
-
-    struct nlmsghdr *l_hdr;
-    struct rtgenmsg *l_msg;
-    struct sockaddr_nl l_addr;
-
-    memset(l_buffer, 0, sizeof(l_buffer));
-
-    l_hdr = (struct nlmsghdr *)l_buffer;
-    l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
-
-    l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
-    l_hdr->nlmsg_type = p_request;
-    l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
-    l_hdr->nlmsg_pid = 0;
-    l_hdr->nlmsg_seq = p_socket;
-    l_msg->rtgen_family = AF_UNSPEC;
-
-    memset(&l_addr, 0, sizeof(l_addr));
-    l_addr.nl_family = AF_NETLINK;
-    return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
-}
-
-static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
-{
-    struct sockaddr_nl l_addr;
-    struct msghdr l_msg;
-
-    struct iovec l_iov;
-    l_iov.iov_base = p_buffer;
-    l_iov.iov_len = p_len;
-
-    for(;;)
-    {
-        int l_result;
-        l_msg.msg_name = (void *)&l_addr;
-        l_msg.msg_namelen = sizeof(l_addr);
-        l_msg.msg_iov = &l_iov;
-        l_msg.msg_iovlen = 1;
-        l_msg.msg_control = NULL;
-        l_msg.msg_controllen = 0;
-        l_msg.msg_flags = 0;
-        l_result = recvmsg(p_socket, &l_msg, 0);
-
-        if(l_result < 0)
-        {
-            if(errno == EINTR)
-            {
-                continue;
-            }
-            return -2;
-        }
-
-        /* Buffer was too small */
-        if(l_msg.msg_flags & MSG_TRUNC)
-        {
-            return -1;
-        }
-        return l_result;
-    }
-}
-
-static struct nlmsghdr *getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done)
-{
-    size_t l_size = 4096;
-    void *l_buffer = NULL;
-
-    for(;;)
-    {
-        int l_read;
-
-        uv__free(l_buffer);
-        l_buffer = uv__malloc(l_size);
-        if (l_buffer == NULL)
-        {
-            return NULL;
-        }
-
-        l_read = netlink_recv(p_socket, l_buffer, l_size);
-        *p_size = l_read;
-        if(l_read == -2)
-        {
-            uv__free(l_buffer);
-            return NULL;
-        }
-        if(l_read >= 0)
-        {
-            struct nlmsghdr *l_hdr;
-            for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
-            {
-                if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
-                {
-                    continue;
-                }
-
-                if(l_hdr->nlmsg_type == NLMSG_DONE)
-                {
-                    *p_done = 1;
-                    break;
-                }
-
-                if(l_hdr->nlmsg_type == NLMSG_ERROR)
-                {
-                    uv__free(l_buffer);
-                    return NULL;
-                }
-            }
-            return l_buffer;
-        }
-
-        l_size *= 2;
-    }
-}
-
-static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
-{
-    NetlinkList *l_item = (NetlinkList*)uv__malloc(sizeof(NetlinkList));
-    if (l_item == NULL)
-    {
-        return NULL;
-    }
-
-    l_item->m_next = NULL;
-    l_item->m_data = p_data;
-    l_item->m_size = p_size;
-    return l_item;
-}
-
-static void freeResultList(NetlinkList *p_list)
-{
-    NetlinkList *l_cur;
-    while(p_list)
-    {
-        l_cur = p_list;
-        p_list = p_list->m_next;
-        uv__free(l_cur->m_data);
-        uv__free(l_cur);
-    }
-}
-
-static NetlinkList *getResultList(int p_socket, int p_request, pid_t p_pid)
-{
-    int l_size;
-    int l_done;
-    NetlinkList *l_list;
-    NetlinkList *l_end;
-
-    if(netlink_send(p_socket, p_request) < 0)
-    {
-        return NULL;
-    }
-
-    l_list = NULL;
-    l_end = NULL;
-
-    l_done = 0;
-    while(!l_done)
-    {
-        NetlinkList *l_item;
-
-        struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, p_pid, &l_size, &l_done);
-        /* Error */
-        if(!l_hdr)
-        {
-            freeResultList(l_list);
-            return NULL;
-        }
-
-        l_item = newListItem(l_hdr, l_size);
-        if (!l_item)
-        {
-            freeResultList(l_list);
-            return NULL;
-        }
-        if(!l_list)
-        {
-            l_list = l_item;
-        }
-        else
-        {
-            l_end->m_next = l_item;
-        }
-        l_end = l_item;
-    }
-    return l_list;
-}
-
-static size_t maxSize(size_t a, size_t b)
-{
-    return (a > b ? a : b);
-}
-
-static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
-{
-    switch(p_family)
-    {
-        case AF_INET:
-            return sizeof(struct sockaddr_in);
-        case AF_INET6:
-            return sizeof(struct sockaddr_in6);
-        case AF_PACKET:
-            return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
-        default:
-            return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
-    }
-}
-
-static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
-{
-    switch(p_family)
-    {
-        case AF_INET:
-            memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
-            break;
-        case AF_INET6:
-            memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
-            break;
-        case AF_PACKET:
-            memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
-            ((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
-            break;
-        default:
-            memcpy(p_dest->sa_data, p_data, p_size);
-            break;
-    }
-    p_dest->sa_family = p_family;
-}
-
-static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
-{
-    if(!*p_resultList)
-    {
-        *p_resultList = p_entry;
-    }
-    else
-    {
-        struct ifaddrs *l_cur = *p_resultList;
-        while(l_cur->ifa_next)
-        {
-            l_cur = l_cur->ifa_next;
-        }
-        l_cur->ifa_next = p_entry;
-    }
-}
-
-static int interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList)
-{
-    struct ifaddrs *l_entry;
-
-    char *l_index;
-    char *l_name;
-    char *l_addr;
-    char *l_data;
-
-    struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
-
-    size_t l_nameSize = 0;
-    size_t l_addrSize = 0;
-    size_t l_dataSize = 0;
-
-    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
-    struct rtattr *l_rta;
-    for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
-    {
-        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
-        switch(l_rta->rta_type)
-        {
-            case IFLA_ADDRESS:
-            case IFLA_BROADCAST:
-                l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
-                break;
-            case IFLA_IFNAME:
-                l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
-                break;
-            case IFLA_STATS:
-                l_dataSize += NLMSG_ALIGN(l_rtaSize);
-                break;
-            default:
-                break;
-        }
-    }
-
-    l_entry = (struct ifaddrs*)uv__malloc(sizeof(struct ifaddrs) + sizeof(int) + l_nameSize + l_addrSize + l_dataSize);
-    if (l_entry == NULL)
-    {
-        return -1;
-    }
-    memset(l_entry, 0, sizeof(struct ifaddrs));
-    l_entry->ifa_name = "";
-
-    l_index = ((char *)l_entry) + sizeof(struct ifaddrs);
-    l_name = l_index + sizeof(int);
-    l_addr = l_name + l_nameSize;
-    l_data = l_addr + l_addrSize;
-
-    /* Save the interface index so we can look it up when handling the
-     * addresses.
-     */
-    memcpy(l_index, &l_info->ifi_index, sizeof(int));
-
-    l_entry->ifa_flags = l_info->ifi_flags;
-
-    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
-    for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
-    {
-        void *l_rtaData = RTA_DATA(l_rta);
-        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
-        switch(l_rta->rta_type)
-        {
-            case IFLA_ADDRESS:
-            case IFLA_BROADCAST:
-            {
-                size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
-                makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
-                ((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
-                ((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
-                if(l_rta->rta_type == IFLA_ADDRESS)
-                {
-                    l_entry->ifa_addr = (struct sockaddr *)l_addr;
-                }
-                else
-                {
-                    l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
-                }
-                l_addr += NLMSG_ALIGN(l_addrLen);
-                break;
-            }
-            case IFLA_IFNAME:
-                strncpy(l_name, l_rtaData, l_rtaDataSize);
-                l_name[l_rtaDataSize] = '\0';
-                l_entry->ifa_name = l_name;
-                break;
-            case IFLA_STATS:
-                memcpy(l_data, l_rtaData, l_rtaDataSize);
-                l_entry->ifa_data = l_data;
-                break;
-            default:
-                break;
-        }
-    }
-
-    addToEnd(p_resultList, l_entry);
-    return 0;
-}
-
-static struct ifaddrs *findInterface(int p_index, struct ifaddrs **p_links, int p_numLinks)
-{
-    int l_num = 0;
-    struct ifaddrs *l_cur = *p_links;
-    while(l_cur && l_num < p_numLinks)
-    {
-        char *l_indexPtr = ((char *)l_cur) + sizeof(struct ifaddrs);
-        int l_index;
-        memcpy(&l_index, l_indexPtr, sizeof(int));
-        if(l_index == p_index)
-        {
-            return l_cur;
-        }
-
-        l_cur = l_cur->ifa_next;
-        ++l_num;
-    }
-    return NULL;
-}
-
-static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, int p_numLinks)
-{
-    struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
-    struct ifaddrs *l_interface = findInterface(l_info->ifa_index, p_resultList, p_numLinks);
-
-    size_t l_nameSize = 0;
-    size_t l_addrSize = 0;
-
-    int l_addedNetmask = 0;
-
-    size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
-    struct rtattr *l_rta;
-    struct ifaddrs *l_entry;
-
-    char *l_name;
-    char *l_addr;
-
-    for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
-    {
-        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
-        if(l_info->ifa_family == AF_PACKET)
-        {
-            continue;
-        }
-
-        switch(l_rta->rta_type)
-        {
-            case IFA_ADDRESS:
-            case IFA_LOCAL:
-                if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
-                {
-                    /* Make room for netmask */
-                    l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
-                    l_addedNetmask = 1;
-                }
-            case IFA_BROADCAST:
-                l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
-                break;
-            case IFA_LABEL:
-                l_nameSize += NLMSG_ALIGN(l_rtaDataSize + 1);
-                break;
-            default:
-                break;
-        }
-    }
-
-    l_entry = (struct ifaddrs*)uv__malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
-    if (l_entry == NULL)
-    {
-        return -1;
-    }
-    memset(l_entry, 0, sizeof(struct ifaddrs));
-    l_entry->ifa_name = (l_interface ? l_interface->ifa_name : "");
-
-    l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
-    l_addr = l_name + l_nameSize;
-
-    l_entry->ifa_flags = l_info->ifa_flags;
-    if(l_interface)
-    {
-        l_entry->ifa_flags |= l_interface->ifa_flags;
-    }
-
-    l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
-    for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
-    {
-        void *l_rtaData = RTA_DATA(l_rta);
-        size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
-        switch(l_rta->rta_type)
-        {
-            case IFA_ADDRESS:
-            case IFA_BROADCAST:
-            case IFA_LOCAL:
-            {
-                size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
-                makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
-                if(l_info->ifa_family == AF_INET6)
-                {
-                    if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
-                    {
-                        ((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
-                    }
-                }
-
-                /* Apparently in a point-to-point network IFA_ADDRESS contains
-                 * the dest address and IFA_LOCAL contains the local address
-                 */
-                if(l_rta->rta_type == IFA_ADDRESS)
-                {
-                    if(l_entry->ifa_addr)
-                    {
-                        l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
-                    }
-                    else
-                    {
-                        l_entry->ifa_addr = (struct sockaddr *)l_addr;
-                    }
-                }
-                else if(l_rta->rta_type == IFA_LOCAL)
-                {
-                    if(l_entry->ifa_addr)
-                    {
-                        l_entry->ifa_dstaddr = l_entry->ifa_addr;
-                    }
-                    l_entry->ifa_addr = (struct sockaddr *)l_addr;
-                }
-                else
-                {
-                    l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
-                }
-                l_addr += NLMSG_ALIGN(l_addrLen);
-                break;
-            }
-            case IFA_LABEL:
-                strncpy(l_name, l_rtaData, l_rtaDataSize);
-                l_name[l_rtaDataSize] = '\0';
-                l_entry->ifa_name = l_name;
-                break;
-            default:
-                break;
-        }
-    }
-
-    if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
-    {
-        unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
-        unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
-        unsigned char l_mask[16] = {0};
-        unsigned i;
-        for(i=0; i<(l_prefix/8); ++i)
-        {
-            l_mask[i] = 0xff;
-        }
-        if(l_prefix % 8)
-        {
-            l_mask[i] = 0xff << (8 - (l_prefix % 8));
-        }
-
-        makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
-        l_entry->ifa_netmask = (struct sockaddr *)l_addr;
-    }
-
-    addToEnd(p_resultList, l_entry);
-    return 0;
-}
-
-static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
-{
-
-    int l_numLinks = 0;
-    for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
-    {
-        unsigned int l_nlsize = p_netlinkList->m_size;
-        struct nlmsghdr *l_hdr;
-        for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
-        {
-            if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
-            {
-                continue;
-            }
-
-            if(l_hdr->nlmsg_type == NLMSG_DONE)
-            {
-                break;
-            }
-
-            if(l_hdr->nlmsg_type == RTM_NEWLINK)
-            {
-                if(interpretLink(l_hdr, p_resultList) == -1)
-                {
-                    return -1;
-                }
-                ++l_numLinks;
-            }
-        }
-    }
-    return l_numLinks;
-}
-
-static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
-{
-    for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
-    {
-        unsigned int l_nlsize = p_netlinkList->m_size;
-        struct nlmsghdr *l_hdr;
-        for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
-        {
-            if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
-            {
-                continue;
-            }
-
-            if(l_hdr->nlmsg_type == NLMSG_DONE)
-            {
-                break;
-            }
-
-            if(l_hdr->nlmsg_type == RTM_NEWADDR)
-            {
-                if (interpretAddr(l_hdr, p_resultList, p_numLinks) == -1)
-                {
-                    return -1;
-                }
-            }
-        }
-    }
-    return 0;
-}
-
-int getifaddrs(struct ifaddrs **ifap)
-{
-    int l_socket;
-    int l_result;
-    int l_numLinks;
-    pid_t l_pid;
-    NetlinkList *l_linkResults;
-    NetlinkList *l_addrResults;
-
-    if(!ifap)
-    {
-        return -1;
-    }
-    *ifap = NULL;
-
-    l_socket = netlink_socket(&l_pid);
-    if(l_socket < 0)
-    {
-        return -1;
-    }
-
-    l_linkResults = getResultList(l_socket, RTM_GETLINK, l_pid);
-    if(!l_linkResults)
-    {
-        close(l_socket);
-        return -1;
-    }
-
-    l_addrResults = getResultList(l_socket, RTM_GETADDR, l_pid);
-    if(!l_addrResults)
-    {
-        close(l_socket);
-        freeResultList(l_linkResults);
-        return -1;
-    }
-
-    l_result = 0;
-    l_numLinks = interpretLinks(l_socket, l_pid, l_linkResults, ifap);
-    if(l_numLinks == -1 || interpretAddrs(l_socket, l_pid, l_addrResults, ifap, l_numLinks) == -1)
-    {
-        l_result = -1;
-    }
-
-    freeResultList(l_linkResults);
-    freeResultList(l_addrResults);
-    close(l_socket);
-    return l_result;
-}
-
-void freeifaddrs(struct ifaddrs *ifa)
-{
-    struct ifaddrs *l_cur;
-    while(ifa)
-    {
-        l_cur = ifa;
-        ifa = ifa->ifa_next;
-        uv__free(l_cur);
-    }
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/async.cpp b/wpiutil/src/main/native/libuv/src/unix/async.cpp
deleted file mode 100644
index a5c47bc..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/async.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/* This file contains both the uv__async internal infrastructure and the
- * user-facing uv_async_t functions.
- */
-
-#include "uv.h"
-#include "internal.h"
-#include "atomic-ops.h"
-
-#include <errno.h>
-#include <stdio.h>  /* snprintf() */
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-static void uv__async_send(uv_loop_t* loop);
-static int uv__async_start(uv_loop_t* loop);
-static int uv__async_eventfd(void);
-
-
-int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
-  int err;
-
-  err = uv__async_start(loop);
-  if (err)
-    return err;
-
-  uv__handle_init(loop, (uv_handle_t*)handle, UV_ASYNC);
-  handle->async_cb = async_cb;
-  handle->pending = 0;
-
-  QUEUE_INSERT_TAIL(&loop->async_handles, &handle->queue);
-  uv__handle_start(handle);
-
-  return 0;
-}
-
-
-int uv_async_send(uv_async_t* handle) {
-  /* Do a cheap read first. */
-  if (ACCESS_ONCE(int, handle->pending) != 0)
-    return 0;
-
-  /* Tell the other thread we're busy with the handle. */
-  if (cmpxchgi(&handle->pending, 0, 1) != 0)
-    return 0;
-
-  /* Wake up the other thread's event loop. */
-  uv__async_send(handle->loop);
-
-  /* Tell the other thread we're done. */
-  if (cmpxchgi(&handle->pending, 1, 2) != 1)
-    abort();
-
-  return 0;
-}
-
-
-/* Only call this from the event loop thread. */
-static int uv__async_spin(uv_async_t* handle) {
-  int rc;
-
-  for (;;) {
-    /* rc=0 -- handle is not pending.
-     * rc=1 -- handle is pending, other thread is still working with it.
-     * rc=2 -- handle is pending, other thread is done.
-     */
-    rc = cmpxchgi(&handle->pending, 2, 0);
-
-    if (rc != 1)
-      return rc;
-
-    /* Other thread is busy with this handle, spin until it's done. */
-    cpu_relax();
-  }
-}
-
-
-void uv__async_close(uv_async_t* handle) {
-  uv__async_spin(handle);
-  QUEUE_REMOVE(&handle->queue);
-  uv__handle_stop(handle);
-}
-
-
-static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
-  char buf[1024];
-  ssize_t r;
-  QUEUE queue;
-  QUEUE* q;
-  uv_async_t* h;
-
-  assert(w == &loop->async_io_watcher);
-
-  for (;;) {
-    r = read(w->fd, buf, sizeof(buf));
-
-    if (r == sizeof(buf))
-      continue;
-
-    if (r != -1)
-      break;
-
-    if (errno == EAGAIN || errno == EWOULDBLOCK)
-      break;
-
-    if (errno == EINTR)
-      continue;
-
-    abort();
-  }
-
-  QUEUE_MOVE(&loop->async_handles, &queue);
-  while (!QUEUE_EMPTY(&queue)) {
-    q = QUEUE_HEAD(&queue);
-    h = QUEUE_DATA(q, uv_async_t, queue);
-
-    QUEUE_REMOVE(q);
-    QUEUE_INSERT_TAIL(&loop->async_handles, q);
-
-    if (0 == uv__async_spin(h))
-      continue;  /* Not pending. */
-
-    if (h->async_cb == NULL)
-      continue;
-
-    h->async_cb(h);
-  }
-}
-
-
-static void uv__async_send(uv_loop_t* loop) {
-  const void* buf;
-  ssize_t len;
-  int fd;
-  int r;
-
-  buf = "";
-  len = 1;
-  fd = loop->async_wfd;
-
-#if defined(__linux__)
-  if (fd == -1) {
-    static const uint64_t val = 1;
-    buf = &val;
-    len = sizeof(val);
-    fd = loop->async_io_watcher.fd;  /* eventfd */
-  }
-#endif
-
-  do
-    r = write(fd, buf, len);
-  while (r == -1 && errno == EINTR);
-
-  if (r == len)
-    return;
-
-  if (r == -1)
-    if (errno == EAGAIN || errno == EWOULDBLOCK)
-      return;
-
-  abort();
-}
-
-
-static int uv__async_start(uv_loop_t* loop) {
-  int pipefd[2];
-  int err;
-
-  if (loop->async_io_watcher.fd != -1)
-    return 0;
-
-  err = uv__async_eventfd();
-  if (err >= 0) {
-    pipefd[0] = err;
-    pipefd[1] = -1;
-  }
-  else if (err == UV_ENOSYS) {
-    err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
-#if defined(__linux__)
-    /* Save a file descriptor by opening one of the pipe descriptors as
-     * read/write through the procfs.  That file descriptor can then
-     * function as both ends of the pipe.
-     */
-    if (err == 0) {
-      char buf[32];
-      int fd;
-
-      snprintf(buf, sizeof(buf), "/proc/self/fd/%d", pipefd[0]);
-      fd = uv__open_cloexec(buf, O_RDWR);
-      if (fd >= 0) {
-        uv__close(pipefd[0]);
-        uv__close(pipefd[1]);
-        pipefd[0] = fd;
-        pipefd[1] = fd;
-      }
-    }
-#endif
-  }
-
-  if (err < 0)
-    return err;
-
-  uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]);
-  uv__io_start(loop, &loop->async_io_watcher, POLLIN);
-  loop->async_wfd = pipefd[1];
-
-  return 0;
-}
-
-
-int uv__async_fork(uv_loop_t* loop) {
-  if (loop->async_io_watcher.fd == -1) /* never started */
-    return 0;
-
-  uv__async_stop(loop);
-
-  return uv__async_start(loop);
-}
-
-
-void uv__async_stop(uv_loop_t* loop) {
-  if (loop->async_io_watcher.fd == -1)
-    return;
-
-  if (loop->async_wfd != -1) {
-    if (loop->async_wfd != loop->async_io_watcher.fd)
-      uv__close(loop->async_wfd);
-    loop->async_wfd = -1;
-  }
-
-  uv__io_stop(loop, &loop->async_io_watcher, POLLIN);
-  uv__close(loop->async_io_watcher.fd);
-  loop->async_io_watcher.fd = -1;
-}
-
-
-static int uv__async_eventfd(void) {
-#if defined(__linux__)
-  static int no_eventfd2;
-  static int no_eventfd;
-  int fd;
-
-  if (no_eventfd2)
-    goto skip_eventfd2;
-
-  fd = uv__eventfd2(0, UV__EFD_CLOEXEC | UV__EFD_NONBLOCK);
-  if (fd != -1)
-    return fd;
-
-  if (errno != ENOSYS)
-    return UV__ERR(errno);
-
-  no_eventfd2 = 1;
-
-skip_eventfd2:
-
-  if (no_eventfd)
-    goto skip_eventfd;
-
-  fd = uv__eventfd(0);
-  if (fd != -1) {
-    uv__cloexec(fd, 1);
-    uv__nonblock(fd, 1);
-    return fd;
-  }
-
-  if (errno != ENOSYS)
-    return UV__ERR(errno);
-
-  no_eventfd = 1;
-
-skip_eventfd:
-
-#endif
-
-  return UV_ENOSYS;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/atomic-ops.h b/wpiutil/src/main/native/libuv/src/unix/atomic-ops.h
deleted file mode 100644
index 541a6c8..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/atomic-ops.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef UV_ATOMIC_OPS_H_
-#define UV_ATOMIC_OPS_H_
-
-#include "internal.h"  /* UV_UNUSED */
-
-#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-#include <atomic.h>
-#endif
-
-UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
-UV_UNUSED(static void cpu_relax(void));
-
-/* Prefer hand-rolled assembly over the gcc builtins because the latter also
- * issue full memory barriers.
- */
-UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
-#if defined(__i386__) || defined(__x86_64__)
-  int out;
-  __asm__ __volatile__ ("lock; cmpxchg %2, %1;"
-                        : "=a" (out), "+m" (*(volatile int*) ptr)
-                        : "r" (newval), "0" (oldval)
-                        : "memory");
-  return out;
-#elif defined(_AIX) && defined(__xlC__)
-  const int out = (*(volatile int*) ptr);
-  __compare_and_swap(ptr, &oldval, newval);
-  return out;
-#elif defined(__MVS__)
-  unsigned int op4;
-  if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
-                (unsigned int*) ptr, *ptr, &op4))
-    return oldval;
-  else
-    return op4;
-#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
-  return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval);
-#else
-  return __sync_val_compare_and_swap(ptr, oldval, newval);
-#endif
-}
-
-UV_UNUSED(static void cpu_relax(void)) {
-#if defined(__i386__) || defined(__x86_64__)
-  __asm__ __volatile__ ("rep; nop");  /* a.k.a. PAUSE */
-#endif
-}
-
-#endif  /* UV_ATOMIC_OPS_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/unix/bsd-ifaddrs.cpp b/wpiutil/src/main/native/libuv/src/unix/bsd-ifaddrs.cpp
deleted file mode 100644
index a01aa8d..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/bsd-ifaddrs.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <errno.h>
-#include <stddef.h>
-
-#include <ifaddrs.h>
-#include <net/if.h>
-#if !defined(__CYGWIN__) && !defined(__MSYS__)
-#include <net/if_dl.h>
-#endif
-
-#if defined(__HAIKU__)
-#define IFF_RUNNING IFF_LINK
-#endif
-
-static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
-  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
-    return 1;
-  if (ent->ifa_addr == NULL)
-    return 1;
-#if !defined(__CYGWIN__) && !defined(__MSYS__)
-  /*
-   * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, just see whether `sa_family`
-   * equals to `AF_LINK` or not. Otherwise, the result depends on the operation
-   * system with `AF_LINK` or `PF_INET`.
-   */
-  if (exclude_type == UV__EXCLUDE_IFPHYS)
-    return (ent->ifa_addr->sa_family != AF_LINK);
-#endif
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \
-    defined(__HAIKU__)
-  /*
-   * On BSD getifaddrs returns information related to the raw underlying
-   * devices.  We're not interested in this information.
-   */
-  if (ent->ifa_addr->sa_family == AF_LINK)
-    return 1;
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
-  if (ent->ifa_addr->sa_family != PF_INET &&
-      ent->ifa_addr->sa_family != PF_INET6)
-    return 1;
-#endif
-  return 0;
-}
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
-  struct ifaddrs* addrs;
-  struct ifaddrs* ent;
-  uv_interface_address_t* address;
-  int i;
-
-  *count = 0;
-  *addresses = NULL;
-
-  if (getifaddrs(&addrs) != 0)
-    return UV__ERR(errno);
-
-  /* Count the number of interfaces */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
-      continue;
-    (*count)++;
-  }
-
-  if (*count == 0) {
-    freeifaddrs(addrs);
-    return 0;
-  }
-
-  /* Make sure the memory is initiallized to zero using calloc() */
-  *addresses = (uv_interface_address_t*)uv__calloc(*count, sizeof(**addresses));
-
-  if (*addresses == NULL) {
-    freeifaddrs(addrs);
-    return UV_ENOMEM;
-  }
-
-  address = *addresses;
-
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
-      continue;
-
-    address->name = uv__strdup(ent->ifa_name);
-
-    if (ent->ifa_addr->sa_family == AF_INET6) {
-      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
-    } else {
-      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
-    }
-
-    if (ent->ifa_netmask->sa_family == AF_INET6) {
-      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
-    } else {
-      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
-    }
-
-    address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
-    address++;
-  }
-
-#if !(defined(__CYGWIN__) || defined(__MSYS__))
-  /* Fill in physical addresses for each interface */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
-      continue;
-
-    address = *addresses;
-
-    for (i = 0; i < *count; i++) {
-      if (strcmp(address->name, ent->ifa_name) == 0) {
-        struct sockaddr_dl* sa_addr;
-        sa_addr = (struct sockaddr_dl*)(ent->ifa_addr);
-        memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
-      }
-      address++;
-    }
-  }
-#endif
-
-  freeifaddrs(addrs);
-
-  return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
-                                 int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(addresses[i].name);
-  }
-
-  uv__free(addresses);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/core.cpp b/wpiutil/src/main/native/libuv/src/unix/core.cpp
deleted file mode 100644
index 77bb337..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/core.cpp
+++ /dev/null
@@ -1,1509 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stddef.h> /* NULL */
-#include <stdio.h> /* printf */
-#include <stdlib.h>
-#include <string.h> /* strerror */
-#include <errno.h>
-#include <assert.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <limits.h> /* INT_MAX, PATH_MAX, IOV_MAX */
-#include <sys/uio.h> /* writev */
-#include <sys/resource.h> /* getrusage */
-#include <pwd.h>
-#include <sys/utsname.h>
-#include <sys/time.h>
-
-#ifdef __sun
-# include <sys/filio.h>
-# include <sys/types.h>
-# include <sys/wait.h>
-#endif
-
-#ifdef __APPLE__
-# include <mach-o/dyld.h> /* _NSGetExecutablePath */
-# include <sys/filio.h>
-# if defined(O_CLOEXEC)
-#  define UV__O_CLOEXEC O_CLOEXEC
-# endif
-#endif
-
-#if defined(__DragonFly__)      || \
-    defined(__FreeBSD__)        || \
-    defined(__FreeBSD_kernel__) || \
-    defined(__NetBSD__)
-# include <sys/sysctl.h>
-# include <sys/filio.h>
-# include <sys/wait.h>
-# define UV__O_CLOEXEC O_CLOEXEC
-# if defined(__FreeBSD__) && __FreeBSD__ >= 10
-#  define uv__accept4 accept4
-# endif
-# if defined(__NetBSD__)
-#  define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d))
-# endif
-# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
-#  define UV__SOCK_NONBLOCK SOCK_NONBLOCK
-#  define UV__SOCK_CLOEXEC  SOCK_CLOEXEC
-# endif
-# if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC)
-#  define F_DUP2FD_CLOEXEC  _F_DUP2FD_CLOEXEC
-# endif
-#endif
-
-#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
-# include <dlfcn.h>  /* for dlsym */
-#endif
-
-#if defined(__MVS__)
-#include <sys/ioctl.h>
-#endif
-
-#if defined(__linux__)
-#include <sys/syscall.h>
-#endif
-
-static int uv__run_pending(uv_loop_t* loop);
-
-/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
-STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec));
-STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->base) ==
-              sizeof(((struct iovec*) 0)->iov_base));
-STATIC_ASSERT(sizeof(&((uv_buf_t*) 0)->len) ==
-              sizeof(((struct iovec*) 0)->iov_len));
-STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base));
-STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len));
-
-
-uint64_t uv_hrtime(void) {
-  return uv__hrtime(UV_CLOCK_PRECISE);
-}
-
-
-void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
-  assert(!uv__is_closing(handle));
-
-  handle->flags |= UV_HANDLE_CLOSING;
-  handle->close_cb = close_cb;
-
-  switch (handle->type) {
-  case UV_NAMED_PIPE:
-    uv__pipe_close((uv_pipe_t*)handle);
-    break;
-
-  case UV_TTY:
-    uv__stream_close((uv_stream_t*)handle);
-    break;
-
-  case UV_TCP:
-    uv__tcp_close((uv_tcp_t*)handle);
-    break;
-
-  case UV_UDP:
-    uv__udp_close((uv_udp_t*)handle);
-    break;
-
-  case UV_PREPARE:
-    uv__prepare_close((uv_prepare_t*)handle);
-    break;
-
-  case UV_CHECK:
-    uv__check_close((uv_check_t*)handle);
-    break;
-
-  case UV_IDLE:
-    uv__idle_close((uv_idle_t*)handle);
-    break;
-
-  case UV_ASYNC:
-    uv__async_close((uv_async_t*)handle);
-    break;
-
-  case UV_TIMER:
-    uv__timer_close((uv_timer_t*)handle);
-    break;
-
-  case UV_PROCESS:
-    uv__process_close((uv_process_t*)handle);
-    break;
-
-  case UV_FS_EVENT:
-    uv__fs_event_close((uv_fs_event_t*)handle);
-    break;
-
-  case UV_POLL:
-    uv__poll_close((uv_poll_t*)handle);
-    break;
-
-  case UV_FS_POLL:
-    uv__fs_poll_close((uv_fs_poll_t*)handle);
-    /* Poll handles use file system requests, and one of them may still be
-     * running. The poll code will call uv__make_close_pending() for us. */
-    return;
-
-  case UV_SIGNAL:
-    uv__signal_close((uv_signal_t*) handle);
-    /* Signal handles may not be closed immediately. The signal code will
-     * itself close uv__make_close_pending whenever appropriate. */
-    return;
-
-  default:
-    assert(0);
-  }
-
-  uv__make_close_pending(handle);
-}
-
-int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
-  int r;
-  int fd;
-  socklen_t len;
-
-  if (handle == NULL || value == NULL)
-    return UV_EINVAL;
-
-  if (handle->type == UV_TCP || handle->type == UV_NAMED_PIPE)
-    fd = uv__stream_fd((uv_stream_t*) handle);
-  else if (handle->type == UV_UDP)
-    fd = ((uv_udp_t *) handle)->io_watcher.fd;
-  else
-    return UV_ENOTSUP;
-
-  len = sizeof(*value);
-
-  if (*value == 0)
-    r = getsockopt(fd, SOL_SOCKET, optname, value, &len);
-  else
-    r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len);
-
-  if (r < 0)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-void uv__make_close_pending(uv_handle_t* handle) {
-  assert(handle->flags & UV_HANDLE_CLOSING);
-  assert(!(handle->flags & UV_HANDLE_CLOSED));
-  handle->next_closing = handle->loop->closing_handles;
-  handle->loop->closing_handles = handle;
-}
-
-int uv__getiovmax(void) {
-#if defined(IOV_MAX)
-  return IOV_MAX;
-#elif defined(_SC_IOV_MAX)
-  static int iovmax = -1;
-  if (iovmax == -1) {
-    iovmax = sysconf(_SC_IOV_MAX);
-    /* On some embedded devices (arm-linux-uclibc based ip camera),
-     * sysconf(_SC_IOV_MAX) can not get the correct value. The return
-     * value is -1 and the errno is EINPROGRESS. Degrade the value to 1.
-     */
-    if (iovmax == -1) iovmax = 1;
-  }
-  return iovmax;
-#else
-  return 1024;
-#endif
-}
-
-
-static void uv__finish_close(uv_handle_t* handle) {
-  /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still
-   * possible for it to be active in the sense that uv__is_active() returns
-   * true.
-   *
-   * A good example is when the user calls uv_shutdown(), immediately followed
-   * by uv_close(). The handle is considered active at this point because the
-   * completion of the shutdown req is still pending.
-   */
-  assert(handle->flags & UV_HANDLE_CLOSING);
-  assert(!(handle->flags & UV_HANDLE_CLOSED));
-  handle->flags |= UV_HANDLE_CLOSED;
-
-  switch (handle->type) {
-    case UV_PREPARE:
-    case UV_CHECK:
-    case UV_IDLE:
-    case UV_ASYNC:
-    case UV_TIMER:
-    case UV_PROCESS:
-    case UV_FS_EVENT:
-    case UV_FS_POLL:
-    case UV_POLL:
-    case UV_SIGNAL:
-      break;
-
-    case UV_NAMED_PIPE:
-    case UV_TCP:
-    case UV_TTY:
-      uv__stream_destroy((uv_stream_t*)handle);
-      break;
-
-    case UV_UDP:
-      uv__udp_finish_close((uv_udp_t*)handle);
-      break;
-
-    default:
-      assert(0);
-      break;
-  }
-
-  uv__handle_unref(handle);
-  QUEUE_REMOVE(&handle->handle_queue);
-
-  if (handle->close_cb) {
-    handle->close_cb(handle);
-  }
-}
-
-
-static void uv__run_closing_handles(uv_loop_t* loop) {
-  uv_handle_t* p;
-  uv_handle_t* q;
-
-  p = loop->closing_handles;
-  loop->closing_handles = NULL;
-
-  while (p) {
-    q = p->next_closing;
-    uv__finish_close(p);
-    p = q;
-  }
-}
-
-
-int uv_is_closing(const uv_handle_t* handle) {
-  return uv__is_closing(handle);
-}
-
-
-int uv_backend_fd(const uv_loop_t* loop) {
-  return loop->backend_fd;
-}
-
-
-int uv_backend_timeout(const uv_loop_t* loop) {
-  if (loop->stop_flag != 0)
-    return 0;
-
-  if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
-    return 0;
-
-  if (!QUEUE_EMPTY(&loop->idle_handles))
-    return 0;
-
-  if (!QUEUE_EMPTY(&loop->pending_queue))
-    return 0;
-
-  if (loop->closing_handles)
-    return 0;
-
-  return uv__next_timeout(loop);
-}
-
-
-static int uv__loop_alive(const uv_loop_t* loop) {
-  return uv__has_active_handles(loop) ||
-         uv__has_active_reqs(loop) ||
-         loop->closing_handles != NULL;
-}
-
-
-int uv_loop_alive(const uv_loop_t* loop) {
-    return uv__loop_alive(loop);
-}
-
-
-int uv_run(uv_loop_t* loop, uv_run_mode mode) {
-  int timeout;
-  int r;
-  int ran_pending;
-
-  r = uv__loop_alive(loop);
-  if (!r)
-    uv__update_time(loop);
-
-  while (r != 0 && loop->stop_flag == 0) {
-    uv__update_time(loop);
-    uv__run_timers(loop);
-    ran_pending = uv__run_pending(loop);
-    uv__run_idle(loop);
-    uv__run_prepare(loop);
-
-    timeout = 0;
-    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
-      timeout = uv_backend_timeout(loop);
-
-    uv__io_poll(loop, timeout);
-    uv__run_check(loop);
-    uv__run_closing_handles(loop);
-
-    if (mode == UV_RUN_ONCE) {
-      /* UV_RUN_ONCE implies forward progress: at least one callback must have
-       * been invoked when it returns. uv__io_poll() can return without doing
-       * I/O (meaning: no callbacks) when its timeout expires - which means we
-       * have pending timers that satisfy the forward progress constraint.
-       *
-       * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
-       * the check.
-       */
-      uv__update_time(loop);
-      uv__run_timers(loop);
-    }
-
-    r = uv__loop_alive(loop);
-    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
-      break;
-  }
-
-  /* The if statement lets gcc compile it to a conditional store. Avoids
-   * dirtying a cache line.
-   */
-  if (loop->stop_flag != 0)
-    loop->stop_flag = 0;
-
-  return r;
-}
-
-
-void uv_update_time(uv_loop_t* loop) {
-  uv__update_time(loop);
-}
-
-
-int uv_is_active(const uv_handle_t* handle) {
-  return uv__is_active(handle);
-}
-
-
-/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */
-int uv__socket(int domain, int type, int protocol) {
-  int sockfd;
-  int err;
-
-#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
-  sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol);
-  if (sockfd != -1)
-    return sockfd;
-
-  if (errno != EINVAL)
-    return UV__ERR(errno);
-#endif
-
-  sockfd = socket(domain, type, protocol);
-  if (sockfd == -1)
-    return UV__ERR(errno);
-
-  err = uv__nonblock(sockfd, 1);
-  if (err == 0)
-    err = uv__cloexec(sockfd, 1);
-
-  if (err) {
-    uv__close(sockfd);
-    return err;
-  }
-
-#if defined(SO_NOSIGPIPE)
-  {
-    int on = 1;
-    setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
-  }
-#endif
-
-  return sockfd;
-}
-
-/* get a file pointer to a file in read-only and close-on-exec mode */
-FILE* uv__open_file(const char* path) {
-  int fd;
-  FILE* fp;
-
-  fd = uv__open_cloexec(path, O_RDONLY);
-  if (fd < 0)
-    return NULL;
-
-   fp = fdopen(fd, "r");
-   if (fp == NULL)
-     uv__close(fd);
-
-   return fp;
-}
-
-
-int uv__accept(int sockfd) {
-  int peerfd;
-  int err;
-
-  assert(sockfd >= 0);
-
-  while (1) {
-#if defined(__linux__)                          || \
-    (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
-    defined(__NetBSD__)
-    static int no_accept4;
-
-    if (no_accept4)
-      goto skip;
-
-    peerfd = uv__accept4(sockfd,
-                         NULL,
-                         NULL,
-                         UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC);
-    if (peerfd != -1)
-      return peerfd;
-
-    if (errno == EINTR)
-      continue;
-
-    if (errno != ENOSYS)
-      return UV__ERR(errno);
-
-    no_accept4 = 1;
-skip:
-#endif
-
-    peerfd = accept(sockfd, NULL, NULL);
-    if (peerfd == -1) {
-      if (errno == EINTR)
-        continue;
-      return UV__ERR(errno);
-    }
-
-    err = uv__cloexec(peerfd, 1);
-    if (err == 0)
-      err = uv__nonblock(peerfd, 1);
-
-    if (err) {
-      uv__close(peerfd);
-      return err;
-    }
-
-    return peerfd;
-  }
-}
-
-
-#if defined(__APPLE__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
-#if defined(__LP64__)
-  extern "C" int close$NOCANCEL(int);
-#else
-  extern "C" int close$NOCANCEL$UNIX2003(int);
-#endif
-#pragma GCC diagnostic pop
-#endif
-
-/* close() on macos has the "interesting" quirk that it fails with EINTR
- * without closing the file descriptor when a thread is in the cancel state.
- * That's why libuv calls close$NOCANCEL() instead.
- *
- * glibc on linux has a similar issue: close() is a cancellation point and
- * will unwind the thread when it's in the cancel state. Work around that
- * by making the system call directly. Musl libc is unaffected.
- */
-int uv__close_nocancel(int fd) {
-#if defined(__APPLE__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
-#if defined(__LP64__)
-  return close$NOCANCEL(fd);
-#else
-  return close$NOCANCEL$UNIX2003(fd);
-#endif
-#pragma GCC diagnostic pop
-#elif defined(__linux__)
-  return syscall(SYS_close, fd);
-#else
-  return close(fd);
-#endif
-}
-
-
-int uv__close_nocheckstdio(int fd) {
-  int saved_errno;
-  int rc;
-
-  assert(fd > -1);  /* Catch uninitialized io_watcher.fd bugs. */
-
-  saved_errno = errno;
-  rc = uv__close_nocancel(fd);
-  if (rc == -1) {
-    rc = UV__ERR(errno);
-    if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
-      rc = 0;    /* The close is in progress, not an error. */
-    errno = saved_errno;
-  }
-
-  return rc;
-}
-
-
-int uv__close(int fd) {
-  assert(fd > STDERR_FILENO);  /* Catch stdio close bugs. */
-#if defined(__MVS__)
-  SAVE_ERRNO(epoll_file_close(fd));
-#endif
-  return uv__close_nocheckstdio(fd);
-}
-
-
-int uv__nonblock_ioctl(int fd, int set) {
-  int r;
-
-  do
-    r = ioctl(fd, FIONBIO, &set);
-  while (r == -1 && errno == EINTR);
-
-  if (r)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__)
-int uv__cloexec_ioctl(int fd, int set) {
-  int r;
-
-  do
-    r = ioctl(fd, set ? FIOCLEX : FIONCLEX);
-  while (r == -1 && errno == EINTR);
-
-  if (r)
-    return UV__ERR(errno);
-
-  return 0;
-}
-#endif
-
-
-int uv__nonblock_fcntl(int fd, int set) {
-  int flags;
-  int r;
-
-  do
-    r = fcntl(fd, F_GETFL);
-  while (r == -1 && errno == EINTR);
-
-  if (r == -1)
-    return UV__ERR(errno);
-
-  /* Bail out now if already set/clear. */
-  if (!!(r & O_NONBLOCK) == !!set)
-    return 0;
-
-  if (set)
-    flags = r | O_NONBLOCK;
-  else
-    flags = r & ~O_NONBLOCK;
-
-  do
-    r = fcntl(fd, F_SETFL, flags);
-  while (r == -1 && errno == EINTR);
-
-  if (r)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-int uv__cloexec_fcntl(int fd, int set) {
-  int flags;
-  int r;
-
-  do
-    r = fcntl(fd, F_GETFD);
-  while (r == -1 && errno == EINTR);
-
-  if (r == -1)
-    return UV__ERR(errno);
-
-  /* Bail out now if already set/clear. */
-  if (!!(r & FD_CLOEXEC) == !!set)
-    return 0;
-
-  if (set)
-    flags = r | FD_CLOEXEC;
-  else
-    flags = r & ~FD_CLOEXEC;
-
-  do
-    r = fcntl(fd, F_SETFD, flags);
-  while (r == -1 && errno == EINTR);
-
-  if (r)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
-  struct cmsghdr* cmsg;
-  ssize_t rc;
-  int* pfd;
-  int* end;
-#if defined(__linux__)
-  static int no_msg_cmsg_cloexec;
-  if (no_msg_cmsg_cloexec == 0) {
-    rc = recvmsg(fd, msg, flags | 0x40000000);  /* MSG_CMSG_CLOEXEC */
-    if (rc != -1)
-      return rc;
-    if (errno != EINVAL)
-      return UV__ERR(errno);
-    rc = recvmsg(fd, msg, flags);
-    if (rc == -1)
-      return UV__ERR(errno);
-    no_msg_cmsg_cloexec = 1;
-  } else {
-    rc = recvmsg(fd, msg, flags);
-  }
-#else
-  rc = recvmsg(fd, msg, flags);
-#endif
-  if (rc == -1)
-    return UV__ERR(errno);
-  if (msg->msg_controllen == 0)
-    return rc;
-  for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
-    if (cmsg->cmsg_type == SCM_RIGHTS)
-      for (pfd = (int*) CMSG_DATA(cmsg),
-           end = (int*) ((char*) cmsg + cmsg->cmsg_len);
-           pfd < end;
-           pfd += 1)
-        uv__cloexec(*pfd, 1);
-  return rc;
-}
-
-
-int uv_cwd(char* buffer, size_t* size) {
-  char scratch[1 + UV__PATH_MAX];
-
-  if (buffer == NULL || size == NULL)
-    return UV_EINVAL;
-
-  /* Try to read directly into the user's buffer first... */
-  if (getcwd(buffer, *size) != NULL)
-    goto fixup;
-
-  if (errno != ERANGE)
-    return UV__ERR(errno);
-
-  /* ...or into scratch space if the user's buffer is too small
-   * so we can report how much space to provide on the next try.
-   */
-  if (getcwd(scratch, sizeof(scratch)) == NULL)
-    return UV__ERR(errno);
-
-  buffer = scratch;
-
-fixup:
-
-  *size = strlen(buffer);
-
-  if (*size > 1 && buffer[*size - 1] == '/') {
-    *size -= 1;
-    buffer[*size] = '\0';
-  }
-
-  if (buffer == scratch) {
-    *size += 1;
-    return UV_ENOBUFS;
-  }
-
-  return 0;
-}
-
-
-int uv_chdir(const char* dir) {
-  if (chdir(dir))
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-void uv_disable_stdio_inheritance(void) {
-  int fd;
-
-  /* Set the CLOEXEC flag on all open descriptors. Unconditionally try the
-   * first 16 file descriptors. After that, bail out after the first error.
-   */
-  for (fd = 0; ; fd++)
-    if (uv__cloexec(fd, 1) && fd > 15)
-      break;
-}
-
-
-int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
-  int fd_out;
-
-  switch (handle->type) {
-  case UV_TCP:
-  case UV_NAMED_PIPE:
-  case UV_TTY:
-    fd_out = uv__stream_fd((uv_stream_t*) handle);
-    break;
-
-  case UV_UDP:
-    fd_out = ((uv_udp_t *) handle)->io_watcher.fd;
-    break;
-
-  case UV_POLL:
-    fd_out = ((uv_poll_t *) handle)->io_watcher.fd;
-    break;
-
-  default:
-    return UV_EINVAL;
-  }
-
-  if (uv__is_closing(handle) || fd_out == -1)
-    return UV_EBADF;
-
-  *fd = fd_out;
-  return 0;
-}
-
-
-static int uv__run_pending(uv_loop_t* loop) {
-  QUEUE* q;
-  QUEUE pq;
-  uv__io_t* w;
-
-  if (QUEUE_EMPTY(&loop->pending_queue))
-    return 0;
-
-  QUEUE_MOVE(&loop->pending_queue, &pq);
-
-  while (!QUEUE_EMPTY(&pq)) {
-    q = QUEUE_HEAD(&pq);
-    QUEUE_REMOVE(q);
-    QUEUE_INIT(q);
-    w = QUEUE_DATA(q, uv__io_t, pending_queue);
-    w->cb(loop, w, POLLOUT);
-  }
-
-  return 1;
-}
-
-
-static unsigned int next_power_of_two(unsigned int val) {
-  val -= 1;
-  val |= val >> 1;
-  val |= val >> 2;
-  val |= val >> 4;
-  val |= val >> 8;
-  val |= val >> 16;
-  val += 1;
-  return val;
-}
-
-static void maybe_resize(uv_loop_t* loop, unsigned int len) {
-  void** watchers;
-  void* fake_watcher_list;
-  void* fake_watcher_count;
-  unsigned int nwatchers;
-  unsigned int i;
-
-  if (len <= loop->nwatchers)
-    return;
-
-  /* Preserve fake watcher list and count at the end of the watchers */
-  if (loop->watchers != NULL) {
-    fake_watcher_list = loop->watchers[loop->nwatchers];
-    fake_watcher_count = loop->watchers[loop->nwatchers + 1];
-  } else {
-    fake_watcher_list = NULL;
-    fake_watcher_count = NULL;
-  }
-
-  nwatchers = next_power_of_two(len + 2) - 2;
-  watchers = (void**)
-      uv__realloc(loop->watchers, (nwatchers + 2) * sizeof(loop->watchers[0]));
-
-  if (watchers == NULL)
-    abort();
-  for (i = loop->nwatchers; i < nwatchers; i++)
-    watchers[i] = NULL;
-  watchers[nwatchers] = fake_watcher_list;
-  watchers[nwatchers + 1] = fake_watcher_count;
-
-  loop->watchers = watchers;
-  loop->nwatchers = nwatchers;
-}
-
-
-void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
-  assert(cb != NULL);
-  assert(fd >= -1);
-  QUEUE_INIT(&w->pending_queue);
-  QUEUE_INIT(&w->watcher_queue);
-  w->cb = cb;
-  w->fd = fd;
-  w->events = 0;
-  w->pevents = 0;
-
-#if defined(UV_HAVE_KQUEUE)
-  w->rcount = 0;
-  w->wcount = 0;
-#endif /* defined(UV_HAVE_KQUEUE) */
-}
-
-
-void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
-  assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
-  assert(0 != events);
-  assert(w->fd >= 0);
-  assert(w->fd < INT_MAX);
-
-  w->pevents |= events;
-  maybe_resize(loop, w->fd + 1);
-
-#if !defined(__sun)
-  /* The event ports backend needs to rearm all file descriptors on each and
-   * every tick of the event loop but the other backends allow us to
-   * short-circuit here if the event mask is unchanged.
-   */
-  if (w->events == w->pevents)
-    return;
-#endif
-
-  if (QUEUE_EMPTY(&w->watcher_queue))
-    QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
-
-  if (loop->watchers[w->fd] == NULL) {
-    loop->watchers[w->fd] = w;
-    loop->nfds++;
-  }
-}
-
-
-void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
-  assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
-  assert(0 != events);
-
-  if (w->fd == -1)
-    return;
-
-  assert(w->fd >= 0);
-
-  /* Happens when uv__io_stop() is called on a handle that was never started. */
-  if ((unsigned) w->fd >= loop->nwatchers)
-    return;
-
-  w->pevents &= ~events;
-
-  if (w->pevents == 0) {
-    QUEUE_REMOVE(&w->watcher_queue);
-    QUEUE_INIT(&w->watcher_queue);
-
-    if (loop->watchers[w->fd] != NULL) {
-      assert(loop->watchers[w->fd] == w);
-      assert(loop->nfds > 0);
-      loop->watchers[w->fd] = NULL;
-      loop->nfds--;
-      w->events = 0;
-    }
-  }
-  else if (QUEUE_EMPTY(&w->watcher_queue))
-    QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
-}
-
-
-void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
-  uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
-  QUEUE_REMOVE(&w->pending_queue);
-
-  /* Remove stale events for this file descriptor */
-  if (w->fd != -1)
-    uv__platform_invalidate_fd(loop, w->fd);
-}
-
-
-void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
-  if (QUEUE_EMPTY(&w->pending_queue))
-    QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue);
-}
-
-
-int uv__io_active(const uv__io_t* w, unsigned int events) {
-  assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
-  assert(0 != events);
-  return 0 != (w->pevents & events);
-}
-
-
-int uv__fd_exists(uv_loop_t* loop, int fd) {
-  return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL;
-}
-
-
-int uv_getrusage(uv_rusage_t* rusage) {
-  struct rusage usage;
-
-  if (getrusage(RUSAGE_SELF, &usage))
-    return UV__ERR(errno);
-
-  rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
-  rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec;
-
-  rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec;
-  rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec;
-
-#if !defined(__MVS__) && !defined(__HAIKU__)
-  rusage->ru_maxrss = usage.ru_maxrss;
-  rusage->ru_ixrss = usage.ru_ixrss;
-  rusage->ru_idrss = usage.ru_idrss;
-  rusage->ru_isrss = usage.ru_isrss;
-  rusage->ru_minflt = usage.ru_minflt;
-  rusage->ru_majflt = usage.ru_majflt;
-  rusage->ru_nswap = usage.ru_nswap;
-  rusage->ru_inblock = usage.ru_inblock;
-  rusage->ru_oublock = usage.ru_oublock;
-  rusage->ru_msgsnd = usage.ru_msgsnd;
-  rusage->ru_msgrcv = usage.ru_msgrcv;
-  rusage->ru_nsignals = usage.ru_nsignals;
-  rusage->ru_nvcsw = usage.ru_nvcsw;
-  rusage->ru_nivcsw = usage.ru_nivcsw;
-#endif
-
-  return 0;
-}
-
-
-int uv__open_cloexec(const char* path, int flags) {
-  int err;
-  int fd;
-
-#if defined(UV__O_CLOEXEC)
-  static int no_cloexec;
-
-  if (!no_cloexec) {
-    fd = open(path, flags | UV__O_CLOEXEC);
-    if (fd != -1)
-      return fd;
-
-    if (errno != EINVAL)
-      return UV__ERR(errno);
-
-    /* O_CLOEXEC not supported. */
-    no_cloexec = 1;
-  }
-#endif
-
-  fd = open(path, flags);
-  if (fd == -1)
-    return UV__ERR(errno);
-
-  err = uv__cloexec(fd, 1);
-  if (err) {
-    uv__close(fd);
-    return err;
-  }
-
-  return fd;
-}
-
-
-int uv__dup2_cloexec(int oldfd, int newfd) {
-  int r;
-#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
-  r = dup3(oldfd, newfd, O_CLOEXEC);
-  if (r == -1)
-    return UV__ERR(errno);
-  return r;
-#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
-  r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
-  if (r != -1)
-    return r;
-  if (errno != EINVAL)
-    return UV__ERR(errno);
-  /* Fall through. */
-#elif defined(__linux__)
-  static int no_dup3;
-  if (!no_dup3) {
-    do
-      r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
-    while (r == -1 && errno == EBUSY);
-    if (r != -1)
-      return r;
-    if (errno != ENOSYS)
-      return UV__ERR(errno);
-    /* Fall through. */
-    no_dup3 = 1;
-  }
-#endif
-  {
-    int err;
-    do
-      r = dup2(oldfd, newfd);
-#if defined(__linux__)
-    while (r == -1 && errno == EBUSY);
-#else
-    while (0);  /* Never retry. */
-#endif
-
-    if (r == -1)
-      return UV__ERR(errno);
-
-    err = uv__cloexec(newfd, 1);
-    if (err) {
-      uv__close(newfd);
-      return err;
-    }
-
-    return r;
-  }
-}
-
-
-int uv_os_homedir(char* buffer, size_t* size) {
-  uv_passwd_t pwd;
-  size_t len;
-  int r;
-
-  /* Check if the HOME environment variable is set first. The task of
-     performing input validation on buffer and size is taken care of by
-     uv_os_getenv(). */
-  r = uv_os_getenv("HOME", buffer, size);
-
-  if (r != UV_ENOENT)
-    return r;
-
-  /* HOME is not set, so call uv__getpwuid_r() */
-  r = uv__getpwuid_r(&pwd);
-
-  if (r != 0) {
-    return r;
-  }
-
-  len = strlen(pwd.homedir);
-
-  if (len >= *size) {
-    *size = len + 1;
-    uv_os_free_passwd(&pwd);
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, pwd.homedir, len + 1);
-  *size = len;
-  uv_os_free_passwd(&pwd);
-
-  return 0;
-}
-
-
-int uv_os_tmpdir(char* buffer, size_t* size) {
-  const char* buf;
-  size_t len;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-#define CHECK_ENV_VAR(name)                                                   \
-  do {                                                                        \
-    buf = getenv(name);                                                       \
-    if (buf != NULL)                                                          \
-      goto return_buffer;                                                     \
-  }                                                                           \
-  while (0)
-
-  /* Check the TMPDIR, TMP, TEMP, and TEMPDIR environment variables in order */
-  CHECK_ENV_VAR("TMPDIR");
-  CHECK_ENV_VAR("TMP");
-  CHECK_ENV_VAR("TEMP");
-  CHECK_ENV_VAR("TEMPDIR");
-
-#undef CHECK_ENV_VAR
-
-  /* No temp environment variables defined */
-  #if defined(__ANDROID__)
-    buf = "/data/local/tmp";
-  #else
-    buf = "/tmp";
-  #endif
-
-return_buffer:
-  len = strlen(buf);
-
-  if (len >= *size) {
-    *size = len + 1;
-    return UV_ENOBUFS;
-  }
-
-  /* The returned directory should not have a trailing slash. */
-  if (len > 1 && buf[len - 1] == '/') {
-    len--;
-  }
-
-  memcpy(buffer, buf, len + 1);
-  buffer[len] = '\0';
-  *size = len;
-
-  return 0;
-}
-
-
-int uv__getpwuid_r(uv_passwd_t* pwd) {
-  struct passwd pw;
-  struct passwd* result;
-  char* buf;
-  uid_t uid;
-  size_t bufsize;
-  size_t name_size;
-  size_t homedir_size;
-  size_t shell_size;
-  long initsize;
-  int r;
-#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
-  int (*getpwuid_r)(uid_t, struct passwd*, char*, size_t, struct passwd**);
-
-  getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
-  if (getpwuid_r == NULL)
-    return UV_ENOSYS;
-#endif
-
-  if (pwd == NULL)
-    return UV_EINVAL;
-
-  initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
-
-  if (initsize <= 0)
-    bufsize = 4096;
-  else
-    bufsize = (size_t) initsize;
-
-  uid = geteuid();
-  buf = NULL;
-
-  for (;;) {
-    uv__free(buf);
-    buf = (char*)uv__malloc(bufsize);
-
-    if (buf == NULL)
-      return UV_ENOMEM;
-
-    r = getpwuid_r(uid, &pw, buf, bufsize, &result);
-
-    if (r != ERANGE)
-      break;
-
-    bufsize *= 2;
-  }
-
-  if (r != 0) {
-    uv__free(buf);
-    return -r;
-  }
-
-  if (result == NULL) {
-    uv__free(buf);
-    return UV_ENOENT;
-  }
-
-  /* Allocate memory for the username, shell, and home directory */
-  name_size = strlen(pw.pw_name) + 1;
-  homedir_size = strlen(pw.pw_dir) + 1;
-  shell_size = strlen(pw.pw_shell) + 1;
-  pwd->username = (char*)uv__malloc(name_size + homedir_size + shell_size);
-
-  if (pwd->username == NULL) {
-    uv__free(buf);
-    return UV_ENOMEM;
-  }
-
-  /* Copy the username */
-  memcpy(pwd->username, pw.pw_name, name_size);
-
-  /* Copy the home directory */
-  pwd->homedir = pwd->username + name_size;
-  memcpy(pwd->homedir, pw.pw_dir, homedir_size);
-
-  /* Copy the shell */
-  pwd->shell = pwd->homedir + homedir_size;
-  memcpy(pwd->shell, pw.pw_shell, shell_size);
-
-  /* Copy the uid and gid */
-  pwd->uid = pw.pw_uid;
-  pwd->gid = pw.pw_gid;
-
-  uv__free(buf);
-
-  return 0;
-}
-
-
-void uv_os_free_passwd(uv_passwd_t* pwd) {
-  if (pwd == NULL)
-    return;
-
-  /*
-    The memory for name, shell, and homedir are allocated in a single
-    uv__malloc() call. The base of the pointer is stored in pwd->username, so
-    that is the field that needs to be freed.
-  */
-  uv__free(pwd->username);
-  pwd->username = NULL;
-  pwd->shell = NULL;
-  pwd->homedir = NULL;
-}
-
-
-int uv_os_get_passwd(uv_passwd_t* pwd) {
-  return uv__getpwuid_r(pwd);
-}
-
-
-int uv_translate_sys_error(int sys_errno) {
-  /* If < 0 then it's already a libuv error. */
-  return sys_errno <= 0 ? sys_errno : -sys_errno;
-}
-
-
-int uv_os_getenv(const char* name, char* buffer, size_t* size) {
-  char* var;
-  size_t len;
-
-  if (name == NULL || buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  var = getenv(name);
-
-  if (var == NULL)
-    return UV_ENOENT;
-
-  len = strlen(var);
-
-  if (len >= *size) {
-    *size = len + 1;
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, var, len + 1);
-  *size = len;
-
-  return 0;
-}
-
-
-int uv_os_setenv(const char* name, const char* value) {
-  if (name == NULL || value == NULL)
-    return UV_EINVAL;
-
-  if (setenv(name, value, 1) != 0)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-int uv_os_unsetenv(const char* name) {
-  if (name == NULL)
-    return UV_EINVAL;
-
-  if (unsetenv(name) != 0)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-int uv_os_gethostname(char* buffer, size_t* size) {
-  /*
-    On some platforms, if the input buffer is not large enough, gethostname()
-    succeeds, but truncates the result. libuv can detect this and return ENOBUFS
-    instead by creating a large enough buffer and comparing the hostname length
-    to the size input.
-  */
-  char buf[UV_MAXHOSTNAMESIZE];
-  size_t len;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  if (gethostname(buf, sizeof(buf)) != 0)
-    return UV__ERR(errno);
-
-  buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
-  len = strlen(buf);
-
-  if (len >= *size) {
-    *size = len + 1;
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, buf, len + 1);
-  *size = len;
-  return 0;
-}
-
-
-uv_os_fd_t uv_get_osfhandle(int fd) {
-  return fd;
-}
-
-int uv_open_osfhandle(uv_os_fd_t os_fd) {
-  return os_fd;
-}
-
-uv_pid_t uv_os_getpid(void) {
-  return getpid();
-}
-
-
-uv_pid_t uv_os_getppid(void) {
-  return getppid();
-}
-
-
-int uv_os_getpriority(uv_pid_t pid, int* priority) {
-  int r;
-
-  if (priority == NULL)
-    return UV_EINVAL;
-
-  errno = 0;
-  r = getpriority(PRIO_PROCESS, (int) pid);
-
-  if (r == -1 && errno != 0)
-    return UV__ERR(errno);
-
-  *priority = r;
-  return 0;
-}
-
-
-int uv_os_setpriority(uv_pid_t pid, int priority) {
-  if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
-    return UV_EINVAL;
-
-  if (setpriority(PRIO_PROCESS, (int) pid, priority) != 0)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-int uv_os_uname(uv_utsname_t* buffer) {
-  struct utsname buf;
-  int r;
-
-  if (buffer == NULL)
-    return UV_EINVAL;
-
-  if (uname(&buf) == -1) {
-    r = UV__ERR(errno);
-    goto error;
-  }
-
-  r = uv__strscpy(buffer->sysname, buf.sysname, sizeof(buffer->sysname));
-  if (r == UV_E2BIG)
-    goto error;
-
-#ifdef _AIX
-  r = snprintf(buffer->release,
-               sizeof(buffer->release),
-               "%s.%s",
-               buf.version,
-               buf.release);
-  if (r >= sizeof(buffer->release)) {
-    r = UV_E2BIG;
-    goto error;
-  }
-#else
-  r = uv__strscpy(buffer->release, buf.release, sizeof(buffer->release));
-  if (r == UV_E2BIG)
-    goto error;
-#endif
-
-  r = uv__strscpy(buffer->version, buf.version, sizeof(buffer->version));
-  if (r == UV_E2BIG)
-    goto error;
-
-#if defined(_AIX) || defined(__PASE__)
-  r = uv__strscpy(buffer->machine, "ppc64", sizeof(buffer->machine));
-#else
-  r = uv__strscpy(buffer->machine, buf.machine, sizeof(buffer->machine));
-#endif
-
-  if (r == UV_E2BIG)
-    goto error;
-
-  return 0;
-
-error:
-  buffer->sysname[0] = '\0';
-  buffer->release[0] = '\0';
-  buffer->version[0] = '\0';
-  buffer->machine[0] = '\0';
-  return r;
-}
-
-int uv__getsockpeername(const uv_handle_t* handle,
-                        uv__peersockfunc func,
-                        struct sockaddr* name,
-                        int* namelen) {
-  socklen_t socklen;
-  uv_os_fd_t fd;
-  int r;
-
-  r = uv_fileno(handle, &fd);
-  if (r < 0)
-    return r;
-
-  /* sizeof(socklen_t) != sizeof(int) on some systems. */
-  socklen = (socklen_t) *namelen;
-
-  if (func(fd, name, &socklen))
-    return UV__ERR(errno);
-
-  *namelen = (int) socklen;
-  return 0;
-}
-
-int uv_gettimeofday(uv_timeval64_t* tv) {
-  struct timeval time;
-
-  if (tv == NULL)
-    return UV_EINVAL;
-
-  if (gettimeofday(&time, NULL) != 0)
-    return UV__ERR(errno);
-
-  tv->tv_sec = (int64_t) time.tv_sec;
-  tv->tv_usec = (int32_t) time.tv_usec;
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/cygwin.cpp b/wpiutil/src/main/native/libuv/src/unix/cygwin.cpp
deleted file mode 100644
index 6b5cfb7..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/cygwin.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <sys/sysinfo.h>
-#include <unistd.h>
-
-int uv_uptime(double* uptime) {
-  struct sysinfo info;
-
-  if (sysinfo(&info) < 0)
-    return UV__ERR(errno);
-
-  *uptime = info.uptime;
-  return 0;
-}
-
-int uv_resident_set_memory(size_t* rss) {
-  /* FIXME: read /proc/meminfo? */
-  *rss = 0;
-  return 0;
-}
-
-int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
-  /* FIXME: read /proc/stat? */
-  *cpu_infos = NULL;
-  *count = 0;
-  return UV_ENOSYS;
-}
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
-  (void)cpu_infos;
-  (void)count;
-}
-
-uint64_t uv_get_constrained_memory(void) {
-  return 0;  /* Memory constraints are unknown. */
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/darwin-proctitle.cpp b/wpiutil/src/main/native/libuv/src/unix/darwin-proctitle.cpp
deleted file mode 100644
index f05d9f9..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/darwin-proctitle.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <TargetConditionals.h>
-
-#if !TARGET_OS_IPHONE
-# include <CoreFoundation/CoreFoundation.h>
-# include <ApplicationServices/ApplicationServices.h>
-#endif
-
-#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
-
-
-static int (*dynamic_pthread_setname_np)(const char* name);
-#if !TARGET_OS_IPHONE
-static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
-                                                 const char*,
-                                                 CFStringEncoding);
-static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
-static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
-static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
-static CFTypeRef (*pLSGetCurrentApplicationASN)(void);
-static OSStatus (*pLSSetApplicationInformationItem)(int,
-                                                    CFTypeRef,
-                                                    CFStringRef,
-                                                    CFStringRef,
-                                                    CFDictionaryRef*);
-static void* application_services_handle;
-static void* core_foundation_handle;
-static CFBundleRef launch_services_bundle;
-static CFStringRef* display_name_key;
-static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
-static CFBundleRef (*pCFBundleGetMainBundle)(void);
-static CFBundleRef hi_services_bundle;
-static OSStatus (*pSetApplicationIsDaemon)(int);
-static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
-static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
-                                                                     void*);
-
-
-UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) {
-  if (core_foundation_handle != NULL) {
-    dlclose(core_foundation_handle);
-    core_foundation_handle = NULL;
-  }
-
-  if (application_services_handle != NULL) {
-    dlclose(application_services_handle);
-    application_services_handle = NULL;
-  }
-}
-#endif  /* !TARGET_OS_IPHONE */
-
-
-void uv__set_process_title_platform_init(void) {
-  /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */
-  *(void **)(&dynamic_pthread_setname_np) =
-      dlsym(RTLD_DEFAULT, "pthread_setname_np");
-
-#if !TARGET_OS_IPHONE
-  application_services_handle = dlopen("/System/Library/Frameworks/"
-                                       "ApplicationServices.framework/"
-                                       "Versions/A/ApplicationServices",
-                                       RTLD_LAZY | RTLD_LOCAL);
-  core_foundation_handle = dlopen("/System/Library/Frameworks/"
-                                  "CoreFoundation.framework/"
-                                  "Versions/A/CoreFoundation",
-                                  RTLD_LAZY | RTLD_LOCAL);
-
-  if (application_services_handle == NULL || core_foundation_handle == NULL)
-    goto out;
-
-  *(void **)(&pCFStringCreateWithCString) =
-      dlsym(core_foundation_handle, "CFStringCreateWithCString");
-  *(void **)(&pCFBundleGetBundleWithIdentifier) =
-      dlsym(core_foundation_handle, "CFBundleGetBundleWithIdentifier");
-  *(void **)(&pCFBundleGetDataPointerForName) =
-      dlsym(core_foundation_handle, "CFBundleGetDataPointerForName");
-  *(void **)(&pCFBundleGetFunctionPointerForName) =
-      dlsym(core_foundation_handle, "CFBundleGetFunctionPointerForName");
-
-  if (pCFStringCreateWithCString == NULL ||
-      pCFBundleGetBundleWithIdentifier == NULL ||
-      pCFBundleGetDataPointerForName == NULL ||
-      pCFBundleGetFunctionPointerForName == NULL) {
-    goto out;
-  }
-
-  launch_services_bundle =
-      pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices"));
-
-  if (launch_services_bundle == NULL)
-    goto out;
-
-  *(void **)(&pLSGetCurrentApplicationASN) =
-      pCFBundleGetFunctionPointerForName(launch_services_bundle,
-                                         S("_LSGetCurrentApplicationASN"));
-
-  if (pLSGetCurrentApplicationASN == NULL)
-    goto out;
-
-  *(void **)(&pLSSetApplicationInformationItem) =
-      pCFBundleGetFunctionPointerForName(launch_services_bundle,
-                                         S("_LSSetApplicationInformationItem"));
-
-  if (pLSSetApplicationInformationItem == NULL)
-    goto out;
-
-  display_name_key = (CFStringRef*)
-      pCFBundleGetDataPointerForName(launch_services_bundle,
-                                     S("_kLSDisplayNameKey"));
-
-  if (display_name_key == NULL || *display_name_key == NULL)
-    goto out;
-
-  *(void **)(&pCFBundleGetInfoDictionary) = dlsym(core_foundation_handle,
-                                     "CFBundleGetInfoDictionary");
-  *(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle,
-                                 "CFBundleGetMainBundle");
-
-  if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL)
-    goto out;
-
-  /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
-  hi_services_bundle =
-      pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
-
-  if (hi_services_bundle == NULL)
-    goto out;
-
-  *(void **)(&pSetApplicationIsDaemon) = pCFBundleGetFunctionPointerForName(
-      hi_services_bundle,
-      S("SetApplicationIsDaemon"));
-  *(void **)(&pLSApplicationCheckIn) = pCFBundleGetFunctionPointerForName(
-      launch_services_bundle,
-      S("_LSApplicationCheckIn"));
-  *(void **)(&pLSSetApplicationLaunchServicesServerConnectionStatus) =
-      pCFBundleGetFunctionPointerForName(
-          launch_services_bundle,
-          S("_LSSetApplicationLaunchServicesServerConnectionStatus"));
-
-  if (pSetApplicationIsDaemon == NULL ||
-      pLSApplicationCheckIn == NULL ||
-      pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) {
-    goto out;
-  }
-
-  return;
-
-out:
-  uv__set_process_title_platform_fini();
-#endif  /* !TARGET_OS_IPHONE */
-}
-
-
-void uv__set_process_title(const char* title) {
-#if !TARGET_OS_IPHONE
-  if (core_foundation_handle != NULL && pSetApplicationIsDaemon(1) != noErr) {
-    CFTypeRef asn;
-    pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
-    pLSApplicationCheckIn(/* Magic value */ -2,
-                          pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
-    asn = pLSGetCurrentApplicationASN();
-    pLSSetApplicationInformationItem(/* Magic value */ -2, asn,
-                                     *display_name_key, S(title), NULL);
-  }
-#endif  /* !TARGET_OS_IPHONE */
-
-  if (dynamic_pthread_setname_np != NULL) {
-    char namebuf[64];  /* MAXTHREADNAMESIZE */
-    uv__strscpy(namebuf, title, sizeof(namebuf));
-    dynamic_pthread_setname_np(namebuf);
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/darwin.cpp b/wpiutil/src/main/native/libuv/src/unix/darwin.cpp
deleted file mode 100644
index 2282d91..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/darwin.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <errno.h>
-
-#include <mach/mach.h>
-#include <mach/mach_time.h>
-#include <mach-o/dyld.h> /* _NSGetExecutablePath */
-#include <sys/resource.h>
-#include <sys/sysctl.h>
-#include <unistd.h>  /* sysconf */
-
-
-int uv__platform_loop_init(uv_loop_t* loop) {
-  loop->cf_state = NULL;
-
-  if (uv__kqueue_init(loop))
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-void uv__platform_loop_delete(uv_loop_t* loop) {
-  uv__fsevents_loop_delete(loop);
-}
-
-
-uint64_t uv__hrtime(uv_clocktype_t type) {
-  static mach_timebase_info_data_t info;
-
-  if ((ACCESS_ONCE(uint32_t, info.numer) == 0 ||
-       ACCESS_ONCE(uint32_t, info.denom) == 0) &&
-      mach_timebase_info(&info) != KERN_SUCCESS)
-    abort();
-
-  return mach_absolute_time() * info.numer / info.denom;
-}
-
-
-int uv_exepath(char* buffer, size_t* size) {
-  /* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */
-  char abspath[PATH_MAX * 2 + 1];
-  char exepath[PATH_MAX + 1];
-  uint32_t exepath_size;
-  size_t abspath_size;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  exepath_size = sizeof(exepath);
-  if (_NSGetExecutablePath(exepath, &exepath_size))
-    return UV_EIO;
-
-  if (realpath(exepath, abspath) != abspath)
-    return UV__ERR(errno);
-
-  abspath_size = strlen(abspath);
-  if (abspath_size == 0)
-    return UV_EIO;
-
-  *size -= 1;
-  if (*size > abspath_size)
-    *size = abspath_size;
-
-  memcpy(buffer, abspath, *size);
-  buffer[*size] = '\0';
-
-  return 0;
-}
-
-
-uint64_t uv_get_free_memory(void) {
-  vm_statistics_data_t info;
-  mach_msg_type_number_t count = sizeof(info) / sizeof(integer_t);
-
-  if (host_statistics(mach_host_self(), HOST_VM_INFO,
-                      (host_info_t)&info, &count) != KERN_SUCCESS) {
-    return UV_EINVAL;  /* FIXME(bnoordhuis) Translate error. */
-  }
-
-  return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE);
-}
-
-
-uint64_t uv_get_total_memory(void) {
-  uint64_t info;
-  int which[] = {CTL_HW, HW_MEMSIZE};
-  size_t size = sizeof(info);
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  return (uint64_t) info;
-}
-
-
-uint64_t uv_get_constrained_memory(void) {
-  return 0;  /* Memory constraints are unknown. */
-}
-
-
-void uv_loadavg(double avg[3]) {
-  struct loadavg info;
-  size_t size = sizeof(info);
-  int which[] = {CTL_VM, VM_LOADAVG};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return;
-
-  avg[0] = (double) info.ldavg[0] / info.fscale;
-  avg[1] = (double) info.ldavg[1] / info.fscale;
-  avg[2] = (double) info.ldavg[2] / info.fscale;
-}
-
-
-int uv_resident_set_memory(size_t* rss) {
-  mach_msg_type_number_t count;
-  task_basic_info_data_t info;
-  kern_return_t err;
-
-  count = TASK_BASIC_INFO_COUNT;
-  err = task_info(mach_task_self(),
-                  TASK_BASIC_INFO,
-                  (task_info_t) &info,
-                  &count);
-  (void) &err;
-  /* task_info(TASK_BASIC_INFO) cannot really fail. Anything other than
-   * KERN_SUCCESS implies a libuv bug.
-   */
-  assert(err == KERN_SUCCESS);
-  *rss = info.resident_size;
-
-  return 0;
-}
-
-
-int uv_uptime(double* uptime) {
-  time_t now;
-  struct timeval info;
-  size_t size = sizeof(info);
-  static int which[] = {CTL_KERN, KERN_BOOTTIME};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  now = time(NULL);
-  *uptime = now - info.tv_sec;
-
-  return 0;
-}
-
-int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
-  unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
-               multiplier = ((uint64_t)1000L / ticks);
-  char model[512];
-  uint64_t cpuspeed;
-  size_t size;
-  unsigned int i;
-  natural_t numcpus;
-  mach_msg_type_number_t msg_type;
-  processor_cpu_load_info_data_t *info;
-  uv_cpu_info_t* cpu_info;
-
-  size = sizeof(model);
-  if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) &&
-      sysctlbyname("hw.model", &model, &size, NULL, 0)) {
-    return UV__ERR(errno);
-  }
-
-  size = sizeof(cpuspeed);
-  if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
-                          (processor_info_array_t*)&info,
-                          &msg_type) != KERN_SUCCESS) {
-    return UV_EINVAL;  /* FIXME(bnoordhuis) Translate error. */
-  }
-
-  *cpu_infos = (uv_cpu_info_t*)uv__malloc(numcpus * sizeof(**cpu_infos));
-  if (!(*cpu_infos)) {
-    vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
-    return UV_ENOMEM;
-  }
-
-  *count = numcpus;
-
-  for (i = 0; i < numcpus; i++) {
-    cpu_info = &(*cpu_infos)[i];
-
-    cpu_info->cpu_times.user = (uint64_t)(info[i].cpu_ticks[0]) * multiplier;
-    cpu_info->cpu_times.nice = (uint64_t)(info[i].cpu_ticks[3]) * multiplier;
-    cpu_info->cpu_times.sys = (uint64_t)(info[i].cpu_ticks[1]) * multiplier;
-    cpu_info->cpu_times.idle = (uint64_t)(info[i].cpu_ticks[2]) * multiplier;
-    cpu_info->cpu_times.irq = 0;
-
-    cpu_info->model = uv__strdup(model);
-    cpu_info->speed = cpuspeed/1000000;
-  }
-  vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
-
-  return 0;
-}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(cpu_infos[i].model);
-  }
-
-  uv__free(cpu_infos);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/dl.cpp b/wpiutil/src/main/native/libuv/src/unix/dl.cpp
deleted file mode 100644
index fc1c052..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/dl.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <string.h>
-#include <locale.h>
-
-static int uv__dlerror(uv_lib_t* lib);
-
-
-int uv_dlopen(const char* filename, uv_lib_t* lib) {
-  dlerror(); /* Reset error status. */
-  lib->errmsg = NULL;
-  lib->handle = dlopen(filename, RTLD_LAZY);
-  return lib->handle ? 0 : uv__dlerror(lib);
-}
-
-
-void uv_dlclose(uv_lib_t* lib) {
-  uv__free(lib->errmsg);
-  lib->errmsg = NULL;
-
-  if (lib->handle) {
-    /* Ignore errors. No good way to signal them without leaking memory. */
-    dlclose(lib->handle);
-    lib->handle = NULL;
-  }
-}
-
-
-int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
-  dlerror(); /* Reset error status. */
-  *ptr = dlsym(lib->handle, name);
-  return uv__dlerror(lib);
-}
-
-
-const char* uv_dlerror(const uv_lib_t* lib) {
-  return lib->errmsg ? lib->errmsg : "no error";
-}
-
-
-static int uv__dlerror(uv_lib_t* lib) {
-  const char* errmsg;
-
-  uv__free(lib->errmsg);
-
-  errmsg = dlerror();
-
-  if (errmsg) {
-    lib->errmsg = uv__strdup(errmsg);
-    return -1;
-  }
-  else {
-    lib->errmsg = NULL;
-    return 0;
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/freebsd.cpp b/wpiutil/src/main/native/libuv/src/unix/freebsd.cpp
deleted file mode 100644
index c401145..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/freebsd.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-
-#include <paths.h>
-#include <sys/user.h>
-#include <sys/types.h>
-#include <sys/resource.h>
-#include <sys/sysctl.h>
-#include <vm/vm_param.h> /* VM_LOADAVG */
-#include <time.h>
-#include <stdlib.h>
-#include <unistd.h> /* sysconf */
-#include <fcntl.h>
-
-#ifndef CPUSTATES
-# define CPUSTATES 5U
-#endif
-#ifndef CP_USER
-# define CP_USER 0
-# define CP_NICE 1
-# define CP_SYS 2
-# define CP_IDLE 3
-# define CP_INTR 4
-#endif
-
-
-int uv__platform_loop_init(uv_loop_t* loop) {
-  return uv__kqueue_init(loop);
-}
-
-
-void uv__platform_loop_delete(uv_loop_t* loop) {
-}
-
-
-#ifdef __DragonFly__
-int uv_exepath(char* buffer, size_t* size) {
-  char abspath[PATH_MAX * 2 + 1];
-  ssize_t abspath_size;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  abspath_size = readlink("/proc/curproc/file", abspath, sizeof(abspath));
-  if (abspath_size < 0)
-    return UV__ERR(errno);
-
-  assert(abspath_size > 0);
-  *size -= 1;
-
-  if (*size > abspath_size)
-    *size = abspath_size;
-
-  memcpy(buffer, abspath, *size);
-  buffer[*size] = '\0';
-
-  return 0;
-}
-#else
-int uv_exepath(char* buffer, size_t* size) {
-  char abspath[PATH_MAX * 2 + 1];
-  int mib[4];
-  size_t abspath_size;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC;
-  mib[2] = KERN_PROC_PATHNAME;
-  mib[3] = -1;
-
-  abspath_size = sizeof abspath;
-  if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0))
-    return UV__ERR(errno);
-
-  assert(abspath_size > 0);
-  abspath_size -= 1;
-  *size -= 1;
-
-  if (*size > abspath_size)
-    *size = abspath_size;
-
-  memcpy(buffer, abspath, *size);
-  buffer[*size] = '\0';
-
-  return 0;
-}
-#endif
-
-uint64_t uv_get_free_memory(void) {
-  int freecount;
-  size_t size = sizeof(freecount);
-
-  if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  return (uint64_t) freecount * sysconf(_SC_PAGESIZE);
-
-}
-
-
-uint64_t uv_get_total_memory(void) {
-  unsigned long info;
-  int which[] = {CTL_HW, HW_PHYSMEM};
-
-  size_t size = sizeof(info);
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  return (uint64_t) info;
-}
-
-
-uint64_t uv_get_constrained_memory(void) {
-  return 0;  /* Memory constraints are unknown. */
-}
-
-
-void uv_loadavg(double avg[3]) {
-  struct loadavg info;
-  size_t size = sizeof(info);
-  int which[] = {CTL_VM, VM_LOADAVG};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return;
-
-  avg[0] = (double) info.ldavg[0] / info.fscale;
-  avg[1] = (double) info.ldavg[1] / info.fscale;
-  avg[2] = (double) info.ldavg[2] / info.fscale;
-}
-
-
-int uv_resident_set_memory(size_t* rss) {
-  struct kinfo_proc kinfo;
-  size_t page_size;
-  size_t kinfo_size;
-  int mib[4];
-
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC;
-  mib[2] = KERN_PROC_PID;
-  mib[3] = getpid();
-
-  kinfo_size = sizeof(kinfo);
-
-  if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0))
-    return UV__ERR(errno);
-
-  page_size = getpagesize();
-
-#ifdef __DragonFly__
-  *rss = kinfo.kp_vm_rssize * page_size;
-#else
-  *rss = kinfo.ki_rssize * page_size;
-#endif
-
-  return 0;
-}
-
-
-int uv_uptime(double* uptime) {
-  int r;
-  struct timespec sp;
-  r = clock_gettime(CLOCK_MONOTONIC, &sp);
-  if (r)
-    return UV__ERR(errno);
-
-  *uptime = sp.tv_sec;
-  return 0;
-}
-
-
-int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
-  unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
-               multiplier = ((uint64_t)1000L / ticks), cpuspeed, maxcpus,
-               cur = 0;
-  uv_cpu_info_t* cpu_info;
-  const char* maxcpus_key;
-  const char* cptimes_key;
-  const char* model_key;
-  char model[512];
-  long* cp_times;
-  int numcpus;
-  size_t size;
-  int i;
-
-#if defined(__DragonFly__)
-  /* This is not quite correct but DragonFlyBSD doesn't seem to have anything
-   * comparable to kern.smp.maxcpus or kern.cp_times (kern.cp_time is a total,
-   * not per CPU). At least this stops uv_cpu_info() from failing completely.
-   */
-  maxcpus_key = "hw.ncpu";
-  cptimes_key = "kern.cp_time";
-#else
-  maxcpus_key = "kern.smp.maxcpus";
-  cptimes_key = "kern.cp_times";
-#endif
-
-#if defined(__arm__) || defined(__aarch64__)
-  /* The key hw.model and hw.clockrate are not available on FreeBSD ARM. */
-  model_key = "hw.machine";
-  cpuspeed = 0;
-#else
-  model_key = "hw.model";
-
-  size = sizeof(cpuspeed);
-  if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0))
-    return -errno;
-#endif
-
-  size = sizeof(model);
-  if (sysctlbyname(model_key, &model, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  size = sizeof(numcpus);
-  if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  *cpu_infos = (uv_cpu_info_t*)uv__malloc(numcpus * sizeof(**cpu_infos));
-  if (!(*cpu_infos))
-    return UV_ENOMEM;
-
-  *count = numcpus;
-
-  /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of
-   * ncpu.
-   */
-  size = sizeof(maxcpus);
-  if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) {
-    uv__free(*cpu_infos);
-    return UV__ERR(errno);
-  }
-
-  size = maxcpus * CPUSTATES * sizeof(long);
-
-  cp_times = (long*)uv__malloc(size);
-  if (cp_times == NULL) {
-    uv__free(*cpu_infos);
-    return UV_ENOMEM;
-  }
-
-  if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) {
-    uv__free(cp_times);
-    uv__free(*cpu_infos);
-    return UV__ERR(errno);
-  }
-
-  for (i = 0; i < numcpus; i++) {
-    cpu_info = &(*cpu_infos)[i];
-
-    cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier;
-    cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier;
-    cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier;
-    cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier;
-    cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier;
-
-    cpu_info->model = uv__strdup(model);
-    cpu_info->speed = cpuspeed;
-
-    cur+=CPUSTATES;
-  }
-
-  uv__free(cp_times);
-  return 0;
-}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(cpu_infos[i].model);
-  }
-
-  uv__free(cpu_infos);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/fs.cpp b/wpiutil/src/main/native/libuv/src/unix/fs.cpp
deleted file mode 100644
index 36871ee..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/fs.cpp
+++ /dev/null
@@ -1,1860 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/* Caveat emptor: this file deviates from the libuv convention of returning
- * negated errno codes. Most uv_fs_*() functions map directly to the system
- * call of the same name. For more complex wrappers, it's easier to just
- * return -1 with errno set. The dispatcher in uv__fs_work() takes care of
- * getting the errno to the right place (req->result or as the return value.)
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h> /* PATH_MAX */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/uio.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <poll.h>
-
-#if defined(__DragonFly__)        ||                                      \
-    defined(__FreeBSD__)          ||                                      \
-    defined(__FreeBSD_kernel__)   ||                                      \
-    defined(__OpenBSD__)          ||                                      \
-    defined(__NetBSD__)
-# define HAVE_PREADV 1
-#else
-# define HAVE_PREADV 0
-#endif
-
-#if defined(__linux__) || defined(__sun)
-# include <sys/sendfile.h>
-#endif
-
-#if defined(__APPLE__)
-# include <sys/sysctl.h>
-#elif defined(__linux__) && !defined(FICLONE)
-# include <sys/ioctl.h>
-# define FICLONE _IOW(0x94, 9, int)
-#endif
-
-#if defined(_AIX) && !defined(_AIX71)
-# include <utime.h>
-#endif
-
-#if defined(_AIX) && _XOPEN_SOURCE <= 600
-extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
-#endif
-
-#define INIT(subtype)                                                         \
-  do {                                                                        \
-    if (req == NULL)                                                          \
-      return UV_EINVAL;                                                       \
-    UV_REQ_INIT(req, UV_FS);                                                  \
-    req->fs_type = UV_FS_ ## subtype;                                         \
-    req->result = 0;                                                          \
-    req->ptr = NULL;                                                          \
-    req->loop = loop;                                                         \
-    req->path = NULL;                                                         \
-    req->new_path = NULL;                                                     \
-    req->bufs = NULL;                                                         \
-    req->cb = cb;                                                             \
-  }                                                                           \
-  while (0)
-
-#define PATH                                                                  \
-  do {                                                                        \
-    assert(path != NULL);                                                     \
-    if (cb == NULL) {                                                         \
-      req->path = path;                                                       \
-    } else {                                                                  \
-      req->path = uv__strdup(path);                                           \
-      if (req->path == NULL)                                                  \
-        return UV_ENOMEM;                                                     \
-    }                                                                         \
-  }                                                                           \
-  while (0)
-
-#define PATH2                                                                 \
-  do {                                                                        \
-    if (cb == NULL) {                                                         \
-      req->path = path;                                                       \
-      req->new_path = new_path;                                               \
-    } else {                                                                  \
-      size_t path_len;                                                        \
-      size_t new_path_len;                                                    \
-      path_len = strlen(path) + 1;                                            \
-      new_path_len = strlen(new_path) + 1;                                    \
-      req->path = (char*)uv__malloc(path_len + new_path_len);                 \
-      if (req->path == NULL)                                                  \
-        return UV_ENOMEM;                                                     \
-      req->new_path = req->path + path_len;                                   \
-      memcpy((void*) req->path, path, path_len);                              \
-      memcpy((void*) req->new_path, new_path, new_path_len);                  \
-    }                                                                         \
-  }                                                                           \
-  while (0)
-
-#define POST                                                                  \
-  do {                                                                        \
-    if (cb != NULL) {                                                         \
-      uv__req_register(loop, req);                                            \
-      uv__work_submit(loop,                                                   \
-                      &req->work_req,                                         \
-                      UV__WORK_FAST_IO,                                       \
-                      uv__fs_work,                                            \
-                      uv__fs_done);                                           \
-      return 0;                                                               \
-    }                                                                         \
-    else {                                                                    \
-      uv__fs_work(&req->work_req);                                            \
-      return req->result;                                                     \
-    }                                                                         \
-  }                                                                           \
-  while (0)
-
-
-static int uv__fs_close(int fd) {
-  int rc;
-
-  rc = uv__close_nocancel(fd);
-  if (rc == -1)
-    if (errno == EINTR || errno == EINPROGRESS)
-      rc = 0;  /* The close is in progress, not an error. */
-
-  return rc;
-}
-
-
-static ssize_t uv__fs_fsync(uv_fs_t* req) {
-#if defined(__APPLE__)
-  /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
-   * to the drive platters. This is in contrast to Linux's fdatasync and fsync
-   * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
-   * for flushing buffered data to permanent storage. If F_FULLFSYNC is not
-   * supported by the file system we fall back to F_BARRIERFSYNC or fsync().
-   * This is the same approach taken by sqlite, except sqlite does not issue
-   * an F_BARRIERFSYNC call.
-   */
-  int r;
-
-  r = fcntl(req->file, F_FULLFSYNC);
-  if (r != 0)
-    r = fcntl(req->file, 85 /* F_BARRIERFSYNC */);  /* fsync + barrier */
-  if (r != 0)
-    r = fsync(req->file);
-  return r;
-#else
-  return fsync(req->file);
-#endif
-}
-
-
-static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
-#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
-  return fdatasync(req->file);
-#elif defined(__APPLE__)
-  /* See the comment in uv__fs_fsync. */
-  return uv__fs_fsync(req);
-#else
-  return fsync(req->file);
-#endif
-}
-
-
-static ssize_t uv__fs_futime(uv_fs_t* req) {
-#if defined(__linux__)                                                        \
-    || defined(_AIX71)                                                        \
-    || defined(__HAIKU__)
-  /* utimesat() has nanosecond resolution but we stick to microseconds
-   * for the sake of consistency with other platforms.
-   */
-  struct timespec ts[2];
-  ts[0].tv_sec  = req->atime;
-  ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
-  ts[1].tv_sec  = req->mtime;
-  ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
-  return futimens(req->file, ts);
-#elif defined(__APPLE__)                                                      \
-    || defined(__DragonFly__)                                                 \
-    || defined(__FreeBSD__)                                                   \
-    || defined(__FreeBSD_kernel__)                                            \
-    || defined(__NetBSD__)                                                    \
-    || defined(__OpenBSD__)                                                   \
-    || defined(__sun)
-  struct timeval tv[2];
-  tv[0].tv_sec  = req->atime;
-  tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
-  tv[1].tv_sec  = req->mtime;
-  tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
-# if defined(__sun)
-  return futimesat(req->file, NULL, tv);
-# else
-  return futimes(req->file, tv);
-# endif
-#elif defined(__MVS__)
-  attrib_t atr;
-  memset(&atr, 0, sizeof(atr));
-  atr.att_mtimechg = 1;
-  atr.att_atimechg = 1;
-  atr.att_mtime = req->mtime;
-  atr.att_atime = req->atime;
-  return __fchattr(req->file, &atr, sizeof(atr));
-#else
-  errno = ENOSYS;
-  return -1;
-#endif
-}
-
-
-static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
-  return mkdtemp((char*) req->path) ? 0 : -1;
-}
-
-
-static ssize_t uv__fs_open(uv_fs_t* req) {
-  static int no_cloexec_support;
-  int r;
-
-  /* Try O_CLOEXEC before entering locks */
-  if (no_cloexec_support == 0) {
-#ifdef O_CLOEXEC
-    r = open(req->path, req->flags | O_CLOEXEC, req->mode);
-    if (r >= 0)
-      return r;
-    if (errno != EINVAL)
-      return r;
-    no_cloexec_support = 1;
-#endif  /* O_CLOEXEC */
-  }
-
-  if (req->cb != NULL)
-    uv_rwlock_rdlock(&req->loop->cloexec_lock);
-
-  r = open(req->path, req->flags, req->mode);
-
-  /* In case of failure `uv__cloexec` will leave error in `errno`,
-   * so it is enough to just set `r` to `-1`.
-   */
-  if (r >= 0 && uv__cloexec(r, 1) != 0) {
-    r = uv__close(r);
-    if (r != 0)
-      abort();
-    r = -1;
-  }
-
-  if (req->cb != NULL)
-    uv_rwlock_rdunlock(&req->loop->cloexec_lock);
-
-  return r;
-}
-
-
-static ssize_t uv__fs_preadv(uv_file fd,
-                             uv_buf_t* bufs,
-                             unsigned int nbufs,
-                             off_t off) {
-  uv_buf_t* buf;
-  uv_buf_t* end;
-  ssize_t result;
-  ssize_t rc;
-  size_t pos;
-
-  assert(nbufs > 0);
-
-  result = 0;
-  pos = 0;
-  buf = bufs + 0;
-  end = bufs + nbufs;
-
-  for (;;) {
-    do
-      rc = pread(fd, buf->base + pos, buf->len - pos, off + result);
-    while (rc == -1 && errno == EINTR);
-
-    if (rc == 0)
-      break;
-
-    if (rc == -1 && result == 0)
-      return UV__ERR(errno);
-
-    if (rc == -1)
-      break;  /* We read some data so return that, ignore the error. */
-
-    pos += rc;
-    result += rc;
-
-    if (pos < buf->len)
-      continue;
-
-    pos = 0;
-    buf += 1;
-
-    if (buf == end)
-      break;
-  }
-
-  return result;
-}
-
-
-static ssize_t uv__fs_read(uv_fs_t* req) {
-#if defined(__linux__)
-  static int no_preadv;
-#endif
-  unsigned int iovmax;
-  ssize_t result;
-
-  iovmax = uv__getiovmax();
-  if (req->nbufs > iovmax)
-    req->nbufs = iovmax;
-
-  if (req->off < 0) {
-    if (req->nbufs == 1)
-      result = read(req->file, req->bufs[0].base, req->bufs[0].len);
-    else
-      result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
-  } else {
-    if (req->nbufs == 1) {
-      result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
-      goto done;
-    }
-
-#if HAVE_PREADV
-    result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
-#else
-# if defined(__linux__)
-    if (no_preadv) retry:
-# endif
-    {
-      result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
-    }
-# if defined(__linux__)
-    else {
-      result = uv__preadv(req->file,
-                          (struct iovec*)req->bufs,
-                          req->nbufs,
-                          req->off);
-      if (result == -1 && errno == ENOSYS) {
-        no_preadv = 1;
-        goto retry;
-      }
-    }
-# endif
-#endif
-  }
-
-done:
-  /* Early cleanup of bufs allocation, since we're done with it. */
-  if (req->bufs != req->bufsml)
-    uv__free(req->bufs);
-
-  req->bufs = NULL;
-  req->nbufs = 0;
-
-#ifdef __PASE__
-  /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
-  if (result == -1 && errno == EOPNOTSUPP) {
-    struct stat buf;
-    ssize_t rc;
-    rc = fstat(req->file, &buf);
-    if (rc == 0 && S_ISDIR(buf.st_mode)) {
-      errno = EISDIR;
-    }
-  }
-#endif
-
-  return result;
-}
-
-
-#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)
-#define UV_CONST_DIRENT uv__dirent_t
-#else
-#define UV_CONST_DIRENT const uv__dirent_t
-#endif
-
-
-static int uv__fs_scandir_filter(UV_CONST_DIRENT* dent) {
-  return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
-}
-
-
-static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
-  return strcmp((*a)->d_name, (*b)->d_name);
-}
-
-
-static ssize_t uv__fs_scandir(uv_fs_t* req) {
-  uv__dirent_t** dents;
-  int n;
-
-  dents = NULL;
-  n = scandir(req->path, &dents, uv__fs_scandir_filter, uv__fs_scandir_sort);
-
-  /* NOTE: We will use nbufs as an index field */
-  req->nbufs = 0;
-
-  if (n == 0) {
-    /* OS X still needs to deallocate some memory.
-     * Memory was allocated using the system allocator, so use free() here.
-     */
-    free(dents);
-    dents = NULL;
-  } else if (n == -1) {
-    return n;
-  }
-
-  req->ptr = dents;
-
-  return n;
-}
-
-static int uv__fs_opendir(uv_fs_t* req) {
-  uv_dir_t* dir;
-
-  dir = (uv_dir_t*)uv__malloc(sizeof(*dir));
-  if (dir == NULL)
-    goto error;
-
-  dir->dir = opendir(req->path);
-  if (dir->dir == NULL)
-    goto error;
-
-  req->ptr = dir;
-  return 0;
-
-error:
-  uv__free(dir);
-  req->ptr = NULL;
-  return -1;
-}
-
-static int uv__fs_readdir(uv_fs_t* req) {
-  uv_dir_t* dir;
-  uv_dirent_t* dirent;
-  struct dirent* res;
-  unsigned int dirent_idx;
-  unsigned int i;
-
-  dir = (uv_dir_t*)req->ptr;
-  dirent_idx = 0;
-
-  while (dirent_idx < dir->nentries) {
-    /* readdir() returns NULL on end of directory, as well as on error. errno
-       is used to differentiate between the two conditions. */
-    errno = 0;
-    res = readdir(dir->dir);
-
-    if (res == NULL) {
-      if (errno != 0)
-        goto error;
-      break;
-    }
-
-    if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0)
-      continue;
-
-    dirent = &dir->dirents[dirent_idx];
-    dirent->name = uv__strdup(res->d_name);
-
-    if (dirent->name == NULL)
-      goto error;
-
-    dirent->type = uv__fs_get_dirent_type(res);
-    ++dirent_idx;
-  }
-
-  return dirent_idx;
-
-error:
-  for (i = 0; i < dirent_idx; ++i) {
-    uv__free((char*) dir->dirents[i].name);
-    dir->dirents[i].name = NULL;
-  }
-
-  return -1;
-}
-
-static int uv__fs_closedir(uv_fs_t* req) {
-  uv_dir_t* dir;
-
-  dir = (uv_dir_t*)req->ptr;
-
-  if (dir->dir != NULL) {
-    closedir(dir->dir);
-    dir->dir = NULL;
-  }
-
-  uv__free(req->ptr);
-  req->ptr = NULL;
-  return 0;
-}
-
-static ssize_t uv__fs_pathmax_size(const char* path) {
-  ssize_t pathmax;
-
-  pathmax = pathconf(path, _PC_PATH_MAX);
-
-  if (pathmax == -1)
-    pathmax = UV__PATH_MAX;
-
-  return pathmax;
-}
-
-static ssize_t uv__fs_readlink(uv_fs_t* req) {
-  ssize_t maxlen;
-  ssize_t len;
-  char* buf;
-  char* newbuf;
-
-#if defined(_POSIX_PATH_MAX) || defined(PATH_MAX)
-  maxlen = uv__fs_pathmax_size(req->path);
-#else
-  /* We may not have a real PATH_MAX.  Read size of link.  */
-  struct stat st;
-  int ret;
-  ret = lstat(req->path, &st);
-  if (ret != 0)
-    return -1;
-  if (!S_ISLNK(st.st_mode)) {
-    errno = EINVAL;
-    return -1;
-  }
-
-  maxlen = st.st_size;
-
-  /* According to readlink(2) lstat can report st_size == 0
-     for some symlinks, such as those in /proc or /sys.  */
-  if (maxlen == 0)
-    maxlen = uv__fs_pathmax_size(req->path);
-#endif
-
-  buf = (char*)uv__malloc(maxlen);
-
-  if (buf == NULL) {
-    errno = ENOMEM;
-    return -1;
-  }
-
-#if defined(__MVS__)
-  len = os390_readlink(req->path, buf, maxlen);
-#else
-  len = readlink(req->path, buf, maxlen);
-#endif
-
-  if (len == -1) {
-    uv__free(buf);
-    return -1;
-  }
-
-  /* Uncommon case: resize to make room for the trailing nul byte. */
-  if (len == maxlen) {
-    newbuf = (char*)uv__realloc(buf, len + 1);
-
-    if (newbuf == NULL) {
-      uv__free(buf);
-      return -1;
-    }
-
-    buf = newbuf;
-  }
-
-  buf[len] = '\0';
-  req->ptr = buf;
-
-  return 0;
-}
-
-static ssize_t uv__fs_realpath(uv_fs_t* req) {
-  char* buf;
-
-#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
-  buf = realpath(req->path, NULL);
-  if (buf == NULL)
-    return -1;
-#else
-  ssize_t len;
-
-  len = uv__fs_pathmax_size(req->path);
-  buf = (char*)uv__malloc(len + 1);
-
-  if (buf == NULL) {
-    errno = ENOMEM;
-    return -1;
-  }
-
-  if (realpath(req->path, buf) == NULL) {
-    uv__free(buf);
-    return -1;
-  }
-#endif
-
-  req->ptr = buf;
-
-  return 0;
-}
-
-static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
-  struct pollfd pfd;
-  int use_pread;
-  off_t offset;
-  ssize_t nsent;
-  ssize_t nread;
-  ssize_t nwritten;
-  size_t buflen;
-  size_t len;
-  ssize_t n;
-  int in_fd;
-  int out_fd;
-  char buf[8192];
-
-  len = req->bufsml[0].len;
-  in_fd = req->flags;
-  out_fd = req->file;
-  offset = req->off;
-  use_pread = 1;
-
-  /* Here are the rules regarding errors:
-   *
-   * 1. Read errors are reported only if nsent==0, otherwise we return nsent.
-   *    The user needs to know that some data has already been sent, to stop
-   *    them from sending it twice.
-   *
-   * 2. Write errors are always reported. Write errors are bad because they
-   *    mean data loss: we've read data but now we can't write it out.
-   *
-   * We try to use pread() and fall back to regular read() if the source fd
-   * doesn't support positional reads, for example when it's a pipe fd.
-   *
-   * If we get EAGAIN when writing to the target fd, we poll() on it until
-   * it becomes writable again.
-   *
-   * FIXME: If we get a write error when use_pread==1, it should be safe to
-   *        return the number of sent bytes instead of an error because pread()
-   *        is, in theory, idempotent. However, special files in /dev or /proc
-   *        may support pread() but not necessarily return the same data on
-   *        successive reads.
-   *
-   * FIXME: There is no way now to signal that we managed to send *some* data
-   *        before a write error.
-   */
-  for (nsent = 0; (size_t) nsent < len; ) {
-    buflen = len - nsent;
-
-    if (buflen > sizeof(buf))
-      buflen = sizeof(buf);
-
-    do
-      if (use_pread)
-        nread = pread(in_fd, buf, buflen, offset);
-      else
-        nread = read(in_fd, buf, buflen);
-    while (nread == -1 && errno == EINTR);
-
-    if (nread == 0)
-      goto out;
-
-    if (nread == -1) {
-      if (use_pread && nsent == 0 && (errno == EIO || errno == ESPIPE)) {
-        use_pread = 0;
-        continue;
-      }
-
-      if (nsent == 0)
-        nsent = -1;
-
-      goto out;
-    }
-
-    for (nwritten = 0; nwritten < nread; ) {
-      do
-        n = write(out_fd, buf + nwritten, nread - nwritten);
-      while (n == -1 && errno == EINTR);
-
-      if (n != -1) {
-        nwritten += n;
-        continue;
-      }
-
-      if (errno != EAGAIN && errno != EWOULDBLOCK) {
-        nsent = -1;
-        goto out;
-      }
-
-      pfd.fd = out_fd;
-      pfd.events = POLLOUT;
-      pfd.revents = 0;
-
-      do
-        n = poll(&pfd, 1, -1);
-      while (n == -1 && errno == EINTR);
-
-      if (n == -1 || (pfd.revents & ~POLLOUT) != 0) {
-        errno = EIO;
-        nsent = -1;
-        goto out;
-      }
-    }
-
-    offset += nread;
-    nsent += nread;
-  }
-
-out:
-  if (nsent != -1)
-    req->off = offset;
-
-  return nsent;
-}
-
-
-static ssize_t uv__fs_sendfile(uv_fs_t* req) {
-  int in_fd;
-  int out_fd;
-
-  in_fd = req->flags;
-  out_fd = req->file;
-
-#if defined(__linux__) || defined(__sun)
-  {
-    off_t off;
-    ssize_t r;
-
-    off = req->off;
-    r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);
-
-    /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
-     * it still writes out data. Fortunately, we can detect it by checking if
-     * the offset has been updated.
-     */
-    if (r != -1 || off > req->off) {
-      r = off - req->off;
-      req->off = off;
-      return r;
-    }
-
-    if (errno == EINVAL ||
-        errno == EIO ||
-        errno == ENOTSOCK ||
-        errno == EXDEV) {
-      errno = 0;
-      return uv__fs_sendfile_emul(req);
-    }
-
-    return -1;
-  }
-#elif defined(__APPLE__)           || \
-      defined(__DragonFly__)       || \
-      defined(__FreeBSD__)         || \
-      defined(__FreeBSD_kernel__)
-  {
-    off_t len;
-    ssize_t r;
-
-    /* sendfile() on FreeBSD and Darwin returns EAGAIN if the target fd is in
-     * non-blocking mode and not all data could be written. If a non-zero
-     * number of bytes have been sent, we don't consider it an error.
-     */
-
-#if defined(__FreeBSD__) || defined(__DragonFly__)
-    len = 0;
-    r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
-#elif defined(__FreeBSD_kernel__)
-    len = 0;
-    r = bsd_sendfile(in_fd,
-                     out_fd,
-                     req->off,
-                     req->bufsml[0].len,
-                     NULL,
-                     &len,
-                     0);
-#else
-    /* The darwin sendfile takes len as an input for the length to send,
-     * so make sure to initialize it with the caller's value. */
-    len = req->bufsml[0].len;
-    r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
-#endif
-
-     /*
-     * The man page for sendfile(2) on DragonFly states that `len` contains
-     * a meaningful value ONLY in case of EAGAIN and EINTR.
-     * Nothing is said about it's value in case of other errors, so better
-     * not depend on the potential wrong assumption that is was not modified
-     * by the syscall.
-     */
-    if (r == 0 || ((errno == EAGAIN || errno == EINTR) && len != 0)) {
-      req->off += len;
-      return (ssize_t) len;
-    }
-
-    if (errno == EINVAL ||
-        errno == EIO ||
-        errno == ENOTSOCK ||
-        errno == EXDEV) {
-      errno = 0;
-      return uv__fs_sendfile_emul(req);
-    }
-
-    return -1;
-  }
-#else
-  /* Squelch compiler warnings. */
-  (void) &in_fd;
-  (void) &out_fd;
-
-  return uv__fs_sendfile_emul(req);
-#endif
-}
-
-
-static ssize_t uv__fs_utime(uv_fs_t* req) {
-#if defined(__linux__)                                                         \
-    || defined(_AIX71)                                                         \
-    || defined(__sun)                                                          \
-    || defined(__HAIKU__)
-  /* utimesat() has nanosecond resolution but we stick to microseconds
-   * for the sake of consistency with other platforms.
-   */
-  struct timespec ts[2];
-  ts[0].tv_sec  = req->atime;
-  ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
-  ts[1].tv_sec  = req->mtime;
-  ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
-  return utimensat(AT_FDCWD, req->path, ts, 0);
-#elif defined(__APPLE__)                                                      \
-    || defined(__DragonFly__)                                                 \
-    || defined(__FreeBSD__)                                                   \
-    || defined(__FreeBSD_kernel__)                                            \
-    || defined(__NetBSD__)                                                    \
-    || defined(__OpenBSD__)
-  struct timeval tv[2];
-  tv[0].tv_sec  = req->atime;
-  tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000;
-  tv[1].tv_sec  = req->mtime;
-  tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000;
-  return utimes(req->path, tv);
-#elif defined(_AIX)                                                           \
-    && !defined(_AIX71)
-  struct utimbuf buf;
-  buf.actime = req->atime;
-  buf.modtime = req->mtime;
-  return utime(req->path, &buf);
-#elif defined(__MVS__)
-  attrib_t atr;
-  memset(&atr, 0, sizeof(atr));
-  atr.att_mtimechg = 1;
-  atr.att_atimechg = 1;
-  atr.att_mtime = req->mtime;
-  atr.att_atime = req->atime;
-  return __lchattr((char*) req->path, &atr, sizeof(atr));
-#else
-  errno = ENOSYS;
-  return -1;
-#endif
-}
-
-
-static ssize_t uv__fs_write(uv_fs_t* req) {
-#if defined(__linux__)
-  static int no_pwritev;
-#endif
-  ssize_t r;
-
-  /* Serialize writes on OS X, concurrent write() and pwrite() calls result in
-   * data loss. We can't use a per-file descriptor lock, the descriptor may be
-   * a dup().
-   */
-#if defined(__APPLE__)
-  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
-  if (pthread_mutex_lock(&lock))
-    abort();
-#endif
-
-  if (req->off < 0) {
-    if (req->nbufs == 1)
-      r = write(req->file, req->bufs[0].base, req->bufs[0].len);
-    else
-      r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
-  } else {
-    if (req->nbufs == 1) {
-      r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
-      goto done;
-    }
-#if HAVE_PREADV
-    r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
-#else
-# if defined(__linux__)
-    if (no_pwritev) retry:
-# endif
-    {
-      r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
-    }
-# if defined(__linux__)
-    else {
-      r = uv__pwritev(req->file,
-                      (struct iovec*) req->bufs,
-                      req->nbufs,
-                      req->off);
-      if (r == -1 && errno == ENOSYS) {
-        no_pwritev = 1;
-        goto retry;
-      }
-    }
-# endif
-#endif
-  }
-
-done:
-#if defined(__APPLE__)
-  if (pthread_mutex_unlock(&lock))
-    abort();
-#endif
-
-  return r;
-}
-
-static ssize_t uv__fs_copyfile(uv_fs_t* req) {
-  uv_fs_t fs_req;
-  uv_file srcfd;
-  uv_file dstfd;
-  struct stat src_statsbuf;
-  struct stat dst_statsbuf;
-  int dst_flags;
-  int result;
-  int err;
-  size_t bytes_to_send;
-  int64_t in_offset;
-
-  dstfd = -1;
-  err = 0;
-
-  /* Open the source file. */
-  srcfd = uv_fs_open(NULL, &fs_req, req->path, O_RDONLY, 0, NULL);
-  uv_fs_req_cleanup(&fs_req);
-
-  if (srcfd < 0)
-    return srcfd;
-
-  /* Get the source file's mode. */
-  if (fstat(srcfd, &src_statsbuf)) {
-    err = UV__ERR(errno);
-    goto out;
-  }
-
-  dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
-
-  if (req->flags & UV_FS_COPYFILE_EXCL)
-    dst_flags |= O_EXCL;
-
-  /* Open the destination file. */
-  dstfd = uv_fs_open(NULL,
-                     &fs_req,
-                     req->new_path,
-                     dst_flags,
-                     src_statsbuf.st_mode,
-                     NULL);
-  uv_fs_req_cleanup(&fs_req);
-
-  if (dstfd < 0) {
-    err = dstfd;
-    goto out;
-  }
-
-  /* Get the destination file's mode. */
-  if (fstat(dstfd, &dst_statsbuf)) {
-    err = UV__ERR(errno);
-    goto out;
-  }
-
-  /* Check if srcfd and dstfd refer to the same file */
-  if (src_statsbuf.st_dev == dst_statsbuf.st_dev &&
-      src_statsbuf.st_ino == dst_statsbuf.st_ino) {
-    goto out;
-  }
-
-  if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
-    err = UV__ERR(errno);
-    goto out;
-  }
-
-#ifdef FICLONE
-  if (req->flags & UV_FS_COPYFILE_FICLONE ||
-      req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
-    if (ioctl(dstfd, FICLONE, srcfd) == -1) {
-      /* If an error occurred that the sendfile fallback also won't handle, or
-         this is a force clone then exit. Otherwise, fall through to try using
-         sendfile(). */
-      if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) {
-        err = UV__ERR(errno);
-        goto out;
-      } else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
-        err = UV_ENOTSUP;
-        goto out;
-      }
-    } else {
-      goto out;
-    }
-  }
-#else
-  if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
-    err = UV_ENOSYS;
-    goto out;
-  }
-#endif
-
-  bytes_to_send = src_statsbuf.st_size;
-  in_offset = 0;
-  while (bytes_to_send != 0) {
-    err = uv_fs_sendfile(NULL,
-                         &fs_req,
-                         dstfd,
-                         srcfd,
-                         in_offset,
-                         bytes_to_send,
-                         NULL);
-    uv_fs_req_cleanup(&fs_req);
-    if (err < 0)
-      break;
-    bytes_to_send -= fs_req.result;
-    in_offset += fs_req.result;
-  }
-
-out:
-  if (err < 0)
-    result = err;
-  else
-    result = 0;
-
-  /* Close the source file. */
-  err = uv__close_nocheckstdio(srcfd);
-
-  /* Don't overwrite any existing errors. */
-  if (err != 0 && result == 0)
-    result = err;
-
-  /* Close the destination file if it is open. */
-  if (dstfd >= 0) {
-    err = uv__close_nocheckstdio(dstfd);
-
-    /* Don't overwrite any existing errors. */
-    if (err != 0 && result == 0)
-      result = err;
-
-    /* Remove the destination file if something went wrong. */
-    if (result != 0) {
-      uv_fs_unlink(NULL, &fs_req, req->new_path, NULL);
-      /* Ignore the unlink return value, as an error already happened. */
-      uv_fs_req_cleanup(&fs_req);
-    }
-  }
-
-  if (result == 0)
-    return 0;
-
-  errno = UV__ERR(result);
-  return -1;
-}
-
-static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
-  dst->st_dev = src->st_dev;
-  dst->st_mode = src->st_mode;
-  dst->st_nlink = src->st_nlink;
-  dst->st_uid = src->st_uid;
-  dst->st_gid = src->st_gid;
-  dst->st_rdev = src->st_rdev;
-  dst->st_ino = src->st_ino;
-  dst->st_size = src->st_size;
-  dst->st_blksize = src->st_blksize;
-  dst->st_blocks = src->st_blocks;
-
-#if defined(__APPLE__)
-  dst->st_atim.tv_sec = src->st_atimespec.tv_sec;
-  dst->st_atim.tv_nsec = src->st_atimespec.tv_nsec;
-  dst->st_mtim.tv_sec = src->st_mtimespec.tv_sec;
-  dst->st_mtim.tv_nsec = src->st_mtimespec.tv_nsec;
-  dst->st_ctim.tv_sec = src->st_ctimespec.tv_sec;
-  dst->st_ctim.tv_nsec = src->st_ctimespec.tv_nsec;
-  dst->st_birthtim.tv_sec = src->st_birthtimespec.tv_sec;
-  dst->st_birthtim.tv_nsec = src->st_birthtimespec.tv_nsec;
-  dst->st_flags = src->st_flags;
-  dst->st_gen = src->st_gen;
-#elif defined(__ANDROID__)
-  dst->st_atim.tv_sec = src->st_atime;
-  dst->st_atim.tv_nsec = src->st_atimensec;
-  dst->st_mtim.tv_sec = src->st_mtime;
-  dst->st_mtim.tv_nsec = src->st_mtimensec;
-  dst->st_ctim.tv_sec = src->st_ctime;
-  dst->st_ctim.tv_nsec = src->st_ctimensec;
-  dst->st_birthtim.tv_sec = src->st_ctime;
-  dst->st_birthtim.tv_nsec = src->st_ctimensec;
-  dst->st_flags = 0;
-  dst->st_gen = 0;
-#elif !defined(_AIX) && (       \
-    defined(__DragonFly__)   || \
-    defined(__FreeBSD__)     || \
-    defined(__OpenBSD__)     || \
-    defined(__NetBSD__)      || \
-    defined(_GNU_SOURCE)     || \
-    defined(_BSD_SOURCE)     || \
-    defined(_SVID_SOURCE)    || \
-    defined(_XOPEN_SOURCE)   || \
-    defined(_DEFAULT_SOURCE))
-  dst->st_atim.tv_sec = src->st_atim.tv_sec;
-  dst->st_atim.tv_nsec = src->st_atim.tv_nsec;
-  dst->st_mtim.tv_sec = src->st_mtim.tv_sec;
-  dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
-  dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
-  dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
-# if defined(__FreeBSD__)    || \
-     defined(__NetBSD__)
-  dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
-  dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
-  dst->st_flags = src->st_flags;
-  dst->st_gen = src->st_gen;
-# else
-  dst->st_birthtim.tv_sec = src->st_ctim.tv_sec;
-  dst->st_birthtim.tv_nsec = src->st_ctim.tv_nsec;
-  dst->st_flags = 0;
-  dst->st_gen = 0;
-# endif
-#else
-  dst->st_atim.tv_sec = src->st_atime;
-  dst->st_atim.tv_nsec = 0;
-  dst->st_mtim.tv_sec = src->st_mtime;
-  dst->st_mtim.tv_nsec = 0;
-  dst->st_ctim.tv_sec = src->st_ctime;
-  dst->st_ctim.tv_nsec = 0;
-  dst->st_birthtim.tv_sec = src->st_ctime;
-  dst->st_birthtim.tv_nsec = 0;
-  dst->st_flags = 0;
-  dst->st_gen = 0;
-#endif
-}
-
-
-static int uv__fs_statx(int fd,
-                        const char* path,
-                        int is_fstat,
-                        int is_lstat,
-                        uv_stat_t* buf) {
-  STATIC_ASSERT(UV_ENOSYS != -1);
-#ifdef __linux__
-  static int no_statx;
-  struct uv__statx statxbuf;
-  int dirfd;
-  int flags;
-  int mode;
-  int rc;
-
-  if (no_statx)
-    return UV_ENOSYS;
-
-  dirfd = AT_FDCWD;
-  flags = 0; /* AT_STATX_SYNC_AS_STAT */
-  mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
-
-  if (is_fstat) {
-    dirfd = fd;
-    flags |= 0x1000; /* AT_EMPTY_PATH */
-  }
-
-  if (is_lstat)
-    flags |= AT_SYMLINK_NOFOLLOW;
-
-  rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
-
-  if (rc == -1) {
-    /* EPERM happens when a seccomp filter rejects the system call.
-     * Has been observed with libseccomp < 2.3.3 and docker < 18.04.
-     */
-    if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
-      return -1;
-
-    no_statx = 1;
-    return UV_ENOSYS;
-  }
-
-  buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor;
-  buf->st_mode = statxbuf.stx_mode;
-  buf->st_nlink = statxbuf.stx_nlink;
-  buf->st_uid = statxbuf.stx_uid;
-  buf->st_gid = statxbuf.stx_gid;
-  buf->st_rdev = statxbuf.stx_rdev_major;
-  buf->st_ino = statxbuf.stx_ino;
-  buf->st_size = statxbuf.stx_size;
-  buf->st_blksize = statxbuf.stx_blksize;
-  buf->st_blocks = statxbuf.stx_blocks;
-  buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec;
-  buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec;
-  buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec;
-  buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec;
-  buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec;
-  buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec;
-  buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec;
-  buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec;
-  buf->st_flags = 0;
-  buf->st_gen = 0;
-
-  return 0;
-#else
-  return UV_ENOSYS;
-#endif /* __linux__ */
-}
-
-
-static int uv__fs_stat(const char *path, uv_stat_t *buf) {
-  struct stat pbuf;
-  int ret;
-
-  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
-  if (ret != UV_ENOSYS)
-    return ret;
-
-  ret = stat(path, &pbuf);
-  if (ret == 0)
-    uv__to_stat(&pbuf, buf);
-
-  return ret;
-}
-
-
-static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
-  struct stat pbuf;
-  int ret;
-
-  ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
-  if (ret != UV_ENOSYS)
-    return ret;
-
-  ret = lstat(path, &pbuf);
-  if (ret == 0)
-    uv__to_stat(&pbuf, buf);
-
-  return ret;
-}
-
-
-static int uv__fs_fstat(int fd, uv_stat_t *buf) {
-  struct stat pbuf;
-  int ret;
-
-  ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
-  if (ret != UV_ENOSYS)
-    return ret;
-
-  ret = fstat(fd, &pbuf);
-  if (ret == 0)
-    uv__to_stat(&pbuf, buf);
-
-  return ret;
-}
-
-static size_t uv__fs_buf_offset(uv_buf_t* bufs, size_t size) {
-  size_t offset;
-  /* Figure out which bufs are done */
-  for (offset = 0; size > 0 && bufs[offset].len <= size; ++offset)
-    size -= bufs[offset].len;
-
-  /* Fix a partial read/write */
-  if (size > 0) {
-    bufs[offset].base += size;
-    bufs[offset].len -= size;
-  }
-  return offset;
-}
-
-static ssize_t uv__fs_write_all(uv_fs_t* req) {
-  unsigned int iovmax;
-  unsigned int nbufs;
-  uv_buf_t* bufs;
-  ssize_t total;
-  ssize_t result;
-
-  iovmax = uv__getiovmax();
-  nbufs = req->nbufs;
-  bufs = req->bufs;
-  total = 0;
-
-  while (nbufs > 0) {
-    req->nbufs = nbufs;
-    if (req->nbufs > iovmax)
-      req->nbufs = iovmax;
-
-    do
-      result = uv__fs_write(req);
-    while (result < 0 && errno == EINTR);
-
-    if (result <= 0) {
-      if (total == 0)
-        total = result;
-      break;
-    }
-
-    if (req->off >= 0)
-      req->off += result;
-
-    req->nbufs = uv__fs_buf_offset(req->bufs, result);
-    req->bufs += req->nbufs;
-    nbufs -= req->nbufs;
-    total += result;
-  }
-
-  if (bufs != req->bufsml)
-    uv__free(bufs);
-
-  req->bufs = NULL;
-  req->nbufs = 0;
-
-  return total;
-}
-
-
-static void uv__fs_work(struct uv__work* w) {
-  int retry_on_eintr;
-  uv_fs_t* req;
-  ssize_t r;
-
-  req = container_of(w, uv_fs_t, work_req);
-  retry_on_eintr = !(req->fs_type == UV_FS_CLOSE ||
-                     req->fs_type == UV_FS_READ);
-
-  do {
-    errno = 0;
-
-#define X(type, action)                                                       \
-  case UV_FS_ ## type:                                                        \
-    r = action;                                                               \
-    break;
-
-    switch (req->fs_type) {
-    X(ACCESS, access(req->path, req->flags));
-    X(CHMOD, chmod(req->path, req->mode));
-    X(CHOWN, chown(req->path, req->uid, req->gid));
-    X(CLOSE, uv__fs_close(req->file));
-    X(COPYFILE, uv__fs_copyfile(req));
-    X(FCHMOD, fchmod(req->file, req->mode));
-    X(FCHOWN, fchown(req->file, req->uid, req->gid));
-    X(LCHOWN, lchown(req->path, req->uid, req->gid));
-    X(FDATASYNC, uv__fs_fdatasync(req));
-    X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
-    X(FSYNC, uv__fs_fsync(req));
-    X(FTRUNCATE, ftruncate(req->file, req->off));
-    X(FUTIME, uv__fs_futime(req));
-    X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
-    X(LINK, link(req->path, req->new_path));
-    X(MKDIR, mkdir(req->path, req->mode));
-    X(MKDTEMP, uv__fs_mkdtemp(req));
-    X(OPEN, uv__fs_open(req));
-    X(READ, uv__fs_read(req));
-    X(SCANDIR, uv__fs_scandir(req));
-    X(OPENDIR, uv__fs_opendir(req));
-    X(READDIR, uv__fs_readdir(req));
-    X(CLOSEDIR, uv__fs_closedir(req));
-    X(READLINK, uv__fs_readlink(req));
-    X(REALPATH, uv__fs_realpath(req));
-    X(RENAME, rename(req->path, req->new_path));
-    X(RMDIR, rmdir(req->path));
-    X(SENDFILE, uv__fs_sendfile(req));
-    X(STAT, uv__fs_stat(req->path, &req->statbuf));
-    X(SYMLINK, symlink(req->path, req->new_path));
-    X(UNLINK, unlink(req->path));
-    X(UTIME, uv__fs_utime(req));
-    X(WRITE, uv__fs_write_all(req));
-    default: abort();
-    }
-#undef X
-  } while (r == -1 && errno == EINTR && retry_on_eintr);
-
-  if (r == -1)
-    req->result = UV__ERR(errno);
-  else
-    req->result = r;
-
-  if (r == 0 && (req->fs_type == UV_FS_STAT ||
-                 req->fs_type == UV_FS_FSTAT ||
-                 req->fs_type == UV_FS_LSTAT)) {
-    req->ptr = &req->statbuf;
-  }
-}
-
-
-static void uv__fs_done(struct uv__work* w, int status) {
-  uv_fs_t* req;
-
-  req = container_of(w, uv_fs_t, work_req);
-  uv__req_unregister(req->loop, req);
-
-  if (status == UV_ECANCELED) {
-    assert(req->result == 0);
-    req->result = UV_ECANCELED;
-  }
-
-  req->cb(req);
-}
-
-
-int uv_fs_access(uv_loop_t* loop,
-                 uv_fs_t* req,
-                 const char* path,
-                 int flags,
-                 uv_fs_cb cb) {
-  INIT(ACCESS);
-  PATH;
-  req->flags = flags;
-  POST;
-}
-
-
-int uv_fs_chmod(uv_loop_t* loop,
-                uv_fs_t* req,
-                const char* path,
-                int mode,
-                uv_fs_cb cb) {
-  INIT(CHMOD);
-  PATH;
-  req->mode = mode;
-  POST;
-}
-
-
-int uv_fs_chown(uv_loop_t* loop,
-                uv_fs_t* req,
-                const char* path,
-                uv_uid_t uid,
-                uv_gid_t gid,
-                uv_fs_cb cb) {
-  INIT(CHOWN);
-  PATH;
-  req->uid = uid;
-  req->gid = gid;
-  POST;
-}
-
-
-int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
-  INIT(CLOSE);
-  req->file = file;
-  POST;
-}
-
-
-int uv_fs_fchmod(uv_loop_t* loop,
-                 uv_fs_t* req,
-                 uv_file file,
-                 int mode,
-                 uv_fs_cb cb) {
-  INIT(FCHMOD);
-  req->file = file;
-  req->mode = mode;
-  POST;
-}
-
-
-int uv_fs_fchown(uv_loop_t* loop,
-                 uv_fs_t* req,
-                 uv_file file,
-                 uv_uid_t uid,
-                 uv_gid_t gid,
-                 uv_fs_cb cb) {
-  INIT(FCHOWN);
-  req->file = file;
-  req->uid = uid;
-  req->gid = gid;
-  POST;
-}
-
-
-int uv_fs_lchown(uv_loop_t* loop,
-                 uv_fs_t* req,
-                 const char* path,
-                 uv_uid_t uid,
-                 uv_gid_t gid,
-                 uv_fs_cb cb) {
-  INIT(LCHOWN);
-  PATH;
-  req->uid = uid;
-  req->gid = gid;
-  POST;
-}
-
-
-int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
-  INIT(FDATASYNC);
-  req->file = file;
-  POST;
-}
-
-
-int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
-  INIT(FSTAT);
-  req->file = file;
-  POST;
-}
-
-
-int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
-  INIT(FSYNC);
-  req->file = file;
-  POST;
-}
-
-
-int uv_fs_ftruncate(uv_loop_t* loop,
-                    uv_fs_t* req,
-                    uv_file file,
-                    int64_t off,
-                    uv_fs_cb cb) {
-  INIT(FTRUNCATE);
-  req->file = file;
-  req->off = off;
-  POST;
-}
-
-
-int uv_fs_futime(uv_loop_t* loop,
-                 uv_fs_t* req,
-                 uv_file file,
-                 double atime,
-                 double mtime,
-                 uv_fs_cb cb) {
-  INIT(FUTIME);
-  req->file = file;
-  req->atime = atime;
-  req->mtime = mtime;
-  POST;
-}
-
-
-int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
-  INIT(LSTAT);
-  PATH;
-  POST;
-}
-
-
-int uv_fs_link(uv_loop_t* loop,
-               uv_fs_t* req,
-               const char* path,
-               const char* new_path,
-               uv_fs_cb cb) {
-  INIT(LINK);
-  PATH2;
-  POST;
-}
-
-
-int uv_fs_mkdir(uv_loop_t* loop,
-                uv_fs_t* req,
-                const char* path,
-                int mode,
-                uv_fs_cb cb) {
-  INIT(MKDIR);
-  PATH;
-  req->mode = mode;
-  POST;
-}
-
-
-int uv_fs_mkdtemp(uv_loop_t* loop,
-                  uv_fs_t* req,
-                  const char* tpl,
-                  uv_fs_cb cb) {
-  INIT(MKDTEMP);
-  req->path = uv__strdup(tpl);
-  if (req->path == NULL)
-    return UV_ENOMEM;
-  POST;
-}
-
-
-int uv_fs_open(uv_loop_t* loop,
-               uv_fs_t* req,
-               const char* path,
-               int flags,
-               int mode,
-               uv_fs_cb cb) {
-  INIT(OPEN);
-  PATH;
-  req->flags = flags;
-  req->mode = mode;
-  POST;
-}
-
-
-int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
-               uv_file file,
-               const uv_buf_t bufs[],
-               unsigned int nbufs,
-               int64_t off,
-               uv_fs_cb cb) {
-  INIT(READ);
-
-  if (bufs == NULL || nbufs == 0)
-    return UV_EINVAL;
-
-  req->file = file;
-
-  req->nbufs = nbufs;
-  req->bufs = req->bufsml;
-  if (nbufs > ARRAY_SIZE(req->bufsml))
-    req->bufs = (uv_buf_t*)uv__malloc(nbufs * sizeof(*bufs));
-
-  if (req->bufs == NULL)
-    return UV_ENOMEM;
-
-  memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
-
-  req->off = off;
-  POST;
-}
-
-
-int uv_fs_scandir(uv_loop_t* loop,
-                  uv_fs_t* req,
-                  const char* path,
-                  int flags,
-                  uv_fs_cb cb) {
-  INIT(SCANDIR);
-  PATH;
-  req->flags = flags;
-  POST;
-}
-
-int uv_fs_opendir(uv_loop_t* loop,
-                  uv_fs_t* req,
-                  const char* path,
-                  uv_fs_cb cb) {
-  INIT(OPENDIR);
-  PATH;
-  POST;
-}
-
-int uv_fs_readdir(uv_loop_t* loop,
-                  uv_fs_t* req,
-                  uv_dir_t* dir,
-                  uv_fs_cb cb) {
-  INIT(READDIR);
-
-  if (dir == NULL || dir->dir == NULL || dir->dirents == NULL)
-    return UV_EINVAL;
-
-  req->ptr = dir;
-  POST;
-}
-
-int uv_fs_closedir(uv_loop_t* loop,
-                   uv_fs_t* req,
-                   uv_dir_t* dir,
-                   uv_fs_cb cb) {
-  INIT(CLOSEDIR);
-
-  if (dir == NULL)
-    return UV_EINVAL;
-
-  req->ptr = dir;
-  POST;
-}
-
-int uv_fs_readlink(uv_loop_t* loop,
-                   uv_fs_t* req,
-                   const char* path,
-                   uv_fs_cb cb) {
-  INIT(READLINK);
-  PATH;
-  POST;
-}
-
-
-int uv_fs_realpath(uv_loop_t* loop,
-                  uv_fs_t* req,
-                  const char * path,
-                  uv_fs_cb cb) {
-  INIT(REALPATH);
-  PATH;
-  POST;
-}
-
-
-int uv_fs_rename(uv_loop_t* loop,
-                 uv_fs_t* req,
-                 const char* path,
-                 const char* new_path,
-                 uv_fs_cb cb) {
-  INIT(RENAME);
-  PATH2;
-  POST;
-}
-
-
-int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
-  INIT(RMDIR);
-  PATH;
-  POST;
-}
-
-
-int uv_fs_sendfile(uv_loop_t* loop,
-                   uv_fs_t* req,
-                   uv_file out_fd,
-                   uv_file in_fd,
-                   int64_t off,
-                   size_t len,
-                   uv_fs_cb cb) {
-  INIT(SENDFILE);
-  req->flags = in_fd; /* hack */
-  req->file = out_fd;
-  req->off = off;
-  req->bufsml[0].len = len;
-  POST;
-}
-
-
-int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
-  INIT(STAT);
-  PATH;
-  POST;
-}
-
-
-int uv_fs_symlink(uv_loop_t* loop,
-                  uv_fs_t* req,
-                  const char* path,
-                  const char* new_path,
-                  int flags,
-                  uv_fs_cb cb) {
-  INIT(SYMLINK);
-  PATH2;
-  req->flags = flags;
-  POST;
-}
-
-
-int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
-  INIT(UNLINK);
-  PATH;
-  POST;
-}
-
-
-int uv_fs_utime(uv_loop_t* loop,
-                uv_fs_t* req,
-                const char* path,
-                double atime,
-                double mtime,
-                uv_fs_cb cb) {
-  INIT(UTIME);
-  PATH;
-  req->atime = atime;
-  req->mtime = mtime;
-  POST;
-}
-
-
-int uv_fs_write(uv_loop_t* loop,
-                uv_fs_t* req,
-                uv_file file,
-                const uv_buf_t bufs[],
-                unsigned int nbufs,
-                int64_t off,
-                uv_fs_cb cb) {
-  INIT(WRITE);
-
-  if (bufs == NULL || nbufs == 0)
-    return UV_EINVAL;
-
-  req->file = file;
-
-  req->nbufs = nbufs;
-  req->bufs = req->bufsml;
-  if (nbufs > ARRAY_SIZE(req->bufsml))
-    req->bufs = (uv_buf_t*)uv__malloc(nbufs * sizeof(*bufs));
-
-  if (req->bufs == NULL)
-    return UV_ENOMEM;
-
-  memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
-
-  req->off = off;
-  POST;
-}
-
-
-void uv_fs_req_cleanup(uv_fs_t* req) {
-  if (req == NULL)
-    return;
-
-  /* Only necessary for asychronous requests, i.e., requests with a callback.
-   * Synchronous ones don't copy their arguments and have req->path and
-   * req->new_path pointing to user-owned memory.  UV_FS_MKDTEMP is the
-   * exception to the rule, it always allocates memory.
-   */
-  if (req->path != NULL && (req->cb != NULL || req->fs_type == UV_FS_MKDTEMP))
-    uv__free((void*) req->path);  /* Memory is shared with req->new_path. */
-
-  req->path = NULL;
-  req->new_path = NULL;
-
-  if (req->fs_type == UV_FS_READDIR && req->ptr != NULL)
-    uv__fs_readdir_cleanup(req);
-
-  if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
-    uv__fs_scandir_cleanup(req);
-
-  if (req->bufs != req->bufsml)
-    uv__free(req->bufs);
-  req->bufs = NULL;
-
-  if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf)
-    uv__free(req->ptr);
-  req->ptr = NULL;
-}
-
-
-int uv_fs_copyfile(uv_loop_t* loop,
-                   uv_fs_t* req,
-                   const char* path,
-                   const char* new_path,
-                   int flags,
-                   uv_fs_cb cb) {
-  INIT(COPYFILE);
-
-  if (flags & ~(UV_FS_COPYFILE_EXCL |
-                UV_FS_COPYFILE_FICLONE |
-                UV_FS_COPYFILE_FICLONE_FORCE)) {
-    return UV_EINVAL;
-  }
-
-  PATH2;
-  req->flags = flags;
-  POST;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/fsevents.cpp b/wpiutil/src/main/native/libuv/src/unix/fsevents.cpp
deleted file mode 100644
index 32d280f..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/fsevents.cpp
+++ /dev/null
@@ -1,922 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#if TARGET_OS_IPHONE || MAC_OS_X_VERSION_MAX_ALLOWED < 1070
-
-/* iOS (currently) doesn't provide the FSEvents-API (nor CoreServices) */
-/* macOS prior to 10.7 doesn't provide the full FSEvents API so use kqueue */
-
-int uv__fsevents_init(uv_fs_event_t* handle) {
-  return 0;
-}
-
-
-int uv__fsevents_close(uv_fs_event_t* handle) {
-  return 0;
-}
-
-
-void uv__fsevents_loop_delete(uv_loop_t* loop) {
-}
-
-#else /* TARGET_OS_IPHONE */
-
-#include <dlfcn.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <pthread.h>
-
-#include <CoreFoundation/CFRunLoop.h>
-#include <CoreServices/CoreServices.h>
-
-/* These are macros to avoid "initializer element is not constant" errors
- * with old versions of gcc.
- */
-#define kFSEventsModified (kFSEventStreamEventFlagItemFinderInfoMod |         \
-                           kFSEventStreamEventFlagItemModified |              \
-                           kFSEventStreamEventFlagItemInodeMetaMod |          \
-                           kFSEventStreamEventFlagItemChangeOwner |           \
-                           kFSEventStreamEventFlagItemXattrMod)
-
-#define kFSEventsRenamed  (kFSEventStreamEventFlagItemCreated |               \
-                           kFSEventStreamEventFlagItemRemoved |               \
-                           kFSEventStreamEventFlagItemRenamed)
-
-#define kFSEventsSystem   (kFSEventStreamEventFlagUserDropped |               \
-                           kFSEventStreamEventFlagKernelDropped |             \
-                           kFSEventStreamEventFlagEventIdsWrapped |           \
-                           kFSEventStreamEventFlagHistoryDone |               \
-                           kFSEventStreamEventFlagMount |                     \
-                           kFSEventStreamEventFlagUnmount |                   \
-                           kFSEventStreamEventFlagRootChanged)
-
-typedef struct uv__fsevents_event_s uv__fsevents_event_t;
-typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t;
-typedef struct uv__cf_loop_state_s uv__cf_loop_state_t;
-
-enum uv__cf_loop_signal_type_e {
-  kUVCFLoopSignalRegular,
-  kUVCFLoopSignalClosing
-};
-typedef enum uv__cf_loop_signal_type_e uv__cf_loop_signal_type_t;
-
-struct uv__cf_loop_signal_s {
-  QUEUE member;
-  uv_fs_event_t* handle;
-  uv__cf_loop_signal_type_t type;
-};
-
-struct uv__fsevents_event_s {
-  QUEUE member;
-  int events;
-  char path[1];
-};
-
-struct uv__cf_loop_state_s {
-  CFRunLoopRef loop;
-  CFRunLoopSourceRef signal_source;
-  int fsevent_need_reschedule;
-  FSEventStreamRef fsevent_stream;
-  uv_sem_t fsevent_sem;
-  uv_mutex_t fsevent_mutex;
-  void* fsevent_handles[2];
-  unsigned int fsevent_handle_count;
-};
-
-/* Forward declarations */
-static void uv__cf_loop_cb(void* arg);
-static void* uv__cf_loop_runner(void* arg);
-static int uv__cf_loop_signal(uv_loop_t* loop,
-                              uv_fs_event_t* handle,
-                              uv__cf_loop_signal_type_t type);
-
-/* Lazy-loaded by uv__fsevents_global_init(). */
-static CFArrayRef (*pCFArrayCreate)(CFAllocatorRef,
-                                    const void**,
-                                    CFIndex,
-                                    const CFArrayCallBacks*);
-static void (*pCFRelease)(CFTypeRef);
-static void (*pCFRunLoopAddSource)(CFRunLoopRef,
-                                   CFRunLoopSourceRef,
-                                   CFStringRef);
-static CFRunLoopRef (*pCFRunLoopGetCurrent)(void);
-static void (*pCFRunLoopRemoveSource)(CFRunLoopRef,
-                                      CFRunLoopSourceRef,
-                                      CFStringRef);
-static void (*pCFRunLoopRun)(void);
-static CFRunLoopSourceRef (*pCFRunLoopSourceCreate)(CFAllocatorRef,
-                                                    CFIndex,
-                                                    CFRunLoopSourceContext*);
-static void (*pCFRunLoopSourceSignal)(CFRunLoopSourceRef);
-static void (*pCFRunLoopStop)(CFRunLoopRef);
-static void (*pCFRunLoopWakeUp)(CFRunLoopRef);
-static CFStringRef (*pCFStringCreateWithFileSystemRepresentation)(
-    CFAllocatorRef,
-    const char*);
-static CFStringEncoding (*pCFStringGetSystemEncoding)(void);
-static CFStringRef (*pkCFRunLoopDefaultMode);
-static FSEventStreamRef (*pFSEventStreamCreate)(CFAllocatorRef,
-                                                FSEventStreamCallback,
-                                                FSEventStreamContext*,
-                                                CFArrayRef,
-                                                FSEventStreamEventId,
-                                                CFTimeInterval,
-                                                FSEventStreamCreateFlags);
-static void (*pFSEventStreamFlushSync)(FSEventStreamRef);
-static void (*pFSEventStreamInvalidate)(FSEventStreamRef);
-static void (*pFSEventStreamRelease)(FSEventStreamRef);
-static void (*pFSEventStreamScheduleWithRunLoop)(FSEventStreamRef,
-                                                 CFRunLoopRef,
-                                                 CFStringRef);
-static Boolean (*pFSEventStreamStart)(FSEventStreamRef);
-static void (*pFSEventStreamStop)(FSEventStreamRef);
-
-#define UV__FSEVENTS_PROCESS(handle, block)                                   \
-    do {                                                                      \
-      QUEUE events;                                                           \
-      QUEUE* q;                                                               \
-      uv__fsevents_event_t* event;                                            \
-      int err;                                                                \
-      uv_mutex_lock(&(handle)->cf_mutex);                                     \
-      /* Split-off all events and empty original queue */                     \
-      QUEUE_MOVE(&(handle)->cf_events, &events);                              \
-      /* Get error (if any) and zero original one */                          \
-      err = (handle)->cf_error;                                               \
-      (handle)->cf_error = 0;                                                 \
-      uv_mutex_unlock(&(handle)->cf_mutex);                                   \
-      /* Loop through events, deallocating each after processing */           \
-      while (!QUEUE_EMPTY(&events)) {                                         \
-        q = QUEUE_HEAD(&events);                                              \
-        event = QUEUE_DATA(q, uv__fsevents_event_t, member);                  \
-        QUEUE_REMOVE(q);                                                      \
-        /* NOTE: Checking uv__is_active() is required here, because handle    \
-         * callback may close handle and invoking it after it will lead to    \
-         * incorrect behaviour */                                             \
-        if (!uv__is_closing((handle)) && uv__is_active((handle)))             \
-          block                                                               \
-        /* Free allocated data */                                             \
-        uv__free(event);                                                      \
-      }                                                                       \
-      if (err != 0 && !uv__is_closing((handle)) && uv__is_active((handle)))   \
-        (handle)->cb((handle), NULL, 0, err);                                 \
-    } while (0)
-
-
-/* Runs in UV loop's thread, when there're events to report to handle */
-static void uv__fsevents_cb(uv_async_t* cb) {
-  uv_fs_event_t* handle;
-
-  handle = (uv_fs_event_t*)cb->data;
-
-  UV__FSEVENTS_PROCESS(handle, {
-    handle->cb(handle, event->path[0] ? event->path : NULL, event->events, 0);
-  });
-}
-
-
-/* Runs in CF thread, pushed event into handle's event list */
-static void uv__fsevents_push_event(uv_fs_event_t* handle,
-                                    QUEUE* events,
-                                    int err) {
-  assert(events != NULL || err != 0);
-  uv_mutex_lock(&handle->cf_mutex);
-
-  /* Concatenate two queues */
-  if (events != NULL)
-    QUEUE_ADD(&handle->cf_events, events);
-
-  /* Propagate error */
-  if (err != 0)
-    handle->cf_error = err;
-  uv_mutex_unlock(&handle->cf_mutex);
-
-  uv_async_send(handle->cf_cb);
-}
-
-
-/* Runs in CF thread, when there're events in FSEventStream */
-static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
-                                  void* info,
-                                  size_t numEvents,
-                                  void* eventPaths,
-                                  const FSEventStreamEventFlags eventFlags[],
-                                  const FSEventStreamEventId eventIds[]) {
-  size_t i;
-  int len;
-  char** paths;
-  char* path;
-  char* pos;
-  uv_fs_event_t* handle;
-  QUEUE* q;
-  uv_loop_t* loop;
-  uv__cf_loop_state_t* state;
-  uv__fsevents_event_t* event;
-  FSEventStreamEventFlags flags;
-  QUEUE head;
-
-  loop = (uv_loop_t*)info;
-  state = (uv__cf_loop_state_t*)loop->cf_state;
-  assert(state != NULL);
-  paths = (char**)eventPaths;
-
-  /* For each handle */
-  uv_mutex_lock(&state->fsevent_mutex);
-  QUEUE_FOREACH(q, &state->fsevent_handles) {
-    handle = QUEUE_DATA(q, uv_fs_event_t, cf_member);
-    QUEUE_INIT(&head);
-
-    /* Process and filter out events */
-    for (i = 0; i < numEvents; i++) {
-      flags = eventFlags[i];
-
-      /* Ignore system events */
-      if (flags & kFSEventsSystem)
-        continue;
-
-      path = paths[i];
-      len = strlen(path);
-
-      if (handle->realpath_len == 0)
-        continue; /* This should be unreachable */
-
-      /* Filter out paths that are outside handle's request */
-      if (len < handle->realpath_len)
-        continue;
-
-      if (handle->realpath_len != len &&
-          path[handle->realpath_len] != '/')
-        /* Make sure that realpath actually named a directory,
-         * or that we matched the whole string */
-        continue;
-
-      if (memcmp(path, handle->realpath, handle->realpath_len) != 0)
-        continue;
-
-      if (!(handle->realpath_len == 1 && handle->realpath[0] == '/')) {
-        /* Remove common prefix, unless the watched folder is "/" */
-        path += handle->realpath_len;
-        len -= handle->realpath_len;
-
-        /* Ignore events with path equal to directory itself */
-        if (len <= 1 && (flags & kFSEventStreamEventFlagItemIsDir))
-          continue;
-
-        if (len == 0) {
-          /* Since we're using fsevents to watch the file itself,
-           * realpath == path, and we now need to get the basename of the file back
-           * (for commonality with other codepaths and platforms). */
-          while (len < handle->realpath_len && path[-1] != '/') {
-            path--;
-            len++;
-          }
-          /* Created and Removed seem to be always set, but don't make sense */
-          flags &= ~kFSEventsRenamed;
-        } else {
-          /* Skip forward slash */
-          path++;
-          len--;
-        }
-      }
-
-      /* Do not emit events from subdirectories (without option set) */
-      if ((handle->cf_flags & UV_FS_EVENT_RECURSIVE) == 0 && *path != '\0') {
-        pos = strchr(path + 1, '/');
-        if (pos != NULL)
-          continue;
-      }
-
-      event = (uv__fsevents_event_t*)uv__malloc(sizeof(*event) + len);
-      if (event == NULL)
-        break;
-
-      memset(event, 0, sizeof(*event));
-      memcpy(event->path, path, len + 1);
-      event->events = UV_RENAME;
-
-      if (0 == (flags & kFSEventsRenamed)) {
-        if (0 != (flags & kFSEventsModified) ||
-            0 == (flags & kFSEventStreamEventFlagItemIsDir))
-          event->events = UV_CHANGE;
-      }
-
-      QUEUE_INSERT_TAIL(&head, &event->member);
-    }
-
-    if (!QUEUE_EMPTY(&head))
-      uv__fsevents_push_event(handle, &head, 0);
-  }
-  uv_mutex_unlock(&state->fsevent_mutex);
-}
-
-
-/* Runs in CF thread */
-static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) {
-  uv__cf_loop_state_t* state;
-  FSEventStreamContext ctx;
-  FSEventStreamRef ref;
-  CFAbsoluteTime latency;
-  FSEventStreamCreateFlags flags;
-
-  /* Initialize context */
-  ctx.version = 0;
-  ctx.info = loop;
-  ctx.retain = NULL;
-  ctx.release = NULL;
-  ctx.copyDescription = NULL;
-
-  latency = 0.05;
-
-  /* Explanation of selected flags:
-   * 1. NoDefer - without this flag, events that are happening continuously
-   *    (i.e. each event is happening after time interval less than `latency`,
-   *    counted from previous event), will be deferred and passed to callback
-   *    once they'll either fill whole OS buffer, or when this continuous stream
-   *    will stop (i.e. there'll be delay between events, bigger than
-   *    `latency`).
-   *    Specifying this flag will invoke callback after `latency` time passed
-   *    since event.
-   * 2. FileEvents - fire callback for file changes too (by default it is firing
-   *    it only for directory changes).
-   */
-  flags = kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents;
-
-  /*
-   * NOTE: It might sound like a good idea to remember last seen StreamEventId,
-   * but in reality one dir might have last StreamEventId less than, the other,
-   * that is being watched now. Which will cause FSEventStream API to report
-   * changes to files from the past.
-   */
-  ref = pFSEventStreamCreate(NULL,
-                             &uv__fsevents_event_cb,
-                             &ctx,
-                             paths,
-                             kFSEventStreamEventIdSinceNow,
-                             latency,
-                             flags);
-  assert(ref != NULL);
-
-  state = (uv__cf_loop_state_t*)loop->cf_state;
-  pFSEventStreamScheduleWithRunLoop(ref,
-                                    state->loop,
-                                    *pkCFRunLoopDefaultMode);
-  if (!pFSEventStreamStart(ref)) {
-    pFSEventStreamInvalidate(ref);
-    pFSEventStreamRelease(ref);
-    return UV_EMFILE;
-  }
-
-  state->fsevent_stream = ref;
-  return 0;
-}
-
-
-/* Runs in CF thread */
-static void uv__fsevents_destroy_stream(uv_loop_t* loop) {
-  uv__cf_loop_state_t* state;
-
-  state = (uv__cf_loop_state_t*)loop->cf_state;
-
-  if (state->fsevent_stream == NULL)
-    return;
-
-  /* Stop emitting events */
-  pFSEventStreamStop(state->fsevent_stream);
-
-  /* Release stream */
-  pFSEventStreamInvalidate(state->fsevent_stream);
-  pFSEventStreamRelease(state->fsevent_stream);
-  state->fsevent_stream = NULL;
-}
-
-
-/* Runs in CF thread, when there're new fsevent handles to add to stream */
-static void uv__fsevents_reschedule(uv_fs_event_t* handle,
-                                    uv__cf_loop_signal_type_t type) {
-  uv__cf_loop_state_t* state;
-  QUEUE* q;
-  uv_fs_event_t* curr;
-  CFArrayRef cf_paths;
-  CFStringRef* paths;
-  unsigned int i;
-  int err;
-  unsigned int path_count;
-
-  state = (uv__cf_loop_state_t*)handle->loop->cf_state;
-  paths = NULL;
-  cf_paths = NULL;
-  err = 0;
-  /* NOTE: `i` is used in deallocation loop below */
-  i = 0;
-
-  /* Optimization to prevent O(n^2) time spent when starting to watch
-   * many files simultaneously
-   */
-  uv_mutex_lock(&state->fsevent_mutex);
-  if (state->fsevent_need_reschedule == 0) {
-    uv_mutex_unlock(&state->fsevent_mutex);
-    goto final;
-  }
-  state->fsevent_need_reschedule = 0;
-  uv_mutex_unlock(&state->fsevent_mutex);
-
-  /* Destroy previous FSEventStream */
-  uv__fsevents_destroy_stream(handle->loop);
-
-  /* Any failure below will be a memory failure */
-  err = UV_ENOMEM;
-
-  /* Create list of all watched paths */
-  uv_mutex_lock(&state->fsevent_mutex);
-  path_count = state->fsevent_handle_count;
-  if (path_count != 0) {
-    paths = (CFStringRef*)uv__malloc(sizeof(*paths) * path_count);
-    if (paths == NULL) {
-      uv_mutex_unlock(&state->fsevent_mutex);
-      goto final;
-    }
-
-    q = &state->fsevent_handles;
-    for (; i < path_count; i++) {
-      q = QUEUE_NEXT(q);
-      assert(q != &state->fsevent_handles);
-      curr = QUEUE_DATA(q, uv_fs_event_t, cf_member);
-
-      assert(curr->realpath != NULL);
-      paths[i] =
-          pCFStringCreateWithFileSystemRepresentation(NULL, curr->realpath);
-      if (paths[i] == NULL) {
-        uv_mutex_unlock(&state->fsevent_mutex);
-        goto final;
-      }
-    }
-  }
-  uv_mutex_unlock(&state->fsevent_mutex);
-  err = 0;
-
-  if (path_count != 0) {
-    /* Create new FSEventStream */
-    cf_paths = pCFArrayCreate(NULL, (const void**) paths, path_count, NULL);
-    if (cf_paths == NULL) {
-      err = UV_ENOMEM;
-      goto final;
-    }
-    err = uv__fsevents_create_stream(handle->loop, cf_paths);
-  }
-
-final:
-  /* Deallocate all paths in case of failure */
-  if (err != 0) {
-    if (cf_paths == NULL) {
-      while (i != 0)
-        pCFRelease(paths[--i]);
-      uv__free(paths);
-    } else {
-      /* CFArray takes ownership of both strings and original C-array */
-      pCFRelease(cf_paths);
-    }
-
-    /* Broadcast error to all handles */
-    uv_mutex_lock(&state->fsevent_mutex);
-    QUEUE_FOREACH(q, &state->fsevent_handles) {
-      curr = QUEUE_DATA(q, uv_fs_event_t, cf_member);
-      uv__fsevents_push_event(curr, NULL, err);
-    }
-    uv_mutex_unlock(&state->fsevent_mutex);
-  }
-
-  /*
-   * Main thread will block until the removal of handle from the list,
-   * we must tell it when we're ready.
-   *
-   * NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close`
-   */
-  if (type == kUVCFLoopSignalClosing)
-    uv_sem_post(&state->fsevent_sem);
-}
-
-
-static int uv__fsevents_global_init(void) {
-  static pthread_mutex_t global_init_mutex = PTHREAD_MUTEX_INITIALIZER;
-  static void* core_foundation_handle;
-  static void* core_services_handle;
-  int err;
-
-  err = 0;
-  pthread_mutex_lock(&global_init_mutex);
-  if (core_foundation_handle != NULL)
-    goto out;
-
-  /* The libraries are never unloaded because we currently don't have a good
-   * mechanism for keeping a reference count. It's unlikely to be an issue
-   * but if it ever becomes one, we can turn the dynamic library handles into
-   * per-event loop properties and have the dynamic linker keep track for us.
-   */
-  err = UV_ENOSYS;
-  core_foundation_handle = dlopen("/System/Library/Frameworks/"
-                                  "CoreFoundation.framework/"
-                                  "Versions/A/CoreFoundation",
-                                  RTLD_LAZY | RTLD_LOCAL);
-  if (core_foundation_handle == NULL)
-    goto out;
-
-  core_services_handle = dlopen("/System/Library/Frameworks/"
-                                "CoreServices.framework/"
-                                "Versions/A/CoreServices",
-                                RTLD_LAZY | RTLD_LOCAL);
-  if (core_services_handle == NULL)
-    goto out;
-
-  err = UV_ENOENT;
-#define V(handle, symbol)                                                     \
-  do {                                                                        \
-    *(void **)(&p ## symbol) = dlsym((handle), #symbol);                      \
-    if (p ## symbol == NULL)                                                  \
-      goto out;                                                               \
-  }                                                                           \
-  while (0)
-  V(core_foundation_handle, CFArrayCreate);
-  V(core_foundation_handle, CFRelease);
-  V(core_foundation_handle, CFRunLoopAddSource);
-  V(core_foundation_handle, CFRunLoopGetCurrent);
-  V(core_foundation_handle, CFRunLoopRemoveSource);
-  V(core_foundation_handle, CFRunLoopRun);
-  V(core_foundation_handle, CFRunLoopSourceCreate);
-  V(core_foundation_handle, CFRunLoopSourceSignal);
-  V(core_foundation_handle, CFRunLoopStop);
-  V(core_foundation_handle, CFRunLoopWakeUp);
-  V(core_foundation_handle, CFStringCreateWithFileSystemRepresentation);
-  V(core_foundation_handle, CFStringGetSystemEncoding);
-  V(core_foundation_handle, kCFRunLoopDefaultMode);
-  V(core_services_handle, FSEventStreamCreate);
-  V(core_services_handle, FSEventStreamFlushSync);
-  V(core_services_handle, FSEventStreamInvalidate);
-  V(core_services_handle, FSEventStreamRelease);
-  V(core_services_handle, FSEventStreamScheduleWithRunLoop);
-  V(core_services_handle, FSEventStreamStart);
-  V(core_services_handle, FSEventStreamStop);
-#undef V
-  err = 0;
-
-out:
-  if (err && core_services_handle != NULL) {
-    dlclose(core_services_handle);
-    core_services_handle = NULL;
-  }
-
-  if (err && core_foundation_handle != NULL) {
-    dlclose(core_foundation_handle);
-    core_foundation_handle = NULL;
-  }
-
-  pthread_mutex_unlock(&global_init_mutex);
-  return err;
-}
-
-
-/* Runs in UV loop */
-static int uv__fsevents_loop_init(uv_loop_t* loop) {
-  CFRunLoopSourceContext ctx;
-  uv__cf_loop_state_t* state;
-  pthread_attr_t attr_storage;
-  pthread_attr_t* attr;
-  int err;
-
-  if (loop->cf_state != NULL)
-    return 0;
-
-  err = uv__fsevents_global_init();
-  if (err)
-    return err;
-
-  state = (uv__cf_loop_state_t*)uv__calloc(1, sizeof(*state));
-  if (state == NULL)
-    return UV_ENOMEM;
-
-  err = uv_mutex_init(&loop->cf_mutex);
-  if (err)
-    goto fail_mutex_init;
-
-  err = uv_sem_init(&loop->cf_sem, 0);
-  if (err)
-    goto fail_sem_init;
-
-  QUEUE_INIT(&loop->cf_signals);
-
-  err = uv_sem_init(&state->fsevent_sem, 0);
-  if (err)
-    goto fail_fsevent_sem_init;
-
-  err = uv_mutex_init(&state->fsevent_mutex);
-  if (err)
-    goto fail_fsevent_mutex_init;
-
-  QUEUE_INIT(&state->fsevent_handles);
-  state->fsevent_need_reschedule = 0;
-  state->fsevent_handle_count = 0;
-
-  memset(&ctx, 0, sizeof(ctx));
-  ctx.info = loop;
-  ctx.perform = uv__cf_loop_cb;
-  state->signal_source = pCFRunLoopSourceCreate(NULL, 0, &ctx);
-  if (state->signal_source == NULL) {
-    err = UV_ENOMEM;
-    goto fail_signal_source_create;
-  }
-
-  /* In the unlikely event that pthread_attr_init() fails, create the thread
-   * with the default stack size. We'll use a little more address space but
-   * that in itself is not a fatal error.
-   */
-  attr = &attr_storage;
-  if (pthread_attr_init(attr))
-    attr = NULL;
-
-  if (attr != NULL)
-    if (pthread_attr_setstacksize(attr, 4 * PTHREAD_STACK_MIN))
-      abort();
-
-  loop->cf_state = state;
-
-  /* uv_thread_t is an alias for pthread_t. */
-  err = UV__ERR(pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop));
-
-  if (attr != NULL)
-    pthread_attr_destroy(attr);
-
-  if (err)
-    goto fail_thread_create;
-
-  /* Synchronize threads */
-  uv_sem_wait(&loop->cf_sem);
-  return 0;
-
-fail_thread_create:
-  loop->cf_state = NULL;
-
-fail_signal_source_create:
-  uv_mutex_destroy(&state->fsevent_mutex);
-
-fail_fsevent_mutex_init:
-  uv_sem_destroy(&state->fsevent_sem);
-
-fail_fsevent_sem_init:
-  uv_sem_destroy(&loop->cf_sem);
-
-fail_sem_init:
-  uv_mutex_destroy(&loop->cf_mutex);
-
-fail_mutex_init:
-  uv__free(state);
-  return err;
-}
-
-
-/* Runs in UV loop */
-void uv__fsevents_loop_delete(uv_loop_t* loop) {
-  uv__cf_loop_signal_t* s;
-  uv__cf_loop_state_t* state;
-  QUEUE* q;
-
-  if (loop->cf_state == NULL)
-    return;
-
-  if (uv__cf_loop_signal(loop, NULL, kUVCFLoopSignalRegular) != 0)
-    abort();
-
-  uv_thread_join(&loop->cf_thread);
-  uv_sem_destroy(&loop->cf_sem);
-  uv_mutex_destroy(&loop->cf_mutex);
-
-  /* Free any remaining data */
-  while (!QUEUE_EMPTY(&loop->cf_signals)) {
-    q = QUEUE_HEAD(&loop->cf_signals);
-    s = QUEUE_DATA(q, uv__cf_loop_signal_t, member);
-    QUEUE_REMOVE(q);
-    uv__free(s);
-  }
-
-  /* Destroy state */
-  state = (uv__cf_loop_state_t*)loop->cf_state;
-  uv_sem_destroy(&state->fsevent_sem);
-  uv_mutex_destroy(&state->fsevent_mutex);
-  pCFRelease(state->signal_source);
-  uv__free(state);
-  loop->cf_state = NULL;
-}
-
-
-/* Runs in CF thread. This is the CF loop's body */
-static void* uv__cf_loop_runner(void* arg) {
-  uv_loop_t* loop;
-  uv__cf_loop_state_t* state;
-
-  loop = (uv_loop_t*)arg;
-  state = (uv__cf_loop_state_t*)loop->cf_state;
-  state->loop = pCFRunLoopGetCurrent();
-
-  pCFRunLoopAddSource(state->loop,
-                      state->signal_source,
-                      *pkCFRunLoopDefaultMode);
-
-  uv_sem_post(&loop->cf_sem);
-
-  pCFRunLoopRun();
-  pCFRunLoopRemoveSource(state->loop,
-                         state->signal_source,
-                         *pkCFRunLoopDefaultMode);
-
-  return NULL;
-}
-
-
-/* Runs in CF thread, executed after `uv__cf_loop_signal()` */
-static void uv__cf_loop_cb(void* arg) {
-  uv_loop_t* loop;
-  uv__cf_loop_state_t* state;
-  QUEUE* item;
-  QUEUE split_head;
-  uv__cf_loop_signal_t* s;
-
-  loop = (uv_loop_t*)arg;
-  state = (uv__cf_loop_state_t*)loop->cf_state;
-
-  uv_mutex_lock(&loop->cf_mutex);
-  QUEUE_MOVE(&loop->cf_signals, &split_head);
-  uv_mutex_unlock(&loop->cf_mutex);
-
-  while (!QUEUE_EMPTY(&split_head)) {
-    item = QUEUE_HEAD(&split_head);
-    QUEUE_REMOVE(item);
-
-    s = QUEUE_DATA(item, uv__cf_loop_signal_t, member);
-
-    /* This was a termination signal */
-    if (s->handle == NULL)
-      pCFRunLoopStop(state->loop);
-    else
-      uv__fsevents_reschedule(s->handle, s->type);
-
-    uv__free(s);
-  }
-}
-
-
-/* Runs in UV loop to notify CF thread */
-int uv__cf_loop_signal(uv_loop_t* loop,
-                       uv_fs_event_t* handle,
-                       uv__cf_loop_signal_type_t type) {
-  uv__cf_loop_signal_t* item;
-  uv__cf_loop_state_t* state;
-
-  item = (uv__cf_loop_signal_t*)uv__malloc(sizeof(*item));
-  if (item == NULL)
-    return UV_ENOMEM;
-
-  item->handle = handle;
-  item->type = type;
-
-  uv_mutex_lock(&loop->cf_mutex);
-  QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member);
-  uv_mutex_unlock(&loop->cf_mutex);
-
-  state = (uv__cf_loop_state_t*)loop->cf_state;
-  assert(state != NULL);
-  pCFRunLoopSourceSignal(state->signal_source);
-  pCFRunLoopWakeUp(state->loop);
-
-  return 0;
-}
-
-
-/* Runs in UV loop to initialize handle */
-int uv__fsevents_init(uv_fs_event_t* handle) {
-  int err;
-  uv__cf_loop_state_t* state;
-
-  err = uv__fsevents_loop_init(handle->loop);
-  if (err)
-    return err;
-
-  /* Get absolute path to file */
-  handle->realpath = realpath(handle->path, NULL);
-  if (handle->realpath == NULL)
-    return UV__ERR(errno);
-  handle->realpath_len = strlen(handle->realpath);
-
-  /* Initialize event queue */
-  QUEUE_INIT(&handle->cf_events);
-  handle->cf_error = 0;
-
-  /*
-   * Events will occur in other thread.
-   * Initialize callback for getting them back into event loop's thread
-   */
-  handle->cf_cb = (uv_async_t*)uv__malloc(sizeof(*handle->cf_cb));
-  if (handle->cf_cb == NULL) {
-    err = UV_ENOMEM;
-    goto fail_cf_cb_malloc;
-  }
-
-  handle->cf_cb->data = handle;
-  uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb);
-  handle->cf_cb->flags |= UV_HANDLE_INTERNAL;
-  uv_unref((uv_handle_t*) handle->cf_cb);
-
-  err = uv_mutex_init(&handle->cf_mutex);
-  if (err)
-    goto fail_cf_mutex_init;
-
-  /* Insert handle into the list */
-  state = (uv__cf_loop_state_t*)handle->loop->cf_state;
-  uv_mutex_lock(&state->fsevent_mutex);
-  QUEUE_INSERT_TAIL(&state->fsevent_handles, &handle->cf_member);
-  state->fsevent_handle_count++;
-  state->fsevent_need_reschedule = 1;
-  uv_mutex_unlock(&state->fsevent_mutex);
-
-  /* Reschedule FSEventStream */
-  assert(handle != NULL);
-  err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalRegular);
-  if (err)
-    goto fail_loop_signal;
-
-  return 0;
-
-fail_loop_signal:
-  uv_mutex_destroy(&handle->cf_mutex);
-
-fail_cf_mutex_init:
-  uv__free(handle->cf_cb);
-  handle->cf_cb = NULL;
-
-fail_cf_cb_malloc:
-  uv__free(handle->realpath);
-  handle->realpath = NULL;
-  handle->realpath_len = 0;
-
-  return err;
-}
-
-
-/* Runs in UV loop to de-initialize handle */
-int uv__fsevents_close(uv_fs_event_t* handle) {
-  int err;
-  uv__cf_loop_state_t* state;
-
-  if (handle->cf_cb == NULL)
-    return UV_EINVAL;
-
-  /* Remove handle from  the list */
-  state = (uv__cf_loop_state_t*)handle->loop->cf_state;
-  uv_mutex_lock(&state->fsevent_mutex);
-  QUEUE_REMOVE(&handle->cf_member);
-  state->fsevent_handle_count--;
-  state->fsevent_need_reschedule = 1;
-  uv_mutex_unlock(&state->fsevent_mutex);
-
-  /* Reschedule FSEventStream */
-  assert(handle != NULL);
-  err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalClosing);
-  if (err)
-    return UV__ERR(err);
-
-  /* Wait for deinitialization */
-  uv_sem_wait(&state->fsevent_sem);
-
-  uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) uv__free);
-  handle->cf_cb = NULL;
-
-  /* Free data in queue */
-  UV__FSEVENTS_PROCESS(handle, {
-    /* NOP */
-  });
-
-  uv_mutex_destroy(&handle->cf_mutex);
-  uv__free(handle->realpath);
-  handle->realpath = NULL;
-  handle->realpath_len = 0;
-
-  return 0;
-}
-
-#endif /* TARGET_OS_IPHONE */
diff --git a/wpiutil/src/main/native/libuv/src/unix/getaddrinfo.cpp b/wpiutil/src/main/native/libuv/src/unix/getaddrinfo.cpp
deleted file mode 100644
index 9a26b45..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/getaddrinfo.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/* Expose glibc-specific EAI_* error codes. Needs to be defined before we
- * include any headers.
- */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#include "uv.h"
-#include "internal.h"
-#include "idna.h"
-
-#include <errno.h>
-#include <stddef.h> /* NULL */
-#include <stdlib.h>
-#include <string.h>
-#include <net/if.h> /* if_indextoname() */
-
-/* EAI_* constants. */
-#include <netdb.h>
-
-
-int uv__getaddrinfo_translate_error(int sys_err) {
-  switch (sys_err) {
-  case 0: return 0;
-#if defined(EAI_ADDRFAMILY)
-  case EAI_ADDRFAMILY: return UV_EAI_ADDRFAMILY;
-#endif
-#if defined(EAI_AGAIN)
-  case EAI_AGAIN: return UV_EAI_AGAIN;
-#endif
-#if defined(EAI_BADFLAGS)
-  case EAI_BADFLAGS: return UV_EAI_BADFLAGS;
-#endif
-#if defined(EAI_BADHINTS)
-  case EAI_BADHINTS: return UV_EAI_BADHINTS;
-#endif
-#if defined(EAI_CANCELED)
-  case EAI_CANCELED: return UV_EAI_CANCELED;
-#endif
-#if defined(EAI_FAIL)
-  case EAI_FAIL: return UV_EAI_FAIL;
-#endif
-#if defined(EAI_FAMILY)
-  case EAI_FAMILY: return UV_EAI_FAMILY;
-#endif
-#if defined(EAI_MEMORY)
-  case EAI_MEMORY: return UV_EAI_MEMORY;
-#endif
-#if defined(EAI_NODATA)
-  case EAI_NODATA: return UV_EAI_NODATA;
-#endif
-#if defined(EAI_NONAME)
-# if !defined(EAI_NODATA) || EAI_NODATA != EAI_NONAME
-  case EAI_NONAME: return UV_EAI_NONAME;
-# endif
-#endif
-#if defined(EAI_OVERFLOW)
-  case EAI_OVERFLOW: return UV_EAI_OVERFLOW;
-#endif
-#if defined(EAI_PROTOCOL)
-  case EAI_PROTOCOL: return UV_EAI_PROTOCOL;
-#endif
-#if defined(EAI_SERVICE)
-  case EAI_SERVICE: return UV_EAI_SERVICE;
-#endif
-#if defined(EAI_SOCKTYPE)
-  case EAI_SOCKTYPE: return UV_EAI_SOCKTYPE;
-#endif
-#if defined(EAI_SYSTEM)
-  case EAI_SYSTEM: return UV__ERR(errno);
-#endif
-  }
-  assert(!"unknown EAI_* error code");
-  abort();
-#ifndef __SUNPRO_C
-  return 0;  /* Pacify compiler. */
-#endif
-}
-
-
-static void uv__getaddrinfo_work(struct uv__work* w) {
-  uv_getaddrinfo_t* req;
-  int err;
-
-  req = container_of(w, uv_getaddrinfo_t, work_req);
-  err = getaddrinfo(req->hostname, req->service, req->hints, &req->addrinfo);
-  req->retcode = uv__getaddrinfo_translate_error(err);
-}
-
-
-static void uv__getaddrinfo_done(struct uv__work* w, int status) {
-  uv_getaddrinfo_t* req;
-
-  req = container_of(w, uv_getaddrinfo_t, work_req);
-  uv__req_unregister(req->loop, req);
-
-  /* See initialization in uv_getaddrinfo(). */
-  if (req->hints)
-    uv__free(req->hints);
-  else if (req->service)
-    uv__free(req->service);
-  else if (req->hostname)
-    uv__free(req->hostname);
-  else
-    assert(0);
-
-  req->hints = NULL;
-  req->service = NULL;
-  req->hostname = NULL;
-
-  if (status == UV_ECANCELED) {
-    assert(req->retcode == 0);
-    req->retcode = UV_EAI_CANCELED;
-  }
-
-  if (req->cb)
-    req->cb(req, req->retcode, req->addrinfo);
-}
-
-
-int uv_getaddrinfo(uv_loop_t* loop,
-                   uv_getaddrinfo_t* req,
-                   uv_getaddrinfo_cb cb,
-                   const char* hostname,
-                   const char* service,
-                   const struct addrinfo* hints) {
-  char hostname_ascii[256];
-  size_t hostname_len;
-  size_t service_len;
-  size_t hints_len;
-  size_t len;
-  char* buf;
-  long rc;
-
-  if (req == NULL || (hostname == NULL && service == NULL))
-    return UV_EINVAL;
-
-  /* FIXME(bnoordhuis) IDNA does not seem to work z/OS,
-   * probably because it uses EBCDIC rather than ASCII.
-   */
-#ifdef __MVS__
-  (void) &hostname_ascii;
-#else
-  if (hostname != NULL) {
-    rc = uv__idna_toascii(hostname,
-                          hostname + strlen(hostname),
-                          hostname_ascii,
-                          hostname_ascii + sizeof(hostname_ascii));
-    if (rc < 0)
-      return rc;
-    hostname = hostname_ascii;
-  }
-#endif
-
-  hostname_len = hostname ? strlen(hostname) + 1 : 0;
-  service_len = service ? strlen(service) + 1 : 0;
-  hints_len = hints ? sizeof(*hints) : 0;
-  buf = (char*)uv__malloc(hostname_len + service_len + hints_len);
-
-  if (buf == NULL)
-    return UV_ENOMEM;
-
-  uv__req_init(loop, req, UV_GETADDRINFO);
-  req->loop = loop;
-  req->cb = cb;
-  req->addrinfo = NULL;
-  req->hints = NULL;
-  req->service = NULL;
-  req->hostname = NULL;
-  req->retcode = 0;
-
-  /* order matters, see uv_getaddrinfo_done() */
-  len = 0;
-
-  if (hints) {
-    req->hints = (struct addrinfo*)memcpy(buf + len, hints, sizeof(*hints));
-    len += sizeof(*hints);
-  }
-
-  if (service) {
-    req->service = (char*)memcpy(buf + len, service, service_len);
-    len += service_len;
-  }
-
-  if (hostname)
-    req->hostname = (char*)memcpy(buf + len, hostname, hostname_len);
-
-  if (cb) {
-    uv__work_submit(loop,
-                    &req->work_req,
-                    UV__WORK_SLOW_IO,
-                    uv__getaddrinfo_work,
-                    uv__getaddrinfo_done);
-    return 0;
-  } else {
-    uv__getaddrinfo_work(&req->work_req);
-    uv__getaddrinfo_done(&req->work_req, 0);
-    return req->retcode;
-  }
-}
-
-
-void uv_freeaddrinfo(struct addrinfo* ai) {
-  if (ai)
-    freeaddrinfo(ai);
-}
-
-
-int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
-  char ifname_buf[UV_IF_NAMESIZE];
-  size_t len;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  if (if_indextoname(ifindex, ifname_buf) == NULL)
-    return UV__ERR(errno);
-
-  len = strnlen(ifname_buf, sizeof(ifname_buf));
-
-  if (*size <= len) {
-    *size = len + 1;
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, ifname_buf, len);
-  buffer[len] = '\0';
-  *size = len;
-
-  return 0;
-}
-
-int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
-  return uv_if_indextoname(ifindex, buffer, size);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/getnameinfo.cpp b/wpiutil/src/main/native/libuv/src/unix/getnameinfo.cpp
deleted file mode 100644
index 991002a..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/getnameinfo.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to
-* deal in the Software without restriction, including without limitation the
-* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-* sell copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in
-* all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-* IN THE SOFTWARE.
-*/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "uv.h"
-#include "internal.h"
-
-
-static void uv__getnameinfo_work(struct uv__work* w) {
-  uv_getnameinfo_t* req;
-  int err;
-  socklen_t salen;
-
-  req = container_of(w, uv_getnameinfo_t, work_req);
-
-  if (req->storage.ss_family == AF_INET)
-    salen = sizeof(struct sockaddr_in);
-  else if (req->storage.ss_family == AF_INET6)
-    salen = sizeof(struct sockaddr_in6);
-  else
-    abort();
-
-  err = getnameinfo((struct sockaddr*) &req->storage,
-                    salen,
-                    req->host,
-                    sizeof(req->host),
-                    req->service,
-                    sizeof(req->service),
-                    req->flags);
-  req->retcode = uv__getaddrinfo_translate_error(err);
-}
-
-static void uv__getnameinfo_done(struct uv__work* w, int status) {
-  uv_getnameinfo_t* req;
-  char* host;
-  char* service;
-
-  req = container_of(w, uv_getnameinfo_t, work_req);
-  uv__req_unregister(req->loop, req);
-  host = service = NULL;
-
-  if (status == UV_ECANCELED) {
-    assert(req->retcode == 0);
-    req->retcode = UV_EAI_CANCELED;
-  } else if (req->retcode == 0) {
-    host = req->host;
-    service = req->service;
-  }
-
-  if (req->getnameinfo_cb)
-    req->getnameinfo_cb(req, req->retcode, host, service);
-}
-
-/*
-* Entry point for getnameinfo
-* return 0 if a callback will be made
-* return error code if validation fails
-*/
-int uv_getnameinfo(uv_loop_t* loop,
-                   uv_getnameinfo_t* req,
-                   uv_getnameinfo_cb getnameinfo_cb,
-                   const struct sockaddr* addr,
-                   int flags) {
-  if (req == NULL || addr == NULL)
-    return UV_EINVAL;
-
-  if (addr->sa_family == AF_INET) {
-    memcpy(&req->storage,
-           addr,
-           sizeof(struct sockaddr_in));
-  } else if (addr->sa_family == AF_INET6) {
-    memcpy(&req->storage,
-           addr,
-           sizeof(struct sockaddr_in6));
-  } else {
-    return UV_EINVAL;
-  }
-
-  uv__req_init(loop, (uv_req_t*)req, UV_GETNAMEINFO);
-
-  req->getnameinfo_cb = getnameinfo_cb;
-  req->flags = flags;
-  req->type = UV_GETNAMEINFO;
-  req->loop = loop;
-  req->retcode = 0;
-
-  if (getnameinfo_cb) {
-    uv__work_submit(loop,
-                    &req->work_req,
-                    UV__WORK_SLOW_IO,
-                    uv__getnameinfo_work,
-                    uv__getnameinfo_done);
-    return 0;
-  } else {
-    uv__getnameinfo_work(&req->work_req);
-    uv__getnameinfo_done(&req->work_req, 0);
-    return req->retcode;
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/ibmi.cpp b/wpiutil/src/main/native/libuv/src/unix/ibmi.cpp
deleted file mode 100644
index 4b0be2d..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/ibmi.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <sys/time.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <utmp.h>
-#include <libgen.h>
-
-#include <sys/protosw.h>
-#include <procinfo.h>
-#include <sys/proc.h>
-#include <sys/procfs.h>
-
-#include <ctype.h>
-
-#include <sys/mntctl.h>
-#include <sys/vmount.h>
-#include <limits.h>
-#include <strings.h>
-#include <sys/vnode.h>
-
-#include <as400_protos.h>
-
-
-typedef struct {
-  int bytes_available;
-  int bytes_returned;
-  char current_date_and_time[8];
-  char system_name[8];
-  char elapsed_time[6];
-  char restricted_state_flag;
-  char reserved;
-  int percent_processing_unit_used;
-  int jobs_in_system;
-  int percent_permanent_addresses;
-  int percent_temporary_addresses;
-  int system_asp;
-  int percent_system_asp_used;
-  int total_auxiliary_storage;
-  int current_unprotected_storage_used;
-  int maximum_unprotected_storage_used;
-  int percent_db_capability;
-  int main_storage_size;
-  int number_of_partitions;
-  int partition_identifier;
-  int reserved1;
-  int current_processing_capacity;
-  char processor_sharing_attribute;
-  char reserved2[3];
-  int number_of_processors;
-  int active_jobs_in_system;
-  int active_threads_in_system;
-  int maximum_jobs_in_system;
-  int percent_temporary_256mb_segments_used;
-  int percent_temporary_4gb_segments_used;
-  int percent_permanent_256mb_segments_used;
-  int percent_permanent_4gb_segments_used;
-  int percent_current_interactive_performance;
-  int percent_uncapped_cpu_capacity_used;
-  int percent_shared_processor_pool_used;
-  long main_storage_size_long;
-} SSTS0200;
-
-
-static int get_ibmi_system_status(SSTS0200* rcvr) {
-  /* rcvrlen is input parameter 2 to QWCRSSTS */
-  unsigned int rcvrlen = sizeof(*rcvr);
-
-  /* format is input parameter 3 to QWCRSSTS ("SSTS0200" in EBCDIC) */
-  unsigned char format[] = {0xE2, 0xE2, 0xE3, 0xE2, 0xF0, 0xF2, 0xF0, 0xF0};
-
-  /* reset_status is input parameter 4 to QWCRSSTS ("*NO       " in EBCDIC) */
-  unsigned char reset_status[] = {
-    0x5C, 0xD5, 0xD6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
-  };
-
-  /* errcode is input parameter 5 to QWCRSSTS */
-  struct _errcode {
-    int bytes_provided;
-    int bytes_available;
-    char msgid[7];
-  } errcode;
-
-  /* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */
-  ILEpointer __attribute__((aligned(16))) qwcrssts_pointer;
-
-  /* qwcrssts_argv is the array of argument pointers to QWCRSSTS */
-  void* qwcrssts_argv[6];
-
-  /* Set the IBM i pointer to the QSYS/QWCRSSTS *PGM object */
-  int rc = _RSLOBJ2(&qwcrssts_pointer, RSLOBJ_TS_PGM, "QWCRSSTS", "QSYS");
-
-  if (rc != 0)
-    return rc;
-
-  /* initialize the QWCRSSTS returned info structure */
-  memset(rcvr, 0, sizeof(*rcvr));
-
-  /* initialize the QWCRSSTS error code structure */
-  memset(&errcode, 0, sizeof(errcode));
-  errcode.bytes_provided = sizeof(errcode);
-
-  /* initialize the array of argument pointers for the QWCRSSTS API */
-  qwcrssts_argv[0] = rcvr;
-  qwcrssts_argv[1] = &rcvrlen;
-  qwcrssts_argv[2] = &format;
-  qwcrssts_argv[3] = &reset_status;
-  qwcrssts_argv[4] = &errcode;
-  qwcrssts_argv[5] = NULL;
-
-  /* Call the IBM i QWCRSSTS API from PASE */
-  rc = _PGMCALL(&qwcrssts_pointer, (void**)&qwcrssts_argv, 0);
-
-  return rc;
-}
-
-
-uint64_t uv_get_free_memory(void) {
-  SSTS0200 rcvr;
-
-  if (get_ibmi_system_status(&rcvr))
-    return 0;
-
-  /* The amount of main storage, in kilobytes, in the system. */
-  uint64_t main_storage_size = rcvr.main_storage_size;
-
-  /* The current amount of storage in use for temporary objects.
-   * in millions (M) of bytes.
-   */
-  uint64_t current_unprotected_storage_used =
-    rcvr.current_unprotected_storage_used * 1024ULL;
-
-  uint64_t free_storage_size =
-    (main_storage_size - current_unprotected_storage_used) * 1024ULL;
-
-  return free_storage_size < 0 ? 0 : free_storage_size;
-}
-
-
-uint64_t uv_get_total_memory(void) {
-  SSTS0200 rcvr;
-
-  if (get_ibmi_system_status(&rcvr))
-    return 0;
-
-  return (uint64_t)rcvr.main_storage_size * 1024ULL;
-}
-
-
-uint64_t uv_get_constrained_memory(void) {
-  return 0;  /* Memory constraints are unknown. */
-}
-
-
-void uv_loadavg(double avg[3]) {
-  SSTS0200 rcvr;
-
-  if (get_ibmi_system_status(&rcvr)) {
-    avg[0] = avg[1] = avg[2] = 0;
-    return;
-  }
-
-  /* The average (in tenths) of the elapsed time during which the processing
-   * units were in use. For example, a value of 411 in binary would be 41.1%.
-   * This percentage could be greater than 100% for an uncapped partition.
-   */
-  double processing_unit_used_percent =
-    rcvr.percent_processing_unit_used / 1000.0;
-
-  avg[0] = avg[1] = avg[2] = processing_unit_used_percent;
-}
-
-
-int uv_resident_set_memory(size_t* rss) {
-  *rss = 0;
-  return 0;
-}
-
-
-int uv_uptime(double* uptime) {
-  return UV_ENOSYS;
-}
-
-
-int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
-  unsigned int numcpus, idx = 0;
-  uv_cpu_info_t* cpu_info;
-
-  *cpu_infos = NULL;
-  *count = 0;
-
-  numcpus = sysconf(_SC_NPROCESSORS_ONLN);
-
-  *cpu_infos = (uv_cpu_info_t*)uv__malloc(numcpus * sizeof(uv_cpu_info_t));
-  if (!*cpu_infos) {
-    return UV_ENOMEM;
-  }
-
-  cpu_info = *cpu_infos;
-  for (idx = 0; idx < numcpus; idx++) {
-    cpu_info->speed = 0;
-    cpu_info->model = uv__strdup("unknown");
-    cpu_info->cpu_times.user = 0;
-    cpu_info->cpu_times.sys = 0;
-    cpu_info->cpu_times.idle = 0;
-    cpu_info->cpu_times.irq = 0;
-    cpu_info->cpu_times.nice = 0;
-    cpu_info++;
-  }
-  *count = numcpus;
-
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/internal.h b/wpiutil/src/main/native/libuv/src/unix/internal.h
deleted file mode 100644
index 13ca2e6..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/internal.h
+++ /dev/null
@@ -1,329 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_UNIX_INTERNAL_H_
-#define UV_UNIX_INTERNAL_H_
-
-#include "uv-common.h"
-
-#include <assert.h>
-#include <limits.h> /* _POSIX_PATH_MAX, PATH_MAX */
-#include <stdlib.h> /* abort */
-#include <string.h> /* strrchr */
-#include <fcntl.h>  /* O_CLOEXEC, may be */
-#include <stdio.h>
-#include <errno.h>
-
-#if defined(__STRICT_ANSI__)
-# define inline __inline
-#endif
-
-#if defined(__linux__)
-# include "linux-syscalls.h"
-#endif /* __linux__ */
-
-#if defined(__MVS__)
-# include "os390-syscalls.h"
-#endif /* __MVS__ */
-
-#if defined(__sun)
-# include <sys/port.h>
-# include <port.h>
-#endif /* __sun */
-
-#if defined(_AIX)
-# define reqevents events
-# define rtnevents revents
-# include <sys/poll.h>
-#else
-# include <poll.h>
-#endif /* _AIX */
-
-#if defined(__APPLE__) && !TARGET_OS_IPHONE
-# include <AvailabilityMacros.h>
-#endif
-
-#if defined(_POSIX_PATH_MAX)
-# define UV__PATH_MAX _POSIX_PATH_MAX
-#elif defined(PATH_MAX)
-# define UV__PATH_MAX PATH_MAX
-#else
-# define UV__PATH_MAX 8192
-#endif
-
-#if defined(__ANDROID__)
-int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
-# ifdef pthread_sigmask
-# undef pthread_sigmask
-# endif
-# define pthread_sigmask(how, set, oldset) uv__pthread_sigmask(how, set, oldset)
-#endif
-
-#define ACCESS_ONCE(type, var)                                                \
-  (*(volatile type*) &(var))
-
-#define ROUND_UP(a, b)                                                        \
-  ((a) % (b) ? ((a) + (b)) - ((a) % (b)) : (a))
-
-#define UNREACHABLE()                                                         \
-  do {                                                                        \
-    assert(0 && "unreachable code");                                          \
-    abort();                                                                  \
-  }                                                                           \
-  while (0)
-
-#define SAVE_ERRNO(block)                                                     \
-  do {                                                                        \
-    int _saved_errno = errno;                                                 \
-    do { block; } while (0);                                                  \
-    errno = _saved_errno;                                                     \
-  }                                                                           \
-  while (0)
-
-/* The __clang__ and __INTEL_COMPILER checks are superfluous because they
- * define __GNUC__. They are here to convey to you, dear reader, that these
- * macros are enabled when compiling with clang or icc.
- */
-#if defined(__clang__) ||                                                     \
-    defined(__GNUC__) ||                                                      \
-    defined(__INTEL_COMPILER)
-# define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration
-# define UV_UNUSED(declaration)     __attribute__((unused)) declaration
-#else
-# define UV_DESTRUCTOR(declaration) declaration
-# define UV_UNUSED(declaration)     declaration
-#endif
-
-/* Leans on the fact that, on Linux, POLLRDHUP == EPOLLRDHUP. */
-#ifdef POLLRDHUP
-# define UV__POLLRDHUP POLLRDHUP
-#else
-# define UV__POLLRDHUP 0x2000
-#endif
-
-#ifdef POLLPRI
-# define UV__POLLPRI POLLPRI
-#else
-# define UV__POLLPRI 0
-#endif
-
-#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
-/*
- * It may be that we are just missing `__POSIX_VISIBLE >= 200809`.
- * Try using fixed value const and give up, if it doesn't work
- */
-# define O_CLOEXEC 0x00100000
-#endif
-
-typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
-
-/* loop flags */
-enum {
-  UV_LOOP_BLOCK_SIGPROF = 1
-};
-
-/* flags of excluding ifaddr */
-enum {
-  UV__EXCLUDE_IFPHYS,
-  UV__EXCLUDE_IFADDR
-};
-
-typedef enum {
-  UV_CLOCK_PRECISE = 0,  /* Use the highest resolution clock available. */
-  UV_CLOCK_FAST = 1      /* Use the fastest clock with <= 1ms granularity. */
-} uv_clocktype_t;
-
-struct uv__stream_queued_fds_s {
-  unsigned int size;
-  unsigned int offset;
-  int fds[1];
-};
-
-
-#if defined(_AIX) || \
-    defined(__APPLE__) || \
-    defined(__DragonFly__) || \
-    defined(__FreeBSD__) || \
-    defined(__FreeBSD_kernel__) || \
-    defined(__linux__) || \
-    defined(__OpenBSD__) || \
-    defined(__NetBSD__)
-#define uv__cloexec uv__cloexec_ioctl
-#define uv__nonblock uv__nonblock_ioctl
-#define UV__NONBLOCK_IS_IOCTL
-#else
-#define uv__cloexec uv__cloexec_fcntl
-#define uv__nonblock uv__nonblock_fcntl
-#define UV__NONBLOCK_IS_FCNTL
-#endif
-
-/* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute
- * when O_NDELAY is not equal to O_NONBLOCK.  Case in point: linux/sparc32
- * and linux/sparc64, where O_NDELAY is O_NONBLOCK + another bit.
- *
- * Libuv uses uv__nonblock_fcntl() directly sometimes so ensure that it
- * commutes with uv__nonblock().
- */
-#if defined(__linux__) && O_NDELAY != O_NONBLOCK
-#undef uv__nonblock
-#define uv__nonblock uv__nonblock_fcntl
-#undef UV__NONBLOCK_IS_IOCTL
-#define UV__NONBLOCK_IS_FCNTL
-#endif
-
-/* core */
-int uv__cloexec_ioctl(int fd, int set);
-int uv__cloexec_fcntl(int fd, int set);
-int uv__nonblock_ioctl(int fd, int set);
-int uv__nonblock_fcntl(int fd, int set);
-int uv__close(int fd); /* preserves errno */
-int uv__close_nocheckstdio(int fd);
-int uv__close_nocancel(int fd);
-int uv__socket(int domain, int type, int protocol);
-ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags);
-void uv__make_close_pending(uv_handle_t* handle);
-int uv__getiovmax(void);
-
-void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd);
-void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events);
-void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events);
-void uv__io_close(uv_loop_t* loop, uv__io_t* w);
-void uv__io_feed(uv_loop_t* loop, uv__io_t* w);
-int uv__io_active(const uv__io_t* w, unsigned int events);
-int uv__io_check_fd(uv_loop_t* loop, int fd);
-void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */
-int uv__io_fork(uv_loop_t* loop);
-int uv__fd_exists(uv_loop_t* loop, int fd);
-
-/* async */
-void uv__async_stop(uv_loop_t* loop);
-int uv__async_fork(uv_loop_t* loop);
-
-
-/* loop */
-void uv__run_idle(uv_loop_t* loop);
-void uv__run_check(uv_loop_t* loop);
-void uv__run_prepare(uv_loop_t* loop);
-
-/* stream */
-void uv__stream_init(uv_loop_t* loop, uv_stream_t* stream,
-    uv_handle_type type);
-int uv__stream_open(uv_stream_t*, int fd, int flags);
-void uv__stream_destroy(uv_stream_t* stream);
-#if defined(__APPLE__)
-int uv__stream_try_select(uv_stream_t* stream, int* fd);
-#endif /* defined(__APPLE__) */
-void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
-int uv__accept(int sockfd);
-int uv__dup2_cloexec(int oldfd, int newfd);
-int uv__open_cloexec(const char* path, int flags);
-
-/* tcp */
-int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
-int uv__tcp_nodelay(int fd, int on);
-int uv__tcp_keepalive(int fd, int on, unsigned int delay);
-
-/* pipe */
-int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
-
-/* signal */
-void uv__signal_close(uv_signal_t* handle);
-void uv__signal_global_once_init(void);
-void uv__signal_loop_cleanup(uv_loop_t* loop);
-int uv__signal_loop_fork(uv_loop_t* loop);
-
-/* platform specific */
-uint64_t uv__hrtime(uv_clocktype_t type);
-int uv__kqueue_init(uv_loop_t* loop);
-int uv__platform_loop_init(uv_loop_t* loop);
-void uv__platform_loop_delete(uv_loop_t* loop);
-void uv__platform_invalidate_fd(uv_loop_t* loop, int fd);
-
-/* various */
-void uv__async_close(uv_async_t* handle);
-void uv__check_close(uv_check_t* handle);
-void uv__fs_event_close(uv_fs_event_t* handle);
-void uv__idle_close(uv_idle_t* handle);
-void uv__pipe_close(uv_pipe_t* handle);
-void uv__poll_close(uv_poll_t* handle);
-void uv__prepare_close(uv_prepare_t* handle);
-void uv__process_close(uv_process_t* handle);
-void uv__stream_close(uv_stream_t* handle);
-void uv__tcp_close(uv_tcp_t* handle);
-void uv__udp_close(uv_udp_t* handle);
-void uv__udp_finish_close(uv_udp_t* handle);
-uv_handle_type uv__handle_type(int fd);
-FILE* uv__open_file(const char* path);
-int uv__getpwuid_r(uv_passwd_t* pwd);
-
-
-#if defined(__APPLE__)
-int uv___stream_fd(const uv_stream_t* handle);
-#define uv__stream_fd(handle) (uv___stream_fd((const uv_stream_t*) (handle)))
-#else
-#define uv__stream_fd(handle) ((handle)->io_watcher.fd)
-#endif /* defined(__APPLE__) */
-
-#ifdef UV__O_NONBLOCK
-# define UV__F_NONBLOCK UV__O_NONBLOCK
-#else
-# define UV__F_NONBLOCK 1
-#endif
-
-int uv__make_socketpair(int fds[2], int flags);
-int uv__make_pipe(int fds[2], int flags);
-
-#if defined(__APPLE__)
-
-int uv__fsevents_init(uv_fs_event_t* handle);
-int uv__fsevents_close(uv_fs_event_t* handle);
-void uv__fsevents_loop_delete(uv_loop_t* loop);
-
-#endif /* defined(__APPLE__) */
-
-UV_UNUSED(static void uv__update_time(uv_loop_t* loop)) {
-  /* Use a fast time source if available.  We only need millisecond precision.
-   */
-  loop->time = uv__hrtime(UV_CLOCK_FAST) / 1000000;
-}
-
-UV_UNUSED(static const char* uv__basename_r(const char* path)) {
-  const char* s;
-
-  s = strrchr(path, '/');
-  if (s == NULL)
-    return (char*) path;
-
-  return s + 1;
-}
-
-#if defined(__linux__)
-int uv__inotify_fork(uv_loop_t* loop, void* old_watchers);
-#endif
-
-typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*);
-
-int uv__getsockpeername(const uv_handle_t* handle,
-                        uv__peersockfunc func,
-                        struct sockaddr* name,
-                        int* namelen);
-
-#endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/unix/kqueue.cpp b/wpiutil/src/main/native/libuv/src/unix/kqueue.cpp
deleted file mode 100644
index 4c4268b..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/kqueue.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <sys/sysctl.h>
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-
-/*
- * Required on
- * - Until at least FreeBSD 11.0
- * - Older versions of Mac OS X
- *
- * http://www.boost.org/doc/libs/1_61_0/boost/asio/detail/kqueue_reactor.hpp
- */
-#ifndef EV_OOBAND
-#define EV_OOBAND  EV_FLAG1
-#endif
-
-static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags);
-
-
-int uv__kqueue_init(uv_loop_t* loop) {
-  loop->backend_fd = kqueue();
-  if (loop->backend_fd == -1)
-    return UV__ERR(errno);
-
-  uv__cloexec(loop->backend_fd, 1);
-
-  return 0;
-}
-
-
-#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
-static int uv__has_forked_with_cfrunloop;
-#endif
-
-int uv__io_fork(uv_loop_t* loop) {
-  int err;
-  loop->backend_fd = -1;
-  err = uv__kqueue_init(loop);
-  if (err)
-    return err;
-
-#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
-  if (loop->cf_state != NULL) {
-    /* We cannot start another CFRunloop and/or thread in the child
-       process; CF aborts if you try or if you try to touch the thread
-       at all to kill it. So the best we can do is ignore it from now
-       on. This means we can't watch directories in the same way
-       anymore (like other BSDs). It also means we cannot properly
-       clean up the allocated resources; calling
-       uv__fsevents_loop_delete from uv_loop_close will crash the
-       process. So we sidestep the issue by pretending like we never
-       started it in the first place.
-    */
-    uv__has_forked_with_cfrunloop = 1;
-    uv__free(loop->cf_state);
-    loop->cf_state = NULL;
-  }
-#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
-  return err;
-}
-
-
-int uv__io_check_fd(uv_loop_t* loop, int fd) {
-  struct kevent ev;
-  int rc;
-
-  rc = 0;
-  EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
-  if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
-    rc = UV__ERR(errno);
-
-  EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
-  if (rc == 0)
-    if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
-      abort();
-
-  return rc;
-}
-
-
-void uv__io_poll(uv_loop_t* loop, int timeout) {
-  struct kevent events[1024];
-  struct kevent* ev;
-  struct timespec spec;
-  unsigned int nevents;
-  unsigned int revents;
-  QUEUE* q;
-  uv__io_t* w;
-  sigset_t* pset;
-  sigset_t set;
-  uint64_t base;
-  uint64_t diff;
-  int have_signals;
-  int filter;
-  int fflags;
-  int count;
-  int nfds;
-  int fd;
-  int op;
-  int i;
-
-  if (loop->nfds == 0) {
-    assert(QUEUE_EMPTY(&loop->watcher_queue));
-    return;
-  }
-
-  nevents = 0;
-
-  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
-    q = QUEUE_HEAD(&loop->watcher_queue);
-    QUEUE_REMOVE(q);
-    QUEUE_INIT(q);
-
-    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
-    assert(w->pevents != 0);
-    assert(w->fd >= 0);
-    assert(w->fd < (int) loop->nwatchers);
-
-    if ((w->events & POLLIN) == 0 && (w->pevents & POLLIN) != 0) {
-      filter = EVFILT_READ;
-      fflags = 0;
-      op = EV_ADD;
-
-      if (w->cb == uv__fs_event) {
-        filter = EVFILT_VNODE;
-        fflags = NOTE_ATTRIB | NOTE_WRITE  | NOTE_RENAME
-               | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE;
-        op = EV_ADD | EV_ONESHOT; /* Stop the event from firing repeatedly. */
-      }
-
-      EV_SET(events + nevents, w->fd, filter, op, fflags, 0, 0);
-
-      if (++nevents == ARRAY_SIZE(events)) {
-        if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
-          abort();
-        nevents = 0;
-      }
-    }
-
-    if ((w->events & POLLOUT) == 0 && (w->pevents & POLLOUT) != 0) {
-      EV_SET(events + nevents, w->fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
-
-      if (++nevents == ARRAY_SIZE(events)) {
-        if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
-          abort();
-        nevents = 0;
-      }
-    }
-
-   if ((w->events & UV__POLLPRI) == 0 && (w->pevents & UV__POLLPRI) != 0) {
-      EV_SET(events + nevents, w->fd, EV_OOBAND, EV_ADD, 0, 0, 0);
-
-      if (++nevents == ARRAY_SIZE(events)) {
-        if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
-          abort();
-        nevents = 0;
-      }
-    }
-
-    w->events = w->pevents;
-  }
-
-  pset = NULL;
-  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
-    pset = &set;
-    sigemptyset(pset);
-    sigaddset(pset, SIGPROF);
-  }
-
-  assert(timeout >= -1);
-  base = loop->time;
-  count = 48; /* Benchmarks suggest this gives the best throughput. */
-
-  for (;; nevents = 0) {
-    if (timeout != -1) {
-      spec.tv_sec = timeout / 1000;
-      spec.tv_nsec = (timeout % 1000) * 1000000;
-    }
-
-    if (pset != NULL)
-      pthread_sigmask(SIG_BLOCK, pset, NULL);
-
-    nfds = kevent(loop->backend_fd,
-                  events,
-                  nevents,
-                  events,
-                  ARRAY_SIZE(events),
-                  timeout == -1 ? NULL : &spec);
-
-    if (pset != NULL)
-      pthread_sigmask(SIG_UNBLOCK, pset, NULL);
-
-    /* Update loop->time unconditionally. It's tempting to skip the update when
-     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
-     * operating system didn't reschedule our process while in the syscall.
-     */
-    SAVE_ERRNO(uv__update_time(loop));
-
-    if (nfds == 0) {
-      assert(timeout != -1);
-      return;
-    }
-
-    if (nfds == -1) {
-      if (errno != EINTR)
-        abort();
-
-      if (timeout == 0)
-        return;
-
-      if (timeout == -1)
-        continue;
-
-      /* Interrupted by a signal. Update timeout and poll again. */
-      goto update_timeout;
-    }
-
-    have_signals = 0;
-    nevents = 0;
-
-    assert(loop->watchers != NULL);
-    loop->watchers[loop->nwatchers] = (uv__io_t*) events;
-    loop->watchers[loop->nwatchers + 1] = (uv__io_t*) (uintptr_t) nfds;
-    for (i = 0; i < nfds; i++) {
-      ev = events + i;
-      fd = ev->ident;
-      /* Skip invalidated events, see uv__platform_invalidate_fd */
-      if (fd == -1)
-        continue;
-      w = (uv__io_t*)loop->watchers[fd];
-
-      if (w == NULL) {
-        /* File descriptor that we've stopped watching, disarm it.
-         * TODO: batch up. */
-        struct kevent events[1];
-
-        EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
-        if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
-          if (errno != EBADF && errno != ENOENT)
-            abort();
-
-        continue;
-      }
-
-      if (ev->filter == EVFILT_VNODE) {
-        assert(w->events == POLLIN);
-        assert(w->pevents == POLLIN);
-        w->cb(loop, w, ev->fflags); /* XXX always uv__fs_event() */
-        nevents++;
-        continue;
-      }
-
-      revents = 0;
-
-      if (ev->filter == EVFILT_READ) {
-        if (w->pevents & POLLIN) {
-          revents |= POLLIN;
-          w->rcount = ev->data;
-        } else {
-          /* TODO batch up */
-          struct kevent events[1];
-          EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
-          if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
-            if (errno != ENOENT)
-              abort();
-        }
-      }
-
-      if (ev->filter == EV_OOBAND) {
-        if (w->pevents & UV__POLLPRI) {
-          revents |= UV__POLLPRI;
-          w->rcount = ev->data;
-        } else {
-          /* TODO batch up */
-          struct kevent events[1];
-          EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
-          if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
-            if (errno != ENOENT)
-              abort();
-        }
-      }
-
-      if (ev->filter == EVFILT_WRITE) {
-        if (w->pevents & POLLOUT) {
-          revents |= POLLOUT;
-          w->wcount = ev->data;
-        } else {
-          /* TODO batch up */
-          struct kevent events[1];
-          EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
-          if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
-            if (errno != ENOENT)
-              abort();
-        }
-      }
-
-      if (ev->flags & EV_ERROR)
-        revents |= POLLERR;
-
-      if ((ev->flags & EV_EOF) && (w->pevents & UV__POLLRDHUP))
-        revents |= UV__POLLRDHUP;
-
-      if (revents == 0)
-        continue;
-
-      /* Run signal watchers last.  This also affects child process watchers
-       * because those are implemented in terms of signal watchers.
-       */
-      if (w == &loop->signal_io_watcher)
-        have_signals = 1;
-      else
-        w->cb(loop, w, revents);
-
-      nevents++;
-    }
-
-    if (have_signals != 0)
-      loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
-
-    loop->watchers[loop->nwatchers] = NULL;
-    loop->watchers[loop->nwatchers + 1] = NULL;
-
-    if (have_signals != 0)
-      return;  /* Event loop should cycle now so don't poll again. */
-
-    if (nevents != 0) {
-      if (nfds == ARRAY_SIZE(events) && --count != 0) {
-        /* Poll for more events but don't block this time. */
-        timeout = 0;
-        continue;
-      }
-      return;
-    }
-
-    if (timeout == 0)
-      return;
-
-    if (timeout == -1)
-      continue;
-
-update_timeout:
-    assert(timeout > 0);
-
-    diff = loop->time - base;
-    if (diff >= (uint64_t) timeout)
-      return;
-
-    timeout -= diff;
-  }
-}
-
-
-void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
-  struct kevent* events;
-  uintptr_t i;
-  uintptr_t nfds;
-
-  assert(loop->watchers != NULL);
-  assert(fd >= 0);
-
-  events = (struct kevent*) loop->watchers[loop->nwatchers];
-  nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
-  if (events == NULL)
-    return;
-
-  /* Invalidate events with same file descriptor */
-  for (i = 0; i < nfds; i++)
-    if ((int) events[i].ident == fd)
-      events[i].ident = -1;
-}
-
-
-static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) {
-  uv_fs_event_t* handle;
-  struct kevent ev;
-  int events;
-  const char* path;
-#if defined(F_GETPATH)
-  /* MAXPATHLEN == PATH_MAX but the former is what XNU calls it internally. */
-  char pathbuf[MAXPATHLEN];
-#endif
-
-  handle = container_of(w, uv_fs_event_t, event_watcher);
-
-  if (fflags & (NOTE_ATTRIB | NOTE_EXTEND))
-    events = UV_CHANGE;
-  else
-    events = UV_RENAME;
-
-  path = NULL;
-#if defined(F_GETPATH)
-  /* Also works when the file has been unlinked from the file system. Passing
-   * in the path when the file has been deleted is arguably a little strange
-   * but it's consistent with what the inotify backend does.
-   */
-  if (fcntl(handle->event_watcher.fd, F_GETPATH, pathbuf) == 0)
-    path = uv__basename_r(pathbuf);
-#endif
-  handle->cb(handle, path, events, 0);
-
-  if (handle->event_watcher.fd == -1)
-    return;
-
-  /* Watcher operates in one-shot mode, re-arm it. */
-  fflags = NOTE_ATTRIB | NOTE_WRITE  | NOTE_RENAME
-         | NOTE_DELETE | NOTE_EXTEND | NOTE_REVOKE;
-
-  EV_SET(&ev, w->fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, fflags, 0, 0);
-
-  if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
-    abort();
-}
-
-
-int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
-  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
-  return 0;
-}
-
-
-int uv_fs_event_start(uv_fs_event_t* handle,
-                      uv_fs_event_cb cb,
-                      const char* path,
-                      unsigned int flags) {
-  int fd;
-
-  if (uv__is_active(handle))
-    return UV_EINVAL;
-
-#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
-  /* Nullify field to perform checks later */
-  handle->cf_cb = NULL;
-  handle->realpath = NULL;
-  handle->realpath_len = 0;
-  handle->cf_flags = flags;
-
-  if (!uv__has_forked_with_cfrunloop) {
-    int r;
-    /* The fallback fd is not used */
-    handle->event_watcher.fd = -1;
-    handle->path = uv__strdup(path);
-    if (handle->path == NULL)
-      return UV_ENOMEM;
-    handle->cb = cb;
-    r = uv__fsevents_init(handle);
-    if (r == 0) {
-      uv__handle_start(handle);
-    } else {
-      uv__free(handle->path);
-      handle->path = NULL;
-    }
-    return r;
-  }
-#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
-
-  /* TODO open asynchronously - but how do we report back errors? */
-  fd = open(path, O_RDONLY);
-  if (fd == -1)
-    return UV__ERR(errno);
-
-  handle->path = uv__strdup(path);
-  if (handle->path == NULL) {
-    uv__close_nocheckstdio(fd);
-    return UV_ENOMEM;
-  }
-
-  handle->cb = cb;
-  uv__handle_start(handle);
-  uv__io_init(&handle->event_watcher, uv__fs_event, fd);
-  uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
-
-  return 0;
-}
-
-
-int uv_fs_event_stop(uv_fs_event_t* handle) {
-  int r;
-  r = 0;
-
-  if (!uv__is_active(handle))
-    return 0;
-
-  uv__handle_stop(handle);
-
-#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
-  if (!uv__has_forked_with_cfrunloop)
-    r = uv__fsevents_close(handle);
-#endif
-
-  if (handle->event_watcher.fd != -1) {
-    uv__io_close(handle->loop, &handle->event_watcher);
-    uv__close(handle->event_watcher.fd);
-    handle->event_watcher.fd = -1;
-  }
-
-  uv__free(handle->path);
-  handle->path = NULL;
-
-  return r;
-}
-
-
-void uv__fs_event_close(uv_fs_event_t* handle) {
-  uv_fs_event_stop(handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/linux-core.cpp b/wpiutil/src/main/native/libuv/src/unix/linux-core.cpp
deleted file mode 100644
index 8a26782..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/linux-core.cpp
+++ /dev/null
@@ -1,1062 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/* We lean on the fact that POLL{IN,OUT,ERR,HUP} correspond with their
- * EPOLL* counterparts.  We use the POLL* variants in this file because that
- * is what libuv uses elsewhere.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <net/if.h>
-#include <sys/epoll.h>
-#include <sys/param.h>
-#include <sys/prctl.h>
-#include <sys/sysinfo.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-
-#define HAVE_IFADDRS_H 1
-
-#ifdef __UCLIBC__
-# if __UCLIBC_MAJOR__ < 0 && __UCLIBC_MINOR__ < 9 && __UCLIBC_SUBLEVEL__ < 32
-#  undef HAVE_IFADDRS_H
-# endif
-#endif
-
-#ifdef HAVE_IFADDRS_H
-# if defined(__ANDROID__)
-#  include "uv/android-ifaddrs.h"
-# else
-#  include <ifaddrs.h>
-# endif
-# include <sys/socket.h>
-# include <net/ethernet.h>
-# include <netpacket/packet.h>
-#endif /* HAVE_IFADDRS_H */
-
-/* Available from 2.6.32 onwards. */
-#ifndef CLOCK_MONOTONIC_COARSE
-# define CLOCK_MONOTONIC_COARSE 6
-#endif
-
-#ifdef __FRC_ROBORIO__
-#include "wpi/timestamp.h"
-#endif
-
-/* This is rather annoying: CLOCK_BOOTTIME lives in <linux/time.h> but we can't
- * include that file because it conflicts with <time.h>. We'll just have to
- * define it ourselves.
- */
-#ifndef CLOCK_BOOTTIME
-# define CLOCK_BOOTTIME 7
-#endif
-
-static int read_models(unsigned int numcpus, uv_cpu_info_t* ci);
-static int read_times(FILE* statfile_fp,
-                      unsigned int numcpus,
-                      uv_cpu_info_t* ci);
-static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
-static uint64_t read_cpufreq(unsigned int cpunum);
-
-
-int uv__platform_loop_init(uv_loop_t* loop) {
-  int fd;
-
-  /* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21,
-   * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all
-   * architectures, we just use that instead.
-   */
-  fd = epoll_create1(O_CLOEXEC);
-
-  /* epoll_create1() can fail either because it's not implemented (old kernel)
-   * or because it doesn't understand the O_CLOEXEC flag.
-   */
-  if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) {
-    fd = epoll_create(256);
-
-    if (fd != -1)
-      uv__cloexec(fd, 1);
-  }
-
-  loop->backend_fd = fd;
-  loop->inotify_fd = -1;
-  loop->inotify_watchers = NULL;
-
-  if (fd == -1)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-int uv__io_fork(uv_loop_t* loop) {
-  int err;
-  void* old_watchers;
-
-  old_watchers = loop->inotify_watchers;
-
-  uv__close(loop->backend_fd);
-  loop->backend_fd = -1;
-  uv__platform_loop_delete(loop);
-
-  err = uv__platform_loop_init(loop);
-  if (err)
-    return err;
-
-  return uv__inotify_fork(loop, old_watchers);
-}
-
-
-void uv__platform_loop_delete(uv_loop_t* loop) {
-  if (loop->inotify_fd == -1) return;
-  uv__io_stop(loop, &loop->inotify_read_watcher, POLLIN);
-  uv__close(loop->inotify_fd);
-  loop->inotify_fd = -1;
-}
-
-
-void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
-  struct epoll_event* events;
-  struct epoll_event dummy;
-  uintptr_t i;
-  uintptr_t nfds;
-
-  assert(loop->watchers != NULL);
-  assert(fd >= 0);
-
-  events = (struct epoll_event*) loop->watchers[loop->nwatchers];
-  nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
-  if (events != NULL)
-    /* Invalidate events with same file descriptor */
-    for (i = 0; i < nfds; i++)
-      if (events[i].data.fd == fd)
-        events[i].data.fd = -1;
-
-  /* Remove the file descriptor from the epoll.
-   * This avoids a problem where the same file description remains open
-   * in another process, causing repeated junk epoll events.
-   *
-   * We pass in a dummy epoll_event, to work around a bug in old kernels.
-   */
-  if (loop->backend_fd >= 0) {
-    /* Work around a bug in kernels 3.10 to 3.19 where passing a struct that
-     * has the EPOLLWAKEUP flag set generates spurious audit syslog warnings.
-     */
-    memset(&dummy, 0, sizeof(dummy));
-    epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &dummy);
-  }
-}
-
-
-int uv__io_check_fd(uv_loop_t* loop, int fd) {
-  struct epoll_event e;
-  int rc;
-
-  memset(&e, 0, sizeof(e));
-  e.events = POLLIN;
-  e.data.fd = -1;
-
-  rc = 0;
-  if (epoll_ctl(loop->backend_fd, EPOLL_CTL_ADD, fd, &e))
-    if (errno != EEXIST)
-      rc = UV__ERR(errno);
-
-  if (rc == 0)
-    if (epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, &e))
-      abort();
-
-  return rc;
-}
-
-
-void uv__io_poll(uv_loop_t* loop, int timeout) {
-  /* A bug in kernels < 2.6.37 makes timeouts larger than ~30 minutes
-   * effectively infinite on 32 bits architectures.  To avoid blocking
-   * indefinitely, we cap the timeout and poll again if necessary.
-   *
-   * Note that "30 minutes" is a simplification because it depends on
-   * the value of CONFIG_HZ.  The magic constant assumes CONFIG_HZ=1200,
-   * that being the largest value I have seen in the wild (and only once.)
-   */
-  static const int max_safe_timeout = 1789569;
-  struct epoll_event events[1024];
-  struct epoll_event* pe;
-  struct epoll_event e;
-  int real_timeout;
-  QUEUE* q;
-  uv__io_t* w;
-  sigset_t sigset;
-  sigset_t* psigset;
-  uint64_t base;
-  int have_signals;
-  int nevents;
-  int count;
-  int nfds;
-  int fd;
-  int op;
-  int i;
-
-  if (loop->nfds == 0) {
-    assert(QUEUE_EMPTY(&loop->watcher_queue));
-    return;
-  }
-
-  memset(&e, 0, sizeof(e));
-
-  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
-    q = QUEUE_HEAD(&loop->watcher_queue);
-    QUEUE_REMOVE(q);
-    QUEUE_INIT(q);
-
-    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
-    assert(w->pevents != 0);
-    assert(w->fd >= 0);
-    assert(w->fd < (int) loop->nwatchers);
-
-    e.events = w->pevents;
-    e.data.fd = w->fd;
-
-    if (w->events == 0)
-      op = EPOLL_CTL_ADD;
-    else
-      op = EPOLL_CTL_MOD;
-
-    /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
-     * events, skip the syscall and squelch the events after epoll_wait().
-     */
-    if (epoll_ctl(loop->backend_fd, op, w->fd, &e)) {
-      if (errno != EEXIST)
-        abort();
-
-      assert(op == EPOLL_CTL_ADD);
-
-      /* We've reactivated a file descriptor that's been watched before. */
-      if (epoll_ctl(loop->backend_fd, EPOLL_CTL_MOD, w->fd, &e))
-        abort();
-    }
-
-    w->events = w->pevents;
-  }
-
-  psigset = NULL;
-  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
-    sigemptyset(&sigset);
-    sigaddset(&sigset, SIGPROF);
-    psigset = &sigset;
-  }
-
-  assert(timeout >= -1);
-  base = loop->time;
-  count = 48; /* Benchmarks suggest this gives the best throughput. */
-  real_timeout = timeout;
-
-  for (;;) {
-    /* See the comment for max_safe_timeout for an explanation of why
-     * this is necessary.  Executive summary: kernel bug workaround.
-     */
-    if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
-      timeout = max_safe_timeout;
-
-    nfds = epoll_pwait(loop->backend_fd,
-                       events,
-                       ARRAY_SIZE(events),
-                       timeout,
-                       psigset);
-
-    /* Update loop->time unconditionally. It's tempting to skip the update when
-     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
-     * operating system didn't reschedule our process while in the syscall.
-     */
-    SAVE_ERRNO(uv__update_time(loop));
-
-    if (nfds == 0) {
-      assert(timeout != -1);
-
-      if (timeout == 0)
-        return;
-
-      /* We may have been inside the system call for longer than |timeout|
-       * milliseconds so we need to update the timestamp to avoid drift.
-       */
-      goto update_timeout;
-    }
-
-    if (nfds == -1) {
-      if (errno != EINTR)
-        abort();
-
-      if (timeout == -1)
-        continue;
-
-      if (timeout == 0)
-        return;
-
-      /* Interrupted by a signal. Update timeout and poll again. */
-      goto update_timeout;
-    }
-
-    have_signals = 0;
-    nevents = 0;
-
-    assert(loop->watchers != NULL);
-    loop->watchers[loop->nwatchers] = events;
-    loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
-    for (i = 0; i < nfds; i++) {
-      pe = events + i;
-      fd = pe->data.fd;
-
-      /* Skip invalidated events, see uv__platform_invalidate_fd */
-      if (fd == -1)
-        continue;
-
-      assert(fd >= 0);
-      assert((unsigned) fd < loop->nwatchers);
-
-      w = (uv__io_t*)loop->watchers[fd];
-
-      if (w == NULL) {
-        /* File descriptor that we've stopped watching, disarm it.
-         *
-         * Ignore all errors because we may be racing with another thread
-         * when the file descriptor is closed.
-         */
-        epoll_ctl(loop->backend_fd, EPOLL_CTL_DEL, fd, pe);
-        continue;
-      }
-
-      /* Give users only events they're interested in. Prevents spurious
-       * callbacks when previous callback invocation in this loop has stopped
-       * the current watcher. Also, filters out events that users has not
-       * requested us to watch.
-       */
-      pe->events &= w->pevents | POLLERR | POLLHUP;
-
-      /* Work around an epoll quirk where it sometimes reports just the
-       * EPOLLERR or EPOLLHUP event.  In order to force the event loop to
-       * move forward, we merge in the read/write events that the watcher
-       * is interested in; uv__read() and uv__write() will then deal with
-       * the error or hangup in the usual fashion.
-       *
-       * Note to self: happens when epoll reports EPOLLIN|EPOLLHUP, the user
-       * reads the available data, calls uv_read_stop(), then sometime later
-       * calls uv_read_start() again.  By then, libuv has forgotten about the
-       * hangup and the kernel won't report EPOLLIN again because there's
-       * nothing left to read.  If anything, libuv is to blame here.  The
-       * current hack is just a quick bandaid; to properly fix it, libuv
-       * needs to remember the error/hangup event.  We should get that for
-       * free when we switch over to edge-triggered I/O.
-       */
-      if (pe->events == POLLERR || pe->events == POLLHUP)
-        pe->events |=
-          w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
-
-      if (pe->events != 0) {
-        /* Run signal watchers last.  This also affects child process watchers
-         * because those are implemented in terms of signal watchers.
-         */
-        if (w == &loop->signal_io_watcher)
-          have_signals = 1;
-        else
-          w->cb(loop, w, pe->events);
-
-        nevents++;
-      }
-    }
-
-    if (have_signals != 0)
-      loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
-
-    loop->watchers[loop->nwatchers] = NULL;
-    loop->watchers[loop->nwatchers + 1] = NULL;
-
-    if (have_signals != 0)
-      return;  /* Event loop should cycle now so don't poll again. */
-
-    if (nevents != 0) {
-      if (nfds == ARRAY_SIZE(events) && --count != 0) {
-        /* Poll for more events but don't block this time. */
-        timeout = 0;
-        continue;
-      }
-      return;
-    }
-
-    if (timeout == 0)
-      return;
-
-    if (timeout == -1)
-      continue;
-
-update_timeout:
-    assert(timeout > 0);
-
-    real_timeout -= (loop->time - base);
-    if (real_timeout <= 0)
-      return;
-
-    timeout = real_timeout;
-  }
-}
-
-
-uint64_t uv__hrtime(uv_clocktype_t type) {
-#ifdef __FRC_ROBORIO__
-  return wpi::Now() * 1000u;
-#else
-  static clock_t fast_clock_id = -1;
-  struct timespec t;
-  clock_t clock_id;
-
-  /* Prefer CLOCK_MONOTONIC_COARSE if available but only when it has
-   * millisecond granularity or better.  CLOCK_MONOTONIC_COARSE is
-   * serviced entirely from the vDSO, whereas CLOCK_MONOTONIC may
-   * decide to make a costly system call.
-   */
-  /* TODO(bnoordhuis) Use CLOCK_MONOTONIC_COARSE for UV_CLOCK_PRECISE
-   * when it has microsecond granularity or better (unlikely).
-   */
-  if (type == UV_CLOCK_FAST && fast_clock_id == -1) {
-    if (clock_getres(CLOCK_MONOTONIC_COARSE, &t) == 0 &&
-        t.tv_nsec <= 1 * 1000 * 1000) {
-      fast_clock_id = CLOCK_MONOTONIC_COARSE;
-    } else {
-      fast_clock_id = CLOCK_MONOTONIC;
-    }
-  }
-
-  clock_id = CLOCK_MONOTONIC;
-  if (type == UV_CLOCK_FAST)
-    clock_id = fast_clock_id;
-
-  if (clock_gettime(clock_id, &t))
-    return 0;  /* Not really possible. */
-
-  return t.tv_sec * (uint64_t) 1e9 + t.tv_nsec;
-#endif
-}
-
-
-int uv_resident_set_memory(size_t* rss) {
-  char buf[1024];
-  const char* s;
-  ssize_t n;
-  long val;
-  int fd;
-  int i;
-
-  do
-    fd = open("/proc/self/stat", O_RDONLY);
-  while (fd == -1 && errno == EINTR);
-
-  if (fd == -1)
-    return UV__ERR(errno);
-
-  do
-    n = read(fd, buf, sizeof(buf) - 1);
-  while (n == -1 && errno == EINTR);
-
-  uv__close(fd);
-  if (n == -1)
-    return UV__ERR(errno);
-  buf[n] = '\0';
-
-  s = strchr(buf, ' ');
-  if (s == NULL)
-    goto err;
-
-  s += 1;
-  if (*s != '(')
-    goto err;
-
-  s = strchr(s, ')');
-  if (s == NULL)
-    goto err;
-
-  for (i = 1; i <= 22; i++) {
-    s = strchr(s + 1, ' ');
-    if (s == NULL)
-      goto err;
-  }
-
-  errno = 0;
-  val = strtol(s, NULL, 10);
-  if (errno != 0)
-    goto err;
-  if (val < 0)
-    goto err;
-
-  *rss = val * getpagesize();
-  return 0;
-
-err:
-  return UV_EINVAL;
-}
-
-
-int uv_uptime(double* uptime) {
-  static volatile int no_clock_boottime;
-  struct timespec now;
-  int r;
-
-  /* Try CLOCK_BOOTTIME first, fall back to CLOCK_MONOTONIC if not available
-   * (pre-2.6.39 kernels). CLOCK_MONOTONIC doesn't increase when the system
-   * is suspended.
-   */
-  if (no_clock_boottime) {
-    retry: r = clock_gettime(CLOCK_MONOTONIC, &now);
-  }
-  else if ((r = clock_gettime(CLOCK_BOOTTIME, &now)) && errno == EINVAL) {
-    no_clock_boottime = 1;
-    goto retry;
-  }
-
-  if (r)
-    return UV__ERR(errno);
-
-  *uptime = now.tv_sec;
-  return 0;
-}
-
-
-static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
-  unsigned int num;
-  char buf[1024];
-
-  if (!fgets(buf, sizeof(buf), statfile_fp))
-    return UV_EIO;
-
-  num = 0;
-  while (fgets(buf, sizeof(buf), statfile_fp)) {
-    if (strncmp(buf, "cpu", 3))
-      break;
-    num++;
-  }
-
-  if (num == 0)
-    return UV_EIO;
-
-  *numcpus = num;
-  return 0;
-}
-
-
-int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
-  unsigned int numcpus;
-  uv_cpu_info_t* ci;
-  int err;
-  FILE* statfile_fp;
-
-  *cpu_infos = NULL;
-  *count = 0;
-
-  statfile_fp = uv__open_file("/proc/stat");
-  if (statfile_fp == NULL)
-    return UV__ERR(errno);
-
-  err = uv__cpu_num(statfile_fp, &numcpus);
-  if (err < 0)
-    goto out;
-
-  err = UV_ENOMEM;
-  ci = (uv_cpu_info_t*)uv__calloc(numcpus, sizeof(*ci));
-  if (ci == NULL)
-    goto out;
-
-  err = read_models(numcpus, ci);
-  if (err == 0)
-    err = read_times(statfile_fp, numcpus, ci);
-
-  if (err) {
-    uv_free_cpu_info(ci, numcpus);
-    goto out;
-  }
-
-  /* read_models() on x86 also reads the CPU speed from /proc/cpuinfo.
-   * We don't check for errors here. Worst case, the field is left zero.
-   */
-  if (ci[0].speed == 0)
-    read_speeds(numcpus, ci);
-
-  *cpu_infos = ci;
-  *count = numcpus;
-  err = 0;
-
-out:
-
-  if (fclose(statfile_fp))
-    if (errno != EINTR && errno != EINPROGRESS)
-      abort();
-
-  return err;
-}
-
-
-static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci) {
-  unsigned int num;
-
-  for (num = 0; num < numcpus; num++)
-    ci[num].speed = read_cpufreq(num) / 1000;
-}
-
-
-/* Also reads the CPU frequency on x86. The other architectures only have
- * a BogoMIPS field, which may not be very accurate.
- *
- * Note: Simply returns on error, uv_cpu_info() takes care of the cleanup.
- */
-static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
-  static const char model_marker[] = "model name\t: ";
-  static const char speed_marker[] = "cpu MHz\t\t: ";
-  const char* inferred_model;
-  unsigned int model_idx;
-  unsigned int speed_idx;
-  char buf[1024];
-  char* model;
-  FILE* fp;
-
-  /* Most are unused on non-ARM, non-MIPS and non-x86 architectures. */
-  (void) &model_marker;
-  (void) &speed_marker;
-  (void) &speed_idx;
-  (void) &model;
-  (void) &buf;
-  (void) &fp;
-
-  model_idx = 0;
-  speed_idx = 0;
-
-#if defined(__arm__) || \
-    defined(__i386__) || \
-    defined(__mips__) || \
-    defined(__x86_64__)
-  fp = uv__open_file("/proc/cpuinfo");
-  if (fp == NULL)
-    return UV__ERR(errno);
-
-  while (fgets(buf, sizeof(buf), fp)) {
-    if (model_idx < numcpus) {
-      if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
-        model = buf + sizeof(model_marker) - 1;
-        model = uv__strndup(model, strlen(model) - 1);  /* Strip newline. */
-        if (model == NULL) {
-          fclose(fp);
-          return UV_ENOMEM;
-        }
-        ci[model_idx++].model = model;
-        continue;
-      }
-    }
-#if defined(__arm__) || defined(__mips__)
-    if (model_idx < numcpus) {
-#if defined(__arm__)
-      /* Fallback for pre-3.8 kernels. */
-      static const char model_marker[] = "Processor\t: ";
-#else	/* defined(__mips__) */
-      static const char model_marker[] = "cpu model\t\t: ";
-#endif
-      if (strncmp(buf, model_marker, sizeof(model_marker) - 1) == 0) {
-        model = buf + sizeof(model_marker) - 1;
-        model = uv__strndup(model, strlen(model) - 1);  /* Strip newline. */
-        if (model == NULL) {
-          fclose(fp);
-          return UV_ENOMEM;
-        }
-        ci[model_idx++].model = model;
-        continue;
-      }
-    }
-#else  /* !__arm__ && !__mips__ */
-    if (speed_idx < numcpus) {
-      if (strncmp(buf, speed_marker, sizeof(speed_marker) - 1) == 0) {
-        ci[speed_idx++].speed = atoi(buf + sizeof(speed_marker) - 1);
-        continue;
-      }
-    }
-#endif  /* __arm__ || __mips__ */
-  }
-
-  fclose(fp);
-#endif  /* __arm__ || __i386__ || __mips__ || __x86_64__ */
-
-  /* Now we want to make sure that all the models contain *something* because
-   * it's not safe to leave them as null. Copy the last entry unless there
-   * isn't one, in that case we simply put "unknown" into everything.
-   */
-  inferred_model = "unknown";
-  if (model_idx > 0)
-    inferred_model = ci[model_idx - 1].model;
-
-  while (model_idx < numcpus) {
-    model = uv__strndup(inferred_model, strlen(inferred_model));
-    if (model == NULL)
-      return UV_ENOMEM;
-    ci[model_idx++].model = model;
-  }
-
-  return 0;
-}
-
-
-static int read_times(FILE* statfile_fp,
-                      unsigned int numcpus,
-                      uv_cpu_info_t* ci) {
-  struct uv_cpu_times_s ts;
-  uint64_t clock_ticks;
-  uint64_t user;
-  uint64_t nice;
-  uint64_t sys;
-  uint64_t idle;
-  uint64_t dummy;
-  uint64_t irq;
-  uint64_t num;
-  uint64_t len;
-  char buf[1024];
-
-  clock_ticks = sysconf(_SC_CLK_TCK);
-  assert(clock_ticks != (uint64_t) -1);
-  assert(clock_ticks != 0);
-
-  rewind(statfile_fp);
-
-  if (!fgets(buf, sizeof(buf), statfile_fp))
-    abort();
-
-  num = 0;
-
-  while (fgets(buf, sizeof(buf), statfile_fp)) {
-    if (num >= numcpus)
-      break;
-
-    if (strncmp(buf, "cpu", 3))
-      break;
-
-    /* skip "cpu<num> " marker */
-    {
-      unsigned int n;
-      int r = sscanf(buf, "cpu%u ", &n);
-      assert(r == 1);
-      (void) r;  /* silence build warning */
-      for (len = sizeof("cpu0"); n /= 10; len++);
-    }
-
-    /* Line contains user, nice, system, idle, iowait, irq, softirq, steal,
-     * guest, guest_nice but we're only interested in the first four + irq.
-     *
-     * Don't use %*s to skip fields or %ll to read straight into the uint64_t
-     * fields, they're not allowed in C89 mode.
-     */
-    if (6 != sscanf(buf + len,
-                    "%" PRIu64 " %" PRIu64 " %" PRIu64
-                    "%" PRIu64 " %" PRIu64 " %" PRIu64,
-                    &user,
-                    &nice,
-                    &sys,
-                    &idle,
-                    &dummy,
-                    &irq))
-      abort();
-
-    ts.user = clock_ticks * user;
-    ts.nice = clock_ticks * nice;
-    ts.sys  = clock_ticks * sys;
-    ts.idle = clock_ticks * idle;
-    ts.irq  = clock_ticks * irq;
-    ci[num++].cpu_times = ts;
-  }
-  assert(num == numcpus);
-
-  return 0;
-}
-
-
-static uint64_t read_cpufreq(unsigned int cpunum) {
-  uint64_t val;
-  char buf[1024];
-  FILE* fp;
-
-  snprintf(buf,
-           sizeof(buf),
-           "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq",
-           cpunum);
-
-  fp = uv__open_file(buf);
-  if (fp == NULL)
-    return 0;
-
-  if (fscanf(fp, "%" PRIu64, &val) != 1)
-    val = 0;
-
-  fclose(fp);
-
-  return val;
-}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(cpu_infos[i].model);
-  }
-
-  uv__free(cpu_infos);
-}
-
-static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
-  if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
-    return 1;
-  if (ent->ifa_addr == NULL)
-    return 1;
-  /*
-   * On Linux getifaddrs returns information related to the raw underlying
-   * devices. We're not interested in this information yet.
-   */
-  if (ent->ifa_addr->sa_family == PF_PACKET)
-    return exclude_type;
-  return !exclude_type;
-}
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
-#ifndef HAVE_IFADDRS_H
-  *count = 0;
-  *addresses = NULL;
-  return UV_ENOSYS;
-#else
-  struct ifaddrs *addrs, *ent;
-  uv_interface_address_t* address;
-  int i;
-  struct sockaddr_ll *sll;
-
-  *count = 0;
-  *addresses = NULL;
-
-  if (getifaddrs(&addrs))
-    return UV__ERR(errno);
-
-  /* Count the number of interfaces */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
-      continue;
-
-    (*count)++;
-  }
-
-  if (*count == 0) {
-    freeifaddrs(addrs);
-    return 0;
-  }
-
-  /* Make sure the memory is initiallized to zero using calloc() */
-  *addresses = (uv_interface_address_t*)uv__calloc(*count, sizeof(**addresses));
-  if (!(*addresses)) {
-    freeifaddrs(addrs);
-    return UV_ENOMEM;
-  }
-
-  address = *addresses;
-
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
-      continue;
-
-    address->name = uv__strdup(ent->ifa_name);
-
-    if (ent->ifa_addr->sa_family == AF_INET6) {
-      address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
-    } else {
-      address->address.address4 = *((struct sockaddr_in*) ent->ifa_addr);
-    }
-
-    if (ent->ifa_netmask->sa_family == AF_INET6) {
-      address->netmask.netmask6 = *((struct sockaddr_in6*) ent->ifa_netmask);
-    } else {
-      address->netmask.netmask4 = *((struct sockaddr_in*) ent->ifa_netmask);
-    }
-
-    address->is_internal = !!(ent->ifa_flags & IFF_LOOPBACK);
-
-    address++;
-  }
-
-  /* Fill in physical addresses for each interface */
-  for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
-    if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
-      continue;
-
-    address = *addresses;
-
-    for (i = 0; i < (*count); i++) {
-      size_t namelen = strlen(ent->ifa_name);
-      /* Alias interface share the same physical address */
-      if (strncmp(address->name, ent->ifa_name, namelen) == 0 &&
-          (address->name[namelen] == 0 || address->name[namelen] == ':')) {
-        sll = (struct sockaddr_ll*)ent->ifa_addr;
-        memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr));
-      }
-      address++;
-    }
-  }
-
-  freeifaddrs(addrs);
-
-  return 0;
-#endif
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
-  int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(addresses[i].name);
-  }
-
-  uv__free(addresses);
-}
-
-
-void uv__set_process_title(const char* title) {
-#if defined(PR_SET_NAME)
-  prctl(PR_SET_NAME, title);  /* Only copies first 16 characters. */
-#endif
-}
-
-
-static uint64_t uv__read_proc_meminfo(const char* what) {
-  uint64_t rc;
-  ssize_t n;
-  char* p;
-  int fd;
-  char buf[4096];  /* Large enough to hold all of /proc/meminfo. */
-
-  rc = 0;
-  fd = uv__open_cloexec("/proc/meminfo", O_RDONLY);
-
-  if (fd == -1)
-    return 0;
-
-  n = read(fd, buf, sizeof(buf) - 1);
-
-  if (n <= 0)
-    goto out;
-
-  buf[n] = '\0';
-  p = strstr(buf, what);
-
-  if (p == NULL)
-    goto out;
-
-  p += strlen(what);
-
-  if (1 != sscanf(p, "%" PRIu64 " kB", &rc))
-    goto out;
-
-  rc *= 1024;
-
-out:
-
-  if (uv__close_nocheckstdio(fd))
-    abort();
-
-  return rc;
-}
-
-
-uint64_t uv_get_free_memory(void) {
-  struct sysinfo info;
-  uint64_t rc;
-
-  rc = uv__read_proc_meminfo("MemFree:");
-
-  if (rc != 0)
-    return rc;
-
-  if (0 == sysinfo(&info))
-    return (uint64_t) info.freeram * info.mem_unit;
-
-  return 0;
-}
-
-
-uint64_t uv_get_total_memory(void) {
-  struct sysinfo info;
-  uint64_t rc;
-
-  rc = uv__read_proc_meminfo("MemTotal:");
-
-  if (rc != 0)
-    return rc;
-
-  if (0 == sysinfo(&info))
-    return (uint64_t) info.totalram * info.mem_unit;
-
-  return 0;
-}
-
-
-static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) {
-  char filename[256];
-  uint64_t rc;
-  int fd;
-  ssize_t n;
-  char buf[32];  /* Large enough to hold an encoded uint64_t. */
-
-  snprintf(filename, 256, "/sys/fs/cgroup/%s/%s", cgroup, param);
-
-  rc = 0;
-  fd = uv__open_cloexec(filename, O_RDONLY);
-
-  if (fd < 0)
-    return 0;
-
-  n = read(fd, buf, sizeof(buf) - 1);
-
-  if (n > 0) {
-    buf[n] = '\0';
-    sscanf(buf, "%" PRIu64, &rc);
-  }
-
-  if (uv__close_nocheckstdio(fd))
-    abort();
-
-  return rc;
-}
-
-
-uint64_t uv_get_constrained_memory(void) {
-  /*
-   * This might return 0 if there was a problem getting the memory limit from
-   * cgroups. This is OK because a return value of 0 signifies that the memory
-   * limit is unknown.
-   */
-  return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes");
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/linux-inotify.cpp b/wpiutil/src/main/native/libuv/src/unix/linux-inotify.cpp
deleted file mode 100644
index ed484cc..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/linux-inotify.cpp
+++ /dev/null
@@ -1,354 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "uv/tree.h"
-#include "internal.h"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-
-struct watcher_list {
-  RB_ENTRY(watcher_list) entry;
-  QUEUE watchers;
-  int iterating;
-  char* path;
-  int wd;
-};
-
-struct watcher_root {
-  struct watcher_list* rbh_root;
-};
-#define CAST(p) ((struct watcher_root*)(p))
-
-
-static int compare_watchers(const struct watcher_list* a,
-                            const struct watcher_list* b) {
-  if (a->wd < b->wd) return -1;
-  if (a->wd > b->wd) return 1;
-  return 0;
-}
-
-
-RB_GENERATE_STATIC(watcher_root, watcher_list, entry, compare_watchers)
-
-
-static void uv__inotify_read(uv_loop_t* loop,
-                             uv__io_t* w,
-                             unsigned int revents);
-
-static void maybe_free_watcher_list(struct watcher_list* w,
-                                    uv_loop_t* loop);
-
-static int new_inotify_fd(void) {
-  int err;
-  int fd;
-
-  fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC);
-  if (fd != -1)
-    return fd;
-
-  if (errno != ENOSYS)
-    return UV__ERR(errno);
-
-  fd = uv__inotify_init();
-  if (fd == -1)
-    return UV__ERR(errno);
-
-  err = uv__cloexec(fd, 1);
-  if (err == 0)
-    err = uv__nonblock(fd, 1);
-
-  if (err) {
-    uv__close(fd);
-    return err;
-  }
-
-  return fd;
-}
-
-
-static int init_inotify(uv_loop_t* loop) {
-  int err;
-
-  if (loop->inotify_fd != -1)
-    return 0;
-
-  err = new_inotify_fd();
-  if (err < 0)
-    return err;
-
-  loop->inotify_fd = err;
-  uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd);
-  uv__io_start(loop, &loop->inotify_read_watcher, POLLIN);
-
-  return 0;
-}
-
-
-int uv__inotify_fork(uv_loop_t* loop, void* old_watchers) {
-  /* Open the inotify_fd, and re-arm all the inotify watchers. */
-  int err;
-  struct watcher_list* tmp_watcher_list_iter;
-  struct watcher_list* watcher_list;
-  struct watcher_list tmp_watcher_list;
-  QUEUE queue;
-  QUEUE* q;
-  uv_fs_event_t* handle;
-  char* tmp_path;
-
-  if (old_watchers != NULL) {
-    /* We must restore the old watcher list to be able to close items
-     * out of it.
-     */
-    loop->inotify_watchers = old_watchers;
-
-    QUEUE_INIT(&tmp_watcher_list.watchers);
-    /* Note that the queue we use is shared with the start and stop()
-     * functions, making QUEUE_FOREACH unsafe to use. So we use the
-     * QUEUE_MOVE trick to safely iterate. Also don't free the watcher
-     * list until we're done iterating. c.f. uv__inotify_read.
-     */
-    RB_FOREACH_SAFE(watcher_list, watcher_root,
-                    CAST(&old_watchers), tmp_watcher_list_iter) {
-      watcher_list->iterating = 1;
-      QUEUE_MOVE(&watcher_list->watchers, &queue);
-      while (!QUEUE_EMPTY(&queue)) {
-        q = QUEUE_HEAD(&queue);
-        handle = QUEUE_DATA(q, uv_fs_event_t, watchers);
-        /* It's critical to keep a copy of path here, because it
-         * will be set to NULL by stop() and then deallocated by
-         * maybe_free_watcher_list
-         */
-        tmp_path = uv__strdup(handle->path);
-        assert(tmp_path != NULL);
-        QUEUE_REMOVE(q);
-        QUEUE_INSERT_TAIL(&watcher_list->watchers, q);
-        uv_fs_event_stop(handle);
-
-        QUEUE_INSERT_TAIL(&tmp_watcher_list.watchers, &handle->watchers);
-        handle->path = tmp_path;
-      }
-      watcher_list->iterating = 0;
-      maybe_free_watcher_list(watcher_list, loop);
-    }
-
-    QUEUE_MOVE(&tmp_watcher_list.watchers, &queue);
-    while (!QUEUE_EMPTY(&queue)) {
-        q = QUEUE_HEAD(&queue);
-        QUEUE_REMOVE(q);
-        handle = QUEUE_DATA(q, uv_fs_event_t, watchers);
-        tmp_path = handle->path;
-        handle->path = NULL;
-        err = uv_fs_event_start(handle, handle->cb, tmp_path, 0);
-        uv__free(tmp_path);
-        if (err)
-          return err;
-    }
-  }
-
-  return 0;
-}
-
-
-static struct watcher_list* find_watcher(uv_loop_t* loop, int wd) {
-  struct watcher_list w;
-  w.wd = wd;
-  return RB_FIND(watcher_root, CAST(&loop->inotify_watchers), &w);
-}
-
-static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) {
-  /* if the watcher_list->watchers is being iterated over, we can't free it. */
-  if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) {
-    /* No watchers left for this path. Clean up. */
-    RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w);
-    uv__inotify_rm_watch(loop->inotify_fd, w->wd);
-    uv__free(w);
-  }
-}
-
-static void uv__inotify_read(uv_loop_t* loop,
-                             uv__io_t* dummy,
-                             unsigned int events) {
-  const struct uv__inotify_event* e;
-  struct watcher_list* w;
-  uv_fs_event_t* h;
-  QUEUE queue;
-  QUEUE* q;
-  const char* path;
-  ssize_t size;
-  const char *p;
-  /* needs to be large enough for sizeof(inotify_event) + strlen(path) */
-  char buf[4096];
-
-  while (1) {
-    do
-      size = read(loop->inotify_fd, buf, sizeof(buf));
-    while (size == -1 && errno == EINTR);
-
-    if (size == -1) {
-      assert(errno == EAGAIN || errno == EWOULDBLOCK);
-      break;
-    }
-
-    assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */
-
-    /* Now we have one or more inotify_event structs. */
-    for (p = buf; p < buf + size; p += sizeof(*e) + e->len) {
-      e = (const struct uv__inotify_event*)p;
-
-      events = 0;
-      if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY))
-        events |= UV_CHANGE;
-      if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY))
-        events |= UV_RENAME;
-
-      w = find_watcher(loop, e->wd);
-      if (w == NULL)
-        continue; /* Stale event, no watchers left. */
-
-      /* inotify does not return the filename when monitoring a single file
-       * for modifications. Repurpose the filename for API compatibility.
-       * I'm not convinced this is a good thing, maybe it should go.
-       */
-      path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path);
-
-      /* We're about to iterate over the queue and call user's callbacks.
-       * What can go wrong?
-       * A callback could call uv_fs_event_stop()
-       * and the queue can change under our feet.
-       * So, we use QUEUE_MOVE() trick to safely iterate over the queue.
-       * And we don't free the watcher_list until we're done iterating.
-       *
-       * First,
-       * tell uv_fs_event_stop() (that could be called from a user's callback)
-       * not to free watcher_list.
-       */
-      w->iterating = 1;
-      QUEUE_MOVE(&w->watchers, &queue);
-      while (!QUEUE_EMPTY(&queue)) {
-        q = QUEUE_HEAD(&queue);
-        h = QUEUE_DATA(q, uv_fs_event_t, watchers);
-
-        QUEUE_REMOVE(q);
-        QUEUE_INSERT_TAIL(&w->watchers, q);
-
-        h->cb(h, path, events, 0);
-      }
-      /* done iterating, time to (maybe) free empty watcher_list */
-      w->iterating = 0;
-      maybe_free_watcher_list(w, loop);
-    }
-  }
-}
-
-
-int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
-  uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
-  return 0;
-}
-
-
-int uv_fs_event_start(uv_fs_event_t* handle,
-                      uv_fs_event_cb cb,
-                      const char* path,
-                      unsigned int flags) {
-  struct watcher_list* w;
-  size_t len;
-  int events;
-  int err;
-  int wd;
-
-  if (uv__is_active(handle))
-    return UV_EINVAL;
-
-  err = init_inotify(handle->loop);
-  if (err)
-    return err;
-
-  events = UV__IN_ATTRIB
-         | UV__IN_CREATE
-         | UV__IN_MODIFY
-         | UV__IN_DELETE
-         | UV__IN_DELETE_SELF
-         | UV__IN_MOVE_SELF
-         | UV__IN_MOVED_FROM
-         | UV__IN_MOVED_TO;
-
-  wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events);
-  if (wd == -1)
-    return UV__ERR(errno);
-
-  w = find_watcher(handle->loop, wd);
-  if (w)
-    goto no_insert;
-
-  len = strlen(path) + 1;
-  w = (watcher_list*)uv__malloc(sizeof(*w) + len);
-  if (w == NULL)
-    return UV_ENOMEM;
-
-  w->wd = wd;
-  w->path = (char*)memcpy(w + 1, path, len);
-  QUEUE_INIT(&w->watchers);
-  w->iterating = 0;
-  RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w);
-
-no_insert:
-  uv__handle_start(handle);
-  QUEUE_INSERT_TAIL(&w->watchers, &handle->watchers);
-  handle->path = w->path;
-  handle->cb = cb;
-  handle->wd = wd;
-
-  return 0;
-}
-
-
-int uv_fs_event_stop(uv_fs_event_t* handle) {
-  struct watcher_list* w;
-
-  if (!uv__is_active(handle))
-    return 0;
-
-  w = find_watcher(handle->loop, handle->wd);
-  assert(w != NULL);
-
-  handle->wd = -1;
-  handle->path = NULL;
-  uv__handle_stop(handle);
-  QUEUE_REMOVE(&handle->watchers);
-
-  maybe_free_watcher_list(w, handle->loop);
-
-  return 0;
-}
-
-
-void uv__fs_event_close(uv_fs_event_t* handle) {
-  uv_fs_event_stop(handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/linux-syscalls.cpp b/wpiutil/src/main/native/libuv/src/unix/linux-syscalls.cpp
deleted file mode 100644
index 5637cf9..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/linux-syscalls.cpp
+++ /dev/null
@@ -1,369 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "linux-syscalls.h"
-#include <unistd.h>
-#include <signal.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#if defined(__has_feature)
-# if __has_feature(memory_sanitizer)
-#  define MSAN_ACTIVE 1
-#  include <sanitizer/msan_interface.h>
-# endif
-#endif
-
-#if defined(__i386__)
-# ifndef __NR_socketcall
-#  define __NR_socketcall 102
-# endif
-#endif
-
-#if defined(__arm__)
-# if defined(__thumb__) || defined(__ARM_EABI__)
-#  define UV_SYSCALL_BASE 0
-# else
-#  define UV_SYSCALL_BASE 0x900000
-# endif
-#endif /* __arm__ */
-
-#ifndef __NR_accept4
-# if defined(__x86_64__)
-#  define __NR_accept4 288
-# elif defined(__i386__)
-   /* Nothing. Handled through socketcall(). */
-# elif defined(__arm__)
-#  define __NR_accept4 (UV_SYSCALL_BASE + 366)
-# endif
-#endif /* __NR_accept4 */
-
-#ifndef __NR_eventfd
-# if defined(__x86_64__)
-#  define __NR_eventfd 284
-# elif defined(__i386__)
-#  define __NR_eventfd 323
-# elif defined(__arm__)
-#  define __NR_eventfd (UV_SYSCALL_BASE + 351)
-# endif
-#endif /* __NR_eventfd */
-
-#ifndef __NR_eventfd2
-# if defined(__x86_64__)
-#  define __NR_eventfd2 290
-# elif defined(__i386__)
-#  define __NR_eventfd2 328
-# elif defined(__arm__)
-#  define __NR_eventfd2 (UV_SYSCALL_BASE + 356)
-# endif
-#endif /* __NR_eventfd2 */
-
-#ifndef __NR_inotify_init
-# if defined(__x86_64__)
-#  define __NR_inotify_init 253
-# elif defined(__i386__)
-#  define __NR_inotify_init 291
-# elif defined(__arm__)
-#  define __NR_inotify_init (UV_SYSCALL_BASE + 316)
-# endif
-#endif /* __NR_inotify_init */
-
-#ifndef __NR_inotify_init1
-# if defined(__x86_64__)
-#  define __NR_inotify_init1 294
-# elif defined(__i386__)
-#  define __NR_inotify_init1 332
-# elif defined(__arm__)
-#  define __NR_inotify_init1 (UV_SYSCALL_BASE + 360)
-# endif
-#endif /* __NR_inotify_init1 */
-
-#ifndef __NR_inotify_add_watch
-# if defined(__x86_64__)
-#  define __NR_inotify_add_watch 254
-# elif defined(__i386__)
-#  define __NR_inotify_add_watch 292
-# elif defined(__arm__)
-#  define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317)
-# endif
-#endif /* __NR_inotify_add_watch */
-
-#ifndef __NR_inotify_rm_watch
-# if defined(__x86_64__)
-#  define __NR_inotify_rm_watch 255
-# elif defined(__i386__)
-#  define __NR_inotify_rm_watch 293
-# elif defined(__arm__)
-#  define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318)
-# endif
-#endif /* __NR_inotify_rm_watch */
-
-#ifndef __NR_pipe2
-# if defined(__x86_64__)
-#  define __NR_pipe2 293
-# elif defined(__i386__)
-#  define __NR_pipe2 331
-# elif defined(__arm__)
-#  define __NR_pipe2 (UV_SYSCALL_BASE + 359)
-# endif
-#endif /* __NR_pipe2 */
-
-#ifndef __NR_recvmmsg
-# if defined(__x86_64__)
-#  define __NR_recvmmsg 299
-# elif defined(__i386__)
-#  define __NR_recvmmsg 337
-# elif defined(__arm__)
-#  define __NR_recvmmsg (UV_SYSCALL_BASE + 365)
-# endif
-#endif /* __NR_recvmsg */
-
-#ifndef __NR_sendmmsg
-# if defined(__x86_64__)
-#  define __NR_sendmmsg 307
-# elif defined(__i386__)
-#  define __NR_sendmmsg 345
-# elif defined(__arm__)
-#  define __NR_sendmmsg (UV_SYSCALL_BASE + 374)
-# endif
-#endif /* __NR_sendmmsg */
-
-#ifndef __NR_utimensat
-# if defined(__x86_64__)
-#  define __NR_utimensat 280
-# elif defined(__i386__)
-#  define __NR_utimensat 320
-# elif defined(__arm__)
-#  define __NR_utimensat (UV_SYSCALL_BASE + 348)
-# endif
-#endif /* __NR_utimensat */
-
-#ifndef __NR_preadv
-# if defined(__x86_64__)
-#  define __NR_preadv 295
-# elif defined(__i386__)
-#  define __NR_preadv 333
-# elif defined(__arm__)
-#  define __NR_preadv (UV_SYSCALL_BASE + 361)
-# endif
-#endif /* __NR_preadv */
-
-#ifndef __NR_pwritev
-# if defined(__x86_64__)
-#  define __NR_pwritev 296
-# elif defined(__i386__)
-#  define __NR_pwritev 334
-# elif defined(__arm__)
-#  define __NR_pwritev (UV_SYSCALL_BASE + 362)
-# endif
-#endif /* __NR_pwritev */
-
-#ifndef __NR_dup3
-# if defined(__x86_64__)
-#  define __NR_dup3 292
-# elif defined(__i386__)
-#  define __NR_dup3 330
-# elif defined(__arm__)
-#  define __NR_dup3 (UV_SYSCALL_BASE + 358)
-# endif
-#endif /* __NR_pwritev */
-
-#ifndef __NR_statx
-# if defined(__x86_64__)
-#  define __NR_statx 332
-# elif defined(__i386__)
-#  define __NR_statx 383
-# elif defined(__aarch64__)
-#  define __NR_statx 397
-# elif defined(__arm__)
-#  define __NR_statx (UV_SYSCALL_BASE + 397)
-# elif defined(__ppc__)
-#  define __NR_statx 383
-# elif defined(__s390__)
-#  define __NR_statx 379
-# endif
-#endif /* __NR_statx */
-
-int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
-#if defined(__i386__)
-  unsigned long args[4];
-  int r;
-
-  args[0] = (unsigned long) fd;
-  args[1] = (unsigned long) addr;
-  args[2] = (unsigned long) addrlen;
-  args[3] = (unsigned long) flags;
-
-  r = syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args);
-
-  /* socketcall() raises EINVAL when SYS_ACCEPT4 is not supported but so does
-   * a bad flags argument. Try to distinguish between the two cases.
-   */
-  if (r == -1)
-    if (errno == EINVAL)
-      if ((flags & ~(UV__SOCK_CLOEXEC|UV__SOCK_NONBLOCK)) == 0)
-        errno = ENOSYS;
-
-  return r;
-#elif defined(__NR_accept4)
-  return syscall(__NR_accept4, fd, addr, addrlen, flags);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__eventfd(unsigned int count) {
-#if defined(__NR_eventfd)
-  return syscall(__NR_eventfd, count);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__eventfd2(unsigned int count, int flags) {
-#if defined(__NR_eventfd2)
-  return syscall(__NR_eventfd2, count, flags);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_init(void) {
-#if defined(__NR_inotify_init)
-  return syscall(__NR_inotify_init);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_init1(int flags) {
-#if defined(__NR_inotify_init1)
-  return syscall(__NR_inotify_init1, flags);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_add_watch(int fd, const char* path, uint32_t mask) {
-#if defined(__NR_inotify_add_watch)
-  return syscall(__NR_inotify_add_watch, fd, path, mask);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_rm_watch(int fd, int32_t wd) {
-#if defined(__NR_inotify_rm_watch)
-  return syscall(__NR_inotify_rm_watch, fd, wd);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__pipe2(int pipefd[2], int flags) {
-#if defined(__NR_pipe2)
-  int result;
-  result = syscall(__NR_pipe2, pipefd, flags);
-#if MSAN_ACTIVE
-  if (!result)
-    __msan_unpoison(pipefd, sizeof(int[2]));
-#endif
-  return result;
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__sendmmsg(int fd,
-                 struct uv__mmsghdr* mmsg,
-                 unsigned int vlen,
-                 unsigned int flags) {
-#if defined(__NR_sendmmsg)
-  return syscall(__NR_sendmmsg, fd, mmsg, vlen, flags);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__recvmmsg(int fd,
-                 struct uv__mmsghdr* mmsg,
-                 unsigned int vlen,
-                 unsigned int flags,
-                 struct timespec* timeout) {
-#if defined(__NR_recvmmsg)
-  return syscall(__NR_recvmmsg, fd, mmsg, vlen, flags, timeout);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
-#if defined(__NR_preadv)
-  return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) {
-#if defined(__NR_pwritev)
-  return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32));
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__dup3(int oldfd, int newfd, int flags) {
-#if defined(__NR_dup3)
-  return syscall(__NR_dup3, oldfd, newfd, flags);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__statx(int dirfd,
-              const char* path,
-              int flags,
-              unsigned int mask,
-              struct uv__statx* statxbuf) {
-  /* __NR_statx make Android box killed by SIGSYS.
-   * That looks like a seccomp2 sandbox filter rejecting the system call.
-   */
-#if defined(__NR_statx) && !defined(__ANDROID__)
-  return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf);
-#else
-  return errno = ENOSYS, -1;
-#endif
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/linux-syscalls.h b/wpiutil/src/main/native/libuv/src/unix/linux-syscalls.h
deleted file mode 100644
index 7e58bfa..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/linux-syscalls.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_LINUX_SYSCALL_H_
-#define UV_LINUX_SYSCALL_H_
-
-#undef  _GNU_SOURCE
-#define _GNU_SOURCE
-
-#include <stdint.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-
-#if defined(__alpha__)
-# define UV__O_CLOEXEC        0x200000
-#elif defined(__hppa__)
-# define UV__O_CLOEXEC        0x200000
-#elif defined(__sparc__)
-# define UV__O_CLOEXEC        0x400000
-#else
-# define UV__O_CLOEXEC        0x80000
-#endif
-
-#if defined(__alpha__)
-# define UV__O_NONBLOCK       0x4
-#elif defined(__hppa__)
-# define UV__O_NONBLOCK       O_NONBLOCK
-#elif defined(__mips__)
-# define UV__O_NONBLOCK       0x80
-#elif defined(__sparc__)
-# define UV__O_NONBLOCK       0x4000
-#else
-# define UV__O_NONBLOCK       0x800
-#endif
-
-#define UV__EFD_CLOEXEC       UV__O_CLOEXEC
-#define UV__EFD_NONBLOCK      UV__O_NONBLOCK
-
-#define UV__IN_CLOEXEC        UV__O_CLOEXEC
-#define UV__IN_NONBLOCK       UV__O_NONBLOCK
-
-#define UV__SOCK_CLOEXEC      UV__O_CLOEXEC
-#if defined(SOCK_NONBLOCK)
-# define UV__SOCK_NONBLOCK    SOCK_NONBLOCK
-#else
-# define UV__SOCK_NONBLOCK    UV__O_NONBLOCK
-#endif
-
-/* inotify flags */
-#define UV__IN_ACCESS         0x001
-#define UV__IN_MODIFY         0x002
-#define UV__IN_ATTRIB         0x004
-#define UV__IN_CLOSE_WRITE    0x008
-#define UV__IN_CLOSE_NOWRITE  0x010
-#define UV__IN_OPEN           0x020
-#define UV__IN_MOVED_FROM     0x040
-#define UV__IN_MOVED_TO       0x080
-#define UV__IN_CREATE         0x100
-#define UV__IN_DELETE         0x200
-#define UV__IN_DELETE_SELF    0x400
-#define UV__IN_MOVE_SELF      0x800
-
-struct uv__statx_timestamp {
-  int64_t tv_sec;
-  uint32_t tv_nsec;
-  int32_t unused0;
-};
-
-struct uv__statx {
-  uint32_t stx_mask;
-  uint32_t stx_blksize;
-  uint64_t stx_attributes;
-  uint32_t stx_nlink;
-  uint32_t stx_uid;
-  uint32_t stx_gid;
-  uint16_t stx_mode;
-  uint16_t unused0;
-  uint64_t stx_ino;
-  uint64_t stx_size;
-  uint64_t stx_blocks;
-  uint64_t stx_attributes_mask;
-  struct uv__statx_timestamp stx_atime;
-  struct uv__statx_timestamp stx_btime;
-  struct uv__statx_timestamp stx_ctime;
-  struct uv__statx_timestamp stx_mtime;
-  uint32_t stx_rdev_major;
-  uint32_t stx_rdev_minor;
-  uint32_t stx_dev_major;
-  uint32_t stx_dev_minor;
-  uint64_t unused1[14];
-};
-
-struct uv__inotify_event {
-  int32_t wd;
-  uint32_t mask;
-  uint32_t cookie;
-  uint32_t len;
-  /* char name[0]; */
-};
-
-struct uv__mmsghdr {
-  struct msghdr msg_hdr;
-  unsigned int msg_len;
-};
-
-int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
-int uv__eventfd(unsigned int count);
-int uv__eventfd2(unsigned int count, int flags);
-int uv__inotify_init(void);
-int uv__inotify_init1(int flags);
-int uv__inotify_add_watch(int fd, const char* path, uint32_t mask);
-int uv__inotify_rm_watch(int fd, int32_t wd);
-int uv__pipe2(int pipefd[2], int flags);
-int uv__recvmmsg(int fd,
-                 struct uv__mmsghdr* mmsg,
-                 unsigned int vlen,
-                 unsigned int flags,
-                 struct timespec* timeout);
-int uv__sendmmsg(int fd,
-                 struct uv__mmsghdr* mmsg,
-                 unsigned int vlen,
-                 unsigned int flags);
-ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
-ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
-int uv__dup3(int oldfd, int newfd, int flags);
-int uv__statx(int dirfd,
-              const char* path,
-              int flags,
-              unsigned int mask,
-              struct uv__statx* statxbuf);
-
-#endif /* UV_LINUX_SYSCALL_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/unix/loop-watcher.cpp b/wpiutil/src/main/native/libuv/src/unix/loop-watcher.cpp
deleted file mode 100644
index b8c1c2a..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/loop-watcher.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#define UV_LOOP_WATCHER_DEFINE(name, type)                                    \
-  int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) {              \
-    uv__handle_init(loop, (uv_handle_t*)handle, UV_##type);                   \
-    handle->name##_cb = NULL;                                                 \
-    return 0;                                                                 \
-  }                                                                           \
-                                                                              \
-  int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) {           \
-    if (uv__is_active(handle)) return 0;                                      \
-    if (cb == NULL) return UV_EINVAL;                                         \
-    QUEUE_INSERT_HEAD(&handle->loop->name##_handles, &handle->queue);         \
-    handle->name##_cb = cb;                                                   \
-    uv__handle_start(handle);                                                 \
-    return 0;                                                                 \
-  }                                                                           \
-                                                                              \
-  int uv_##name##_stop(uv_##name##_t* handle) {                               \
-    if (!uv__is_active(handle)) return 0;                                     \
-    QUEUE_REMOVE(&handle->queue);                                             \
-    uv__handle_stop(handle);                                                  \
-    return 0;                                                                 \
-  }                                                                           \
-                                                                              \
-  void uv__run_##name(uv_loop_t* loop) {                                      \
-    uv_##name##_t* h;                                                         \
-    QUEUE queue;                                                              \
-    QUEUE* q;                                                                 \
-    QUEUE_MOVE(&loop->name##_handles, &queue);                                \
-    while (!QUEUE_EMPTY(&queue)) {                                            \
-      q = QUEUE_HEAD(&queue);                                                 \
-      h = QUEUE_DATA(q, uv_##name##_t, queue);                                \
-      QUEUE_REMOVE(q);                                                        \
-      QUEUE_INSERT_TAIL(&loop->name##_handles, q);                            \
-      h->name##_cb(h);                                                        \
-    }                                                                         \
-  }                                                                           \
-                                                                              \
-  void uv__##name##_close(uv_##name##_t* handle) {                            \
-    uv_##name##_stop(handle);                                                 \
-  }
-
-UV_LOOP_WATCHER_DEFINE(prepare, PREPARE)
-UV_LOOP_WATCHER_DEFINE(check, CHECK)
-UV_LOOP_WATCHER_DEFINE(idle, IDLE)
diff --git a/wpiutil/src/main/native/libuv/src/unix/loop.cpp b/wpiutil/src/main/native/libuv/src/unix/loop.cpp
deleted file mode 100644
index 7a037d1..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/loop.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "uv/tree.h"
-#include "internal.h"
-#include "heap-inl.h"
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-int uv_loop_init(uv_loop_t* loop) {
-  void* saved_data;
-  int err;
-
-
-  saved_data = loop->data;
-  memset(loop, 0, sizeof(*loop));
-  loop->data = saved_data;
-
-  heap_init((struct heap*) &loop->timer_heap);
-  QUEUE_INIT(&loop->wq);
-  QUEUE_INIT(&loop->idle_handles);
-  QUEUE_INIT(&loop->async_handles);
-  QUEUE_INIT(&loop->check_handles);
-  QUEUE_INIT(&loop->prepare_handles);
-  QUEUE_INIT(&loop->handle_queue);
-
-  loop->active_handles = 0;
-  loop->active_reqs.count = 0;
-  loop->nfds = 0;
-  loop->watchers = NULL;
-  loop->nwatchers = 0;
-  QUEUE_INIT(&loop->pending_queue);
-  QUEUE_INIT(&loop->watcher_queue);
-
-  loop->closing_handles = NULL;
-  uv__update_time(loop);
-  loop->async_io_watcher.fd = -1;
-  loop->async_wfd = -1;
-  loop->signal_pipefd[0] = -1;
-  loop->signal_pipefd[1] = -1;
-  loop->backend_fd = -1;
-  loop->emfile_fd = -1;
-
-  loop->timer_counter = 0;
-  loop->stop_flag = 0;
-
-  err = uv__platform_loop_init(loop);
-  if (err)
-    return err;
-
-  uv__signal_global_once_init();
-  err = uv_signal_init(loop, &loop->child_watcher);
-  if (err)
-    goto fail_signal_init;
-
-  uv__handle_unref(&loop->child_watcher);
-  loop->child_watcher.flags |= UV_HANDLE_INTERNAL;
-  QUEUE_INIT(&loop->process_handles);
-
-  err = uv_rwlock_init(&loop->cloexec_lock);
-  if (err)
-    goto fail_rwlock_init;
-
-  err = uv_mutex_init(&loop->wq_mutex);
-  if (err)
-    goto fail_mutex_init;
-
-  err = uv_async_init(loop, &loop->wq_async, uv__work_done);
-  if (err)
-    goto fail_async_init;
-
-  uv__handle_unref(&loop->wq_async);
-  loop->wq_async.flags |= UV_HANDLE_INTERNAL;
-
-  return 0;
-
-fail_async_init:
-  uv_mutex_destroy(&loop->wq_mutex);
-
-fail_mutex_init:
-  uv_rwlock_destroy(&loop->cloexec_lock);
-
-fail_rwlock_init:
-  uv__signal_loop_cleanup(loop);
-
-fail_signal_init:
-  uv__platform_loop_delete(loop);
-
-  return err;
-}
-
-
-int uv_loop_fork(uv_loop_t* loop) {
-  int err;
-  unsigned int i;
-  uv__io_t* w;
-
-  err = uv__io_fork(loop);
-  if (err)
-    return err;
-
-  err = uv__async_fork(loop);
-  if (err)
-    return err;
-
-  err = uv__signal_loop_fork(loop);
-  if (err)
-    return err;
-
-  /* Rearm all the watchers that aren't re-queued by the above. */
-  for (i = 0; i < loop->nwatchers; i++) {
-    w = (uv__io_t*)loop->watchers[i];
-    if (w == NULL)
-      continue;
-
-    if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue)) {
-      w->events = 0; /* Force re-registration in uv__io_poll. */
-      QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
-    }
-  }
-
-  return 0;
-}
-
-
-void uv__loop_close(uv_loop_t* loop) {
-  uv__signal_loop_cleanup(loop);
-  uv__platform_loop_delete(loop);
-  uv__async_stop(loop);
-
-  if (loop->emfile_fd != -1) {
-    uv__close(loop->emfile_fd);
-    loop->emfile_fd = -1;
-  }
-
-  if (loop->backend_fd != -1) {
-    uv__close(loop->backend_fd);
-    loop->backend_fd = -1;
-  }
-
-  uv_mutex_lock(&loop->wq_mutex);
-  assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!");
-  assert(!uv__has_active_reqs(loop));
-  uv_mutex_unlock(&loop->wq_mutex);
-  uv_mutex_destroy(&loop->wq_mutex);
-
-  /*
-   * Note that all thread pool stuff is finished at this point and
-   * it is safe to just destroy rw lock
-   */
-  uv_rwlock_destroy(&loop->cloexec_lock);
-
-#if 0
-  assert(QUEUE_EMPTY(&loop->pending_queue));
-  assert(QUEUE_EMPTY(&loop->watcher_queue));
-  assert(loop->nfds == 0);
-#endif
-
-  uv__free(loop->watchers);
-  loop->watchers = NULL;
-  loop->nwatchers = 0;
-}
-
-
-int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
-  if (option != UV_LOOP_BLOCK_SIGNAL)
-    return UV_ENOSYS;
-
-  if (va_arg(ap, int) != SIGPROF)
-    return UV_EINVAL;
-
-  loop->flags |= UV_LOOP_BLOCK_SIGPROF;
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/netbsd.cpp b/wpiutil/src/main/native/libuv/src/unix/netbsd.cpp
deleted file mode 100644
index fb89843..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/netbsd.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-
-#include <kvm.h>
-#include <paths.h>
-#include <unistd.h>
-#include <time.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <uvm/uvm_extern.h>
-
-#include <unistd.h>
-#include <time.h>
-
-
-int uv__platform_loop_init(uv_loop_t* loop) {
-  return uv__kqueue_init(loop);
-}
-
-
-void uv__platform_loop_delete(uv_loop_t* loop) {
-}
-
-
-void uv_loadavg(double avg[3]) {
-  struct loadavg info;
-  size_t size = sizeof(info);
-  int which[] = {CTL_VM, VM_LOADAVG};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0) == -1) return;
-
-  avg[0] = (double) info.ldavg[0] / info.fscale;
-  avg[1] = (double) info.ldavg[1] / info.fscale;
-  avg[2] = (double) info.ldavg[2] / info.fscale;
-}
-
-
-int uv_exepath(char* buffer, size_t* size) {
-  /* Intermediate buffer, retrieving partial path name does not work
-   * As of NetBSD-8(beta), vnode->path translator does not handle files
-   * with longer names than 31 characters.
-   */
-  char int_buf[PATH_MAX];
-  size_t int_size;
-  int mib[4];
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC_ARGS;
-  mib[2] = -1;
-  mib[3] = KERN_PROC_PATHNAME;
-  int_size = ARRAY_SIZE(int_buf);
-
-  if (sysctl(mib, 4, int_buf, &int_size, NULL, 0))
-    return UV__ERR(errno);
-
-  /* Copy string from the intermediate buffer to outer one with appropriate
-   * length.
-   */
-  /* TODO(bnoordhuis) Check uv__strscpy() return value. */
-  uv__strscpy(buffer, int_buf, *size);
-
-  /* Set new size. */
-  *size = strlen(buffer);
-
-  return 0;
-}
-
-
-uint64_t uv_get_free_memory(void) {
-  struct uvmexp info;
-  size_t size = sizeof(info);
-  int which[] = {CTL_VM, VM_UVMEXP};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
-}
-
-
-uint64_t uv_get_total_memory(void) {
-#if defined(HW_PHYSMEM64)
-  uint64_t info;
-  int which[] = {CTL_HW, HW_PHYSMEM64};
-#else
-  unsigned int info;
-  int which[] = {CTL_HW, HW_PHYSMEM};
-#endif
-  size_t size = sizeof(info);
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  return (uint64_t) info;
-}
-
-
-uint64_t uv_get_constrained_memory(void) {
-  return 0;  /* Memory constraints are unknown. */
-}
-
-
-int uv_resident_set_memory(size_t* rss) {
-  kvm_t *kd = NULL;
-  struct kinfo_proc2 *kinfo = NULL;
-  pid_t pid;
-  int nprocs;
-  int max_size = sizeof(struct kinfo_proc2);
-  int page_size;
-
-  page_size = getpagesize();
-  pid = getpid();
-
-  kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open");
-
-  if (kd == NULL) goto error;
-
-  kinfo = kvm_getproc2(kd, KERN_PROC_PID, pid, max_size, &nprocs);
-  if (kinfo == NULL) goto error;
-
-  *rss = kinfo->p_vm_rssize * page_size;
-
-  kvm_close(kd);
-
-  return 0;
-
-error:
-  if (kd) kvm_close(kd);
-  return UV_EPERM;
-}
-
-
-int uv_uptime(double* uptime) {
-  time_t now;
-  struct timeval info;
-  size_t size = sizeof(info);
-  static int which[] = {CTL_KERN, KERN_BOOTTIME};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  now = time(NULL);
-
-  *uptime = (double)(now - info.tv_sec);
-  return 0;
-}
-
-
-int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
-  unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK);
-  unsigned int multiplier = ((uint64_t)1000L / ticks);
-  unsigned int cur = 0;
-  uv_cpu_info_t* cpu_info;
-  u_int64_t* cp_times;
-  char model[512];
-  u_int64_t cpuspeed;
-  int numcpus;
-  size_t size;
-  int i;
-
-  size = sizeof(model);
-  if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) &&
-      sysctlbyname("hw.model", &model, &size, NULL, 0)) {
-    return UV__ERR(errno);
-  }
-
-  size = sizeof(numcpus);
-  if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
-    return UV__ERR(errno);
-  *count = numcpus;
-
-  /* Only i386 and amd64 have machdep.tsc_freq */
-  size = sizeof(cpuspeed);
-  if (sysctlbyname("machdep.tsc_freq", &cpuspeed, &size, NULL, 0))
-    cpuspeed = 0;
-
-  size = numcpus * CPUSTATES * sizeof(*cp_times);
-  cp_times = (u_int64_t*)uv__malloc(size);
-  if (cp_times == NULL)
-    return UV_ENOMEM;
-
-  if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  *cpu_infos = (uv_cpu_info_t*)uv__malloc(numcpus * sizeof(**cpu_infos));
-  if (!(*cpu_infos)) {
-    uv__free(cp_times);
-    uv__free(*cpu_infos);
-    return UV_ENOMEM;
-  }
-
-  for (i = 0; i < numcpus; i++) {
-    cpu_info = &(*cpu_infos)[i];
-    cpu_info->cpu_times.user = (uint64_t)(cp_times[CP_USER+cur]) * multiplier;
-    cpu_info->cpu_times.nice = (uint64_t)(cp_times[CP_NICE+cur]) * multiplier;
-    cpu_info->cpu_times.sys = (uint64_t)(cp_times[CP_SYS+cur]) * multiplier;
-    cpu_info->cpu_times.idle = (uint64_t)(cp_times[CP_IDLE+cur]) * multiplier;
-    cpu_info->cpu_times.irq = (uint64_t)(cp_times[CP_INTR+cur]) * multiplier;
-    cpu_info->model = uv__strdup(model);
-    cpu_info->speed = (int)(cpuspeed/(uint64_t) 1e6);
-    cur += CPUSTATES;
-  }
-  uv__free(cp_times);
-  return 0;
-}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(cpu_infos[i].model);
-  }
-
-  uv__free(cpu_infos);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/no-fsevents.cpp b/wpiutil/src/main/native/libuv/src/unix/no-fsevents.cpp
deleted file mode 100644
index 158643a..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/no-fsevents.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <errno.h>
-
-int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
-  return UV_ENOSYS;
-}
-
-int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
-                      const char* filename, unsigned int flags) {
-  return UV_ENOSYS;
-}
-
-int uv_fs_event_stop(uv_fs_event_t* handle) {
-  return UV_ENOSYS;
-}
-
-void uv__fs_event_close(uv_fs_event_t* handle) {
-  UNREACHABLE();
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/no-proctitle.cpp b/wpiutil/src/main/native/libuv/src/unix/no-proctitle.cpp
deleted file mode 100644
index 165740c..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/no-proctitle.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <errno.h>
-#include <stddef.h>
-
-char** uv_setup_args(int argc, char** argv) {
-  return argv;
-}
-
-int uv_set_process_title(const char* title) {
-  return 0;
-}
-
-int uv_get_process_title(char* buffer, size_t size) {
-  if (buffer == NULL || size == 0)
-    return UV_EINVAL;
-
-  buffer[0] = '\0';
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/openbsd.cpp b/wpiutil/src/main/native/libuv/src/unix/openbsd.cpp
deleted file mode 100644
index f13ad8c..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/openbsd.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/resource.h>
-#include <sys/sched.h>
-#include <sys/time.h>
-#include <sys/sysctl.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-
-int uv__platform_loop_init(uv_loop_t* loop) {
-  return uv__kqueue_init(loop);
-}
-
-
-void uv__platform_loop_delete(uv_loop_t* loop) {
-}
-
-
-void uv_loadavg(double avg[3]) {
-  struct loadavg info;
-  size_t size = sizeof(info);
-  int which[] = {CTL_VM, VM_LOADAVG};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return;
-
-  avg[0] = (double) info.ldavg[0] / info.fscale;
-  avg[1] = (double) info.ldavg[1] / info.fscale;
-  avg[2] = (double) info.ldavg[2] / info.fscale;
-}
-
-
-int uv_exepath(char* buffer, size_t* size) {
-  int mib[4];
-  char **argsbuf = NULL;
-  char **argsbuf_tmp;
-  size_t argsbuf_size = 100U;
-  size_t exepath_size;
-  pid_t mypid;
-  int err;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  mypid = getpid();
-  for (;;) {
-    err = UV_ENOMEM;
-    argsbuf_tmp = (char**)uv__realloc(argsbuf, argsbuf_size);
-    if (argsbuf_tmp == NULL)
-      goto out;
-    argsbuf = argsbuf_tmp;
-    mib[0] = CTL_KERN;
-    mib[1] = KERN_PROC_ARGS;
-    mib[2] = mypid;
-    mib[3] = KERN_PROC_ARGV;
-    if (sysctl(mib, 4, argsbuf, &argsbuf_size, NULL, 0) == 0) {
-      break;
-    }
-    if (errno != ENOMEM) {
-      err = UV__ERR(errno);
-      goto out;
-    }
-    argsbuf_size *= 2U;
-  }
-
-  if (argsbuf[0] == NULL) {
-    err = UV_EINVAL;  /* FIXME(bnoordhuis) More appropriate error. */
-    goto out;
-  }
-
-  *size -= 1;
-  exepath_size = strlen(argsbuf[0]);
-  if (*size > exepath_size)
-    *size = exepath_size;
-
-  memcpy(buffer, argsbuf[0], *size);
-  buffer[*size] = '\0';
-  err = 0;
-
-out:
-  uv__free(argsbuf);
-
-  return err;
-}
-
-
-uint64_t uv_get_free_memory(void) {
-  struct uvmexp info;
-  size_t size = sizeof(info);
-  int which[] = {CTL_VM, VM_UVMEXP};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
-}
-
-
-uint64_t uv_get_total_memory(void) {
-  uint64_t info;
-  int which[] = {CTL_HW, HW_PHYSMEM64};
-  size_t size = sizeof(info);
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  return (uint64_t) info;
-}
-
-
-uint64_t uv_get_constrained_memory(void) {
-  return 0;  /* Memory constraints are unknown. */
-}
-
-
-int uv_resident_set_memory(size_t* rss) {
-  struct kinfo_proc kinfo;
-  size_t page_size = getpagesize();
-  size_t size = sizeof(struct kinfo_proc);
-  int mib[6];
-
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC;
-  mib[2] = KERN_PROC_PID;
-  mib[3] = getpid();
-  mib[4] = sizeof(struct kinfo_proc);
-  mib[5] = 1;
-
-  if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0)
-    return UV__ERR(errno);
-
-  *rss = kinfo.p_vm_rssize * page_size;
-  return 0;
-}
-
-
-int uv_uptime(double* uptime) {
-  time_t now;
-  struct timeval info;
-  size_t size = sizeof(info);
-  static int which[] = {CTL_KERN, KERN_BOOTTIME};
-
-  if (sysctl(which, 2, &info, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  now = time(NULL);
-
-  *uptime = (double)(now - info.tv_sec);
-  return 0;
-}
-
-
-int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
-  unsigned int ticks = (unsigned int)sysconf(_SC_CLK_TCK),
-               multiplier = ((uint64_t)1000L / ticks), cpuspeed;
-  uint64_t info[CPUSTATES];
-  char model[512];
-  int numcpus = 1;
-  int which[] = {CTL_HW,HW_MODEL,0};
-  size_t size;
-  int i;
-  uv_cpu_info_t* cpu_info;
-
-  size = sizeof(model);
-  if (sysctl(which, 2, &model, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  which[1] = HW_NCPU;
-  size = sizeof(numcpus);
-  if (sysctl(which, 2, &numcpus, &size, NULL, 0))
-    return UV__ERR(errno);
-
-  *cpu_infos = (uv_cpu_info_t*)uv__malloc(numcpus * sizeof(**cpu_infos));
-  if (!(*cpu_infos))
-    return UV_ENOMEM;
-
-  *count = numcpus;
-
-  which[1] = HW_CPUSPEED;
-  size = sizeof(cpuspeed);
-  if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
-    uv__free(*cpu_infos);
-    return UV__ERR(errno);
-  }
-
-  size = sizeof(info);
-  which[0] = CTL_KERN;
-  which[1] = KERN_CPTIME2;
-  for (i = 0; i < numcpus; i++) {
-    which[2] = i;
-    size = sizeof(info);
-    if (sysctl(which, 3, &info, &size, NULL, 0)) {
-      uv__free(*cpu_infos);
-      return UV__ERR(errno);
-    }
-
-    cpu_info = &(*cpu_infos)[i];
-
-    cpu_info->cpu_times.user = (uint64_t)(info[CP_USER]) * multiplier;
-    cpu_info->cpu_times.nice = (uint64_t)(info[CP_NICE]) * multiplier;
-    cpu_info->cpu_times.sys = (uint64_t)(info[CP_SYS]) * multiplier;
-    cpu_info->cpu_times.idle = (uint64_t)(info[CP_IDLE]) * multiplier;
-    cpu_info->cpu_times.irq = (uint64_t)(info[CP_INTR]) * multiplier;
-
-    cpu_info->model = uv__strdup(model);
-    cpu_info->speed = cpuspeed;
-  }
-
-  return 0;
-}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(cpu_infos[i].model);
-  }
-
-  uv__free(cpu_infos);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/pipe.cpp b/wpiutil/src/main/native/libuv/src/unix/pipe.cpp
deleted file mode 100644
index c21033a..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/pipe.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-
-int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
-  uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
-  handle->shutdown_req = NULL;
-  handle->connect_req = NULL;
-  handle->pipe_fname = NULL;
-  handle->ipc = ipc;
-  return 0;
-}
-
-
-int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
-  struct sockaddr_un saddr;
-  const char* pipe_fname;
-  int sockfd;
-  int err;
-
-  pipe_fname = NULL;
-
-  /* Already bound? */
-  if (uv__stream_fd(handle) >= 0)
-    return UV_EINVAL;
-
-  /* Make a copy of the file name, it outlives this function's scope. */
-  pipe_fname = uv__strdup(name);
-  if (pipe_fname == NULL)
-    return UV_ENOMEM;
-
-  /* We've got a copy, don't touch the original any more. */
-  name = NULL;
-
-  err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
-  if (err < 0)
-    goto err_socket;
-  sockfd = err;
-
-  memset(&saddr, 0, sizeof saddr);
-  uv__strscpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
-  saddr.sun_family = AF_UNIX;
-
-  if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
-    err = UV__ERR(errno);
-    /* Convert ENOENT to EACCES for compatibility with Windows. */
-    if (err == UV_ENOENT)
-      err = UV_EACCES;
-
-    uv__close(sockfd);
-    goto err_socket;
-  }
-
-  /* Success. */
-  handle->flags |= UV_HANDLE_BOUND;
-  handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */
-  handle->io_watcher.fd = sockfd;
-  return 0;
-
-err_socket:
-  uv__free((void*)pipe_fname);
-  return err;
-}
-
-
-int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
-  if (uv__stream_fd(handle) == -1)
-    return UV_EINVAL;
-
-#if defined(__MVS__)
-  /* On zOS, backlog=0 has undefined behaviour */
-  if (backlog == 0)
-    backlog = 1;
-  else if (backlog < 0)
-    backlog = SOMAXCONN;
-#endif
-
-  if (listen(uv__stream_fd(handle), backlog))
-    return UV__ERR(errno);
-
-  handle->connection_cb = cb;
-  handle->io_watcher.cb = uv__server_io;
-  uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
-  return 0;
-}
-
-
-void uv__pipe_close(uv_pipe_t* handle) {
-  if (handle->pipe_fname) {
-    /*
-     * Unlink the file system entity before closing the file descriptor.
-     * Doing it the other way around introduces a race where our process
-     * unlinks a socket with the same name that's just been created by
-     * another thread or process.
-     */
-    unlink(handle->pipe_fname);
-    uv__free((void*)handle->pipe_fname);
-    handle->pipe_fname = NULL;
-  }
-
-  uv__stream_close((uv_stream_t*)handle);
-}
-
-
-int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
-  int flags;
-  int mode;
-  int err;
-  flags = 0;
-
-  if (uv__fd_exists(handle->loop, fd))
-    return UV_EEXIST;
-
-  do
-    mode = fcntl(fd, F_GETFL);
-  while (mode == -1 && errno == EINTR);
-
-  if (mode == -1)
-    return UV__ERR(errno); /* according to docs, must be EBADF */
-
-  err = uv__nonblock(fd, 1);
-  if (err)
-    return err;
-
-#if defined(__APPLE__)
-  err = uv__stream_try_select((uv_stream_t*) handle, &fd);
-  if (err)
-    return err;
-#endif /* defined(__APPLE__) */
-
-  mode &= O_ACCMODE;
-  if (mode != O_WRONLY)
-    flags |= UV_HANDLE_READABLE;
-  if (mode != O_RDONLY)
-    flags |= UV_HANDLE_WRITABLE;
-
-  return uv__stream_open((uv_stream_t*)handle, fd, flags);
-}
-
-
-void uv_pipe_connect(uv_connect_t* req,
-                    uv_pipe_t* handle,
-                    const char* name,
-                    uv_connect_cb cb) {
-  struct sockaddr_un saddr;
-  int new_sock;
-  int err;
-  int r;
-
-  new_sock = (uv__stream_fd(handle) == -1);
-
-  if (new_sock) {
-    err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
-    if (err < 0)
-      goto out;
-    handle->io_watcher.fd = err;
-  }
-
-  memset(&saddr, 0, sizeof saddr);
-  uv__strscpy(saddr.sun_path, name, sizeof(saddr.sun_path));
-  saddr.sun_family = AF_UNIX;
-
-  do {
-    r = connect(uv__stream_fd(handle),
-                (struct sockaddr*)&saddr, sizeof saddr);
-  }
-  while (r == -1 && errno == EINTR);
-
-  if (r == -1 && errno != EINPROGRESS) {
-    err = UV__ERR(errno);
-#if defined(__CYGWIN__) || defined(__MSYS__)
-    /* EBADF is supposed to mean that the socket fd is bad, but
-       Cygwin reports EBADF instead of ENOTSOCK when the file is
-       not a socket.  We do not expect to see a bad fd here
-       (e.g. due to new_sock), so translate the error.  */
-    if (err == UV_EBADF)
-      err = UV_ENOTSOCK;
-#endif
-    goto out;
-  }
-
-  err = 0;
-  if (new_sock) {
-    err = uv__stream_open((uv_stream_t*)handle,
-                          uv__stream_fd(handle),
-                          UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
-  }
-
-  if (err == 0)
-    uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
-
-out:
-  handle->delayed_error = err;
-  handle->connect_req = req;
-
-  uv__req_init(handle->loop, req, UV_CONNECT);
-  req->handle = (uv_stream_t*)handle;
-  req->cb = cb;
-  QUEUE_INIT(&req->queue);
-
-  /* Force callback to run on next tick in case of error. */
-  if (err)
-    uv__io_feed(handle->loop, &handle->io_watcher);
-
-}
-
-
-static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
-                                    uv__peersockfunc func,
-                                    char* buffer,
-                                    size_t* size) {
-  struct sockaddr_un sa;
-  socklen_t addrlen;
-  int err;
-
-  addrlen = sizeof(sa);
-  memset(&sa, 0, addrlen);
-  err = uv__getsockpeername((const uv_handle_t*) handle,
-                            func,
-                            (struct sockaddr*) &sa,
-                            (int*) &addrlen);
-  if (err < 0) {
-    *size = 0;
-    return err;
-  }
-
-#if defined(__linux__)
-  if (sa.sun_path[0] == 0)
-    /* Linux abstract namespace */
-    addrlen -= offsetof(struct sockaddr_un, sun_path);
-  else
-#endif
-    addrlen = strlen(sa.sun_path);
-
-
-  if (addrlen >= *size) {
-    *size = addrlen + 1;
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, sa.sun_path, addrlen);
-  *size = addrlen;
-
-  /* only null-terminate if it's not an abstract socket */
-  if (buffer[0] != '\0')
-    buffer[addrlen] = '\0';
-
-  return 0;
-}
-
-
-int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
-  return uv__pipe_getsockpeername(handle, getsockname, buffer, size);
-}
-
-
-int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
-  return uv__pipe_getsockpeername(handle, getpeername, buffer, size);
-}
-
-
-void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
-}
-
-
-int uv_pipe_pending_count(uv_pipe_t* handle) {
-  uv__stream_queued_fds_t* queued_fds;
-
-  if (!handle->ipc)
-    return 0;
-
-  if (handle->accepted_fd == -1)
-    return 0;
-
-  if (handle->queued_fds == NULL)
-    return 1;
-
-  queued_fds = (uv__stream_queued_fds_t*)(handle->queued_fds);
-  return queued_fds->offset + 1;
-}
-
-
-uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
-  if (!handle->ipc)
-    return UV_UNKNOWN_HANDLE;
-
-  if (handle->accepted_fd == -1)
-    return UV_UNKNOWN_HANDLE;
-  else
-    return uv__handle_type(handle->accepted_fd);
-}
-
-
-int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
-  unsigned desired_mode;
-  struct stat pipe_stat;
-  char* name_buffer;
-  size_t name_len;
-  int r;
-
-  if (handle == NULL || uv__stream_fd(handle) == -1)
-    return UV_EBADF;
-
-  if (mode != UV_READABLE &&
-      mode != UV_WRITABLE &&
-      mode != (UV_WRITABLE | UV_READABLE))
-    return UV_EINVAL;
-
-  /* Unfortunately fchmod does not work on all platforms, we will use chmod. */
-  name_len = 0;
-  r = uv_pipe_getsockname(handle, NULL, &name_len);
-  if (r != UV_ENOBUFS)
-    return r;
-
-  name_buffer = (char*)uv__malloc(name_len);
-  if (name_buffer == NULL)
-    return UV_ENOMEM;
-
-  r = uv_pipe_getsockname(handle, name_buffer, &name_len);
-  if (r != 0) {
-    uv__free(name_buffer);
-    return r;
-  }
-
-  /* stat must be used as fstat has a bug on Darwin */
-  if (stat(name_buffer, &pipe_stat) == -1) {
-    uv__free(name_buffer);
-    return -errno;
-  }
-
-  desired_mode = 0;
-  if (mode & UV_READABLE)
-    desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
-  if (mode & UV_WRITABLE)
-    desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-
-  /* Exit early if pipe already has desired mode. */
-  if ((pipe_stat.st_mode & desired_mode) == desired_mode) {
-    uv__free(name_buffer);
-    return 0;
-  }
-
-  pipe_stat.st_mode |= desired_mode;
-
-  r = chmod(name_buffer, pipe_stat.st_mode);
-  uv__free(name_buffer);
-
-  return r != -1 ? 0 : UV__ERR(errno);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/poll.cpp b/wpiutil/src/main/native/libuv/src/unix/poll.cpp
deleted file mode 100644
index d578611..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/poll.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-
-
-static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
-  uv_poll_t* handle;
-  int pevents;
-
-  handle = container_of(w, uv_poll_t, io_watcher);
-
-  /*
-   * As documented in the kernel source fs/kernfs/file.c #780
-   * poll will return POLLERR|POLLPRI in case of sysfs
-   * polling. This does not happen in case of out-of-band
-   * TCP messages.
-   *
-   * The above is the case on (at least) FreeBSD and Linux.
-   *
-   * So to properly determine a POLLPRI or a POLLERR we need
-   * to check for both.
-   */
-  if ((events & POLLERR) && !(events & UV__POLLPRI)) {
-    uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
-    uv__handle_stop(handle);
-    handle->poll_cb(handle, UV_EBADF, 0);
-    return;
-  }
-
-  pevents = 0;
-  if (events & POLLIN)
-    pevents |= UV_READABLE;
-  if (events & UV__POLLPRI)
-    pevents |= UV_PRIORITIZED;
-  if (events & POLLOUT)
-    pevents |= UV_WRITABLE;
-  if (events & UV__POLLRDHUP)
-    pevents |= UV_DISCONNECT;
-
-  handle->poll_cb(handle, 0, pevents);
-}
-
-
-int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
-  int err;
-
-  if (uv__fd_exists(loop, fd))
-    return UV_EEXIST;
-
-  err = uv__io_check_fd(loop, fd);
-  if (err)
-    return err;
-
-  /* If ioctl(FIONBIO) reports ENOTTY, try fcntl(F_GETFL) + fcntl(F_SETFL).
-   * Workaround for e.g. kqueue fds not supporting ioctls.
-   */
-  err = uv__nonblock(fd, 1);
-#ifdef UV__NONBLOCK_IS_IOCTL
-  if (err == UV_ENOTTY)
-    err = uv__nonblock_fcntl(fd, 1);
-#endif
-
-  if (err)
-    return err;
-
-  uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);
-  uv__io_init(&handle->io_watcher, uv__poll_io, fd);
-  handle->poll_cb = NULL;
-  return 0;
-}
-
-
-int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
-    uv_os_sock_t socket) {
-  return uv_poll_init(loop, handle, socket);
-}
-
-
-static void uv__poll_stop(uv_poll_t* handle) {
-  uv__io_stop(handle->loop,
-              &handle->io_watcher,
-              POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
-  uv__handle_stop(handle);
-  uv__platform_invalidate_fd(handle->loop, handle->io_watcher.fd);
-}
-
-
-int uv_poll_stop(uv_poll_t* handle) {
-  assert(!uv__is_closing(handle));
-  uv__poll_stop(handle);
-  return 0;
-}
-
-
-int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
-  int events;
-
-  assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT |
-                      UV_PRIORITIZED)) == 0);
-  assert(!uv__is_closing(handle));
-
-  uv__poll_stop(handle);
-
-  if (pevents == 0)
-    return 0;
-
-  events = 0;
-  if (pevents & UV_READABLE)
-    events |= POLLIN;
-  if (pevents & UV_PRIORITIZED)
-    events |= UV__POLLPRI;
-  if (pevents & UV_WRITABLE)
-    events |= POLLOUT;
-  if (pevents & UV_DISCONNECT)
-    events |= UV__POLLRDHUP;
-
-  uv__io_start(handle->loop, &handle->io_watcher, events);
-  uv__handle_start(handle);
-  handle->poll_cb = poll_cb;
-
-  return 0;
-}
-
-
-void uv__poll_close(uv_poll_t* handle) {
-  uv__poll_stop(handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/posix-hrtime.cpp b/wpiutil/src/main/native/libuv/src/unix/posix-hrtime.cpp
deleted file mode 100644
index 323dfc2..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/posix-hrtime.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stdint.h>
-#include <time.h>
-
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
-uint64_t uv__hrtime(uv_clocktype_t type) {
-  struct timespec ts;
-  clock_gettime(CLOCK_MONOTONIC, &ts);
-  return (((uint64_t) ts.tv_sec) * NANOSEC + ts.tv_nsec);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/posix-poll.cpp b/wpiutil/src/main/native/libuv/src/unix/posix-poll.cpp
deleted file mode 100644
index b932f91..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/posix-poll.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-/* POSIX defines poll() as a portable way to wait on file descriptors.
- * Here we maintain a dynamically sized array of file descriptors and
- * events to pass as the first argument to poll().
- */
-
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <errno.h>
-#include <unistd.h>
-
-int uv__platform_loop_init(uv_loop_t* loop) {
-  loop->poll_fds = NULL;
-  loop->poll_fds_used = 0;
-  loop->poll_fds_size = 0;
-  loop->poll_fds_iterating = 0;
-  return 0;
-}
-
-void uv__platform_loop_delete(uv_loop_t* loop) {
-  uv__free(loop->poll_fds);
-  loop->poll_fds = NULL;
-}
-
-int uv__io_fork(uv_loop_t* loop) {
-  uv__platform_loop_delete(loop);
-  return uv__platform_loop_init(loop);
-}
-
-/* Allocate or dynamically resize our poll fds array.  */
-static void uv__pollfds_maybe_resize(uv_loop_t* loop) {
-  size_t i;
-  size_t n;
-  struct pollfd* p;
-
-  if (loop->poll_fds_used < loop->poll_fds_size)
-    return;
-
-  n = loop->poll_fds_size ? loop->poll_fds_size * 2 : 64;
-  p = (struct pollfd*)uv__realloc(loop->poll_fds, n * sizeof(*loop->poll_fds));
-  if (p == NULL)
-    abort();
-
-  loop->poll_fds = p;
-  for (i = loop->poll_fds_size; i < n; i++) {
-    loop->poll_fds[i].fd = -1;
-    loop->poll_fds[i].events = 0;
-    loop->poll_fds[i].revents = 0;
-  }
-  loop->poll_fds_size = n;
-}
-
-/* Primitive swap operation on poll fds array elements.  */
-static void uv__pollfds_swap(uv_loop_t* loop, size_t l, size_t r) {
-  struct pollfd pfd;
-  pfd = loop->poll_fds[l];
-  loop->poll_fds[l] = loop->poll_fds[r];
-  loop->poll_fds[r] = pfd;
-}
-
-/* Add a watcher's fd to our poll fds array with its pending events.  */
-static void uv__pollfds_add(uv_loop_t* loop, uv__io_t* w) {
-  size_t i;
-  struct pollfd* pe;
-
-  /* If the fd is already in the set just update its events.  */
-  assert(!loop->poll_fds_iterating);
-  for (i = 0; i < loop->poll_fds_used; ++i) {
-    if (loop->poll_fds[i].fd == w->fd) {
-      loop->poll_fds[i].events = w->pevents;
-      return;
-    }
-  }
-
-  /* Otherwise, allocate a new slot in the set for the fd.  */
-  uv__pollfds_maybe_resize(loop);
-  pe = &loop->poll_fds[loop->poll_fds_used++];
-  pe->fd = w->fd;
-  pe->events = w->pevents;
-}
-
-/* Remove a watcher's fd from our poll fds array.  */
-static void uv__pollfds_del(uv_loop_t* loop, int fd) {
-  size_t i;
-  assert(!loop->poll_fds_iterating);
-  for (i = 0; i < loop->poll_fds_used;) {
-    if (loop->poll_fds[i].fd == fd) {
-      /* swap to last position and remove */
-      --loop->poll_fds_used;
-      uv__pollfds_swap(loop, i, loop->poll_fds_used);
-      loop->poll_fds[loop->poll_fds_used].fd = -1;
-      loop->poll_fds[loop->poll_fds_used].events = 0;
-      loop->poll_fds[loop->poll_fds_used].revents = 0;
-      /* This method is called with an fd of -1 to purge the invalidated fds,
-       * so we may possibly have multiples to remove.
-       */
-      if (-1 != fd)
-        return;
-    } else {
-      /* We must only increment the loop counter when the fds do not match.
-       * Otherwise, when we are purging an invalidated fd, the value just
-       * swapped here from the previous end of the array will be skipped.
-       */
-       ++i;
-    }
-  }
-}
-
-
-void uv__io_poll(uv_loop_t* loop, int timeout) {
-  sigset_t* pset;
-  sigset_t set;
-  uint64_t time_base;
-  uint64_t time_diff;
-  QUEUE* q;
-  uv__io_t* w;
-  size_t i;
-  unsigned int nevents;
-  int nfds;
-  int have_signals;
-  struct pollfd* pe;
-  int fd;
-
-  if (loop->nfds == 0) {
-    assert(QUEUE_EMPTY(&loop->watcher_queue));
-    return;
-  }
-
-  /* Take queued watchers and add their fds to our poll fds array.  */
-  while (!QUEUE_EMPTY(&loop->watcher_queue)) {
-    q = QUEUE_HEAD(&loop->watcher_queue);
-    QUEUE_REMOVE(q);
-    QUEUE_INIT(q);
-
-    w = QUEUE_DATA(q, uv__io_t, watcher_queue);
-    assert(w->pevents != 0);
-    assert(w->fd >= 0);
-    assert(w->fd < (int) loop->nwatchers);
-
-    uv__pollfds_add(loop, w);
-
-    w->events = w->pevents;
-  }
-
-  /* Prepare a set of signals to block around poll(), if any.  */
-  pset = NULL;
-  if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
-    pset = &set;
-    sigemptyset(pset);
-    sigaddset(pset, SIGPROF);
-  }
-
-  assert(timeout >= -1);
-  time_base = loop->time;
-
-  /* Loop calls to poll() and processing of results.  If we get some
-   * results from poll() but they turn out not to be interesting to
-   * our caller then we need to loop around and poll() again.
-   */
-  for (;;) {
-    if (pset != NULL)
-      if (pthread_sigmask(SIG_BLOCK, pset, NULL))
-        abort();
-    nfds = poll(loop->poll_fds, (nfds_t)loop->poll_fds_used, timeout);
-    if (pset != NULL)
-      if (pthread_sigmask(SIG_UNBLOCK, pset, NULL))
-        abort();
-
-    /* Update loop->time unconditionally. It's tempting to skip the update when
-     * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
-     * operating system didn't reschedule our process while in the syscall.
-     */
-    SAVE_ERRNO(uv__update_time(loop));
-
-    if (nfds == 0) {
-      assert(timeout != -1);
-      return;
-    }
-
-    if (nfds == -1) {
-      if (errno != EINTR)
-        abort();
-
-      if (timeout == -1)
-        continue;
-
-      if (timeout == 0)
-        return;
-
-      /* Interrupted by a signal. Update timeout and poll again. */
-      goto update_timeout;
-    }
-
-    /* Tell uv__platform_invalidate_fd not to manipulate our array
-     * while we are iterating over it.
-     */
-    loop->poll_fds_iterating = 1;
-
-    /* Initialize a count of events that we care about.  */
-    nevents = 0;
-    have_signals = 0;
-
-    /* Loop over the entire poll fds array looking for returned events.  */
-    for (i = 0; i < loop->poll_fds_used; i++) {
-      pe = loop->poll_fds + i;
-      fd = pe->fd;
-
-      /* Skip invalidated events, see uv__platform_invalidate_fd.  */
-      if (fd == -1)
-        continue;
-
-      assert(fd >= 0);
-      assert((unsigned) fd < loop->nwatchers);
-
-      w = loop->watchers[fd];
-
-      if (w == NULL) {
-        /* File descriptor that we've stopped watching, ignore.  */
-        uv__platform_invalidate_fd(loop, fd);
-        continue;
-      }
-
-      /* Filter out events that user has not requested us to watch
-       * (e.g. POLLNVAL).
-       */
-      pe->revents &= w->pevents | POLLERR | POLLHUP;
-
-      if (pe->revents != 0) {
-        /* Run signal watchers last.  */
-        if (w == &loop->signal_io_watcher) {
-          have_signals = 1;
-        } else {
-          w->cb(loop, w, pe->revents);
-        }
-
-        nevents++;
-      }
-    }
-
-    if (have_signals != 0)
-      loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
-
-    loop->poll_fds_iterating = 0;
-
-    /* Purge invalidated fds from our poll fds array.  */
-    uv__pollfds_del(loop, -1);
-
-    if (have_signals != 0)
-      return;  /* Event loop should cycle now so don't poll again. */
-
-    if (nevents != 0)
-      return;
-
-    if (timeout == 0)
-      return;
-
-    if (timeout == -1)
-      continue;
-
-update_timeout:
-    assert(timeout > 0);
-
-    time_diff = loop->time - time_base;
-    if (time_diff >= (uint64_t) timeout)
-      return;
-
-    timeout -= time_diff;
-  }
-}
-
-/* Remove the given fd from our poll fds array because no one
- * is interested in its events anymore.
- */
-void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
-  size_t i;
-
-  assert(fd >= 0);
-
-  if (loop->poll_fds_iterating) {
-    /* uv__io_poll is currently iterating.  Just invalidate fd.  */
-    for (i = 0; i < loop->poll_fds_used; i++)
-      if (loop->poll_fds[i].fd == fd) {
-        loop->poll_fds[i].fd = -1;
-        loop->poll_fds[i].events = 0;
-        loop->poll_fds[i].revents = 0;
-      }
-  } else {
-    /* uv__io_poll is not iterating.  Delete fd from the set.  */
-    uv__pollfds_del(loop, fd);
-  }
-}
-
-/* Check whether the given fd is supported by poll().  */
-int uv__io_check_fd(uv_loop_t* loop, int fd) {
-  struct pollfd p[1];
-  int rv;
-
-  p[0].fd = fd;
-  p[0].events = POLLIN;
-
-  do
-    rv = poll(p, 1, 0);
-  while (rv == -1 && (errno == EINTR || errno == EAGAIN));
-
-  if (rv == -1)
-    return UV__ERR(errno);
-
-  if (p[0].revents & POLLNVAL)
-    return UV_EINVAL;
-
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/process.cpp b/wpiutil/src/main/native/libuv/src/unix/process.cpp
deleted file mode 100644
index 87dac7f..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/process.cpp
+++ /dev/null
@@ -1,603 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <poll.h>
-
-#if defined(__APPLE__) && !TARGET_OS_IPHONE
-# include <crt_externs.h>
-# define environ (*_NSGetEnviron())
-#else
-extern char **environ;
-#endif
-
-#if defined(__linux__) || defined(__GLIBC__)
-# include <grp.h>
-#endif
-
-
-static void uv__chld(uv_signal_t* handle, int signum) {
-  uv_process_t* process;
-  uv_loop_t* loop;
-  int exit_status;
-  int term_signal;
-  int status;
-  pid_t pid;
-  QUEUE pending;
-  QUEUE* q;
-  QUEUE* h;
-
-  assert(signum == SIGCHLD);
-
-  QUEUE_INIT(&pending);
-  loop = handle->loop;
-
-  h = &loop->process_handles;
-  q = QUEUE_HEAD(h);
-  while (q != h) {
-    process = QUEUE_DATA(q, uv_process_t, queue);
-    q = QUEUE_NEXT(q);
-
-    do
-      pid = waitpid(process->pid, &status, WNOHANG);
-    while (pid == -1 && errno == EINTR);
-
-    if (pid == 0)
-      continue;
-
-    if (pid == -1) {
-      if (errno != ECHILD)
-        abort();
-      continue;
-    }
-
-    process->status = status;
-    QUEUE_REMOVE(&process->queue);
-    QUEUE_INSERT_TAIL(&pending, &process->queue);
-  }
-
-  h = &pending;
-  q = QUEUE_HEAD(h);
-  while (q != h) {
-    process = QUEUE_DATA(q, uv_process_t, queue);
-    q = QUEUE_NEXT(q);
-
-    QUEUE_REMOVE(&process->queue);
-    QUEUE_INIT(&process->queue);
-    uv__handle_stop(process);
-
-    if (process->exit_cb == NULL)
-      continue;
-
-    exit_status = 0;
-    if (WIFEXITED(process->status))
-      exit_status = WEXITSTATUS(process->status);
-
-    term_signal = 0;
-    if (WIFSIGNALED(process->status))
-      term_signal = WTERMSIG(process->status);
-
-    process->exit_cb(process, exit_status, term_signal);
-  }
-  assert(QUEUE_EMPTY(&pending));
-}
-
-
-int uv__make_socketpair(int fds[2], int flags) {
-#if defined(__linux__)
-  static int no_cloexec;
-
-  if (no_cloexec)
-    goto skip;
-
-  if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0)
-    return 0;
-
-  /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported.
-   * Anything else is a genuine error.
-   */
-  if (errno != EINVAL)
-    return UV__ERR(errno);
-
-  no_cloexec = 1;
-
-skip:
-#endif
-
-  if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
-    return UV__ERR(errno);
-
-  uv__cloexec(fds[0], 1);
-  uv__cloexec(fds[1], 1);
-
-  if (flags & UV__F_NONBLOCK) {
-    uv__nonblock(fds[0], 1);
-    uv__nonblock(fds[1], 1);
-  }
-
-  return 0;
-}
-
-
-int uv__make_pipe(int fds[2], int flags) {
-#if defined(__linux__)
-  static int no_pipe2;
-
-  if (no_pipe2)
-    goto skip;
-
-  if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0)
-    return 0;
-
-  if (errno != ENOSYS)
-    return UV__ERR(errno);
-
-  no_pipe2 = 1;
-
-skip:
-#endif
-
-  if (pipe(fds))
-    return UV__ERR(errno);
-
-  uv__cloexec(fds[0], 1);
-  uv__cloexec(fds[1], 1);
-
-  if (flags & UV__F_NONBLOCK) {
-    uv__nonblock(fds[0], 1);
-    uv__nonblock(fds[1], 1);
-  }
-
-  return 0;
-}
-
-
-/*
- * Used for initializing stdio streams like options.stdin_stream. Returns
- * zero on success. See also the cleanup section in uv_spawn().
- */
-static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
-  int mask;
-  int fd;
-
-  mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM;
-
-  switch (container->flags & mask) {
-  case UV_IGNORE:
-    return 0;
-
-  case UV_CREATE_PIPE:
-    assert(container->data.stream != NULL);
-    if (container->data.stream->type != UV_NAMED_PIPE)
-      return UV_EINVAL;
-    else
-      return uv__make_socketpair(fds, 0);
-
-  case UV_INHERIT_FD:
-  case UV_INHERIT_STREAM:
-    if (container->flags & UV_INHERIT_FD)
-      fd = container->data.fd;
-    else
-      fd = uv__stream_fd(container->data.stream);
-
-    if (fd == -1)
-      return UV_EINVAL;
-
-    fds[1] = fd;
-    return 0;
-
-  default:
-    assert(0 && "Unexpected flags");
-    return UV_EINVAL;
-  }
-}
-
-
-static int uv__process_open_stream(uv_stdio_container_t* container,
-                                   int pipefds[2]) {
-  int flags;
-  int err;
-
-  if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0)
-    return 0;
-
-  err = uv__close(pipefds[1]);
-  if (err != 0)
-    abort();
-
-  pipefds[1] = -1;
-  uv__nonblock(pipefds[0], 1);
-
-  flags = 0;
-  if (container->flags & UV_WRITABLE_PIPE)
-    flags |= UV_HANDLE_READABLE;
-  if (container->flags & UV_READABLE_PIPE)
-    flags |= UV_HANDLE_WRITABLE;
-
-  return uv__stream_open(container->data.stream, pipefds[0], flags);
-}
-
-
-static void uv__process_close_stream(uv_stdio_container_t* container) {
-  if (!(container->flags & UV_CREATE_PIPE)) return;
-  uv__stream_close(container->data.stream);
-}
-
-
-static void uv__write_int(int fd, int val) {
-  ssize_t n;
-
-  do
-    n = write(fd, &val, sizeof(val));
-  while (n == -1 && errno == EINTR);
-
-  if (n == -1 && errno == EPIPE)
-    return; /* parent process has quit */
-
-  assert(n == sizeof(val));
-}
-
-
-#if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH))
-/* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be
- * avoided. Since this isn't called on those targets, the function
- * doesn't even need to be defined for them.
- */
-static void uv__process_child_init(const uv_process_options_t* options,
-                                   int stdio_count,
-                                   int (*pipes)[2],
-                                   int error_fd) {
-  sigset_t set;
-  int close_fd;
-  int use_fd;
-  int err;
-  int fd;
-  int n;
-
-  if (options->flags & UV_PROCESS_DETACHED)
-    setsid();
-
-  /* First duplicate low numbered fds, since it's not safe to duplicate them,
-   * they could get replaced. Example: swapping stdout and stderr; without
-   * this fd 2 (stderr) would be duplicated into fd 1, thus making both
-   * stdout and stderr go to the same fd, which was not the intention. */
-  for (fd = 0; fd < stdio_count; fd++) {
-    use_fd = pipes[fd][1];
-    if (use_fd < 0 || use_fd >= fd)
-      continue;
-    pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
-    if (pipes[fd][1] == -1) {
-      uv__write_int(error_fd, UV__ERR(errno));
-      _exit(127);
-    }
-  }
-
-  for (fd = 0; fd < stdio_count; fd++) {
-    close_fd = pipes[fd][0];
-    use_fd = pipes[fd][1];
-
-    if (use_fd < 0) {
-      if (fd >= 3)
-        continue;
-      else {
-        /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
-         * set
-         */
-        use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
-        close_fd = use_fd;
-
-        if (use_fd < 0) {
-          uv__write_int(error_fd, UV__ERR(errno));
-          _exit(127);
-        }
-      }
-    }
-
-    if (fd == use_fd)
-      uv__cloexec_fcntl(use_fd, 0);
-    else
-      fd = dup2(use_fd, fd);
-
-    if (fd == -1) {
-      uv__write_int(error_fd, UV__ERR(errno));
-      _exit(127);
-    }
-
-    if (fd <= 2)
-      uv__nonblock_fcntl(fd, 0);
-
-    if (close_fd >= stdio_count)
-      uv__close(close_fd);
-  }
-
-  for (fd = 0; fd < stdio_count; fd++) {
-    use_fd = pipes[fd][1];
-
-    if (use_fd >= stdio_count)
-      uv__close(use_fd);
-  }
-
-  if (options->cwd != NULL && chdir(options->cwd)) {
-    uv__write_int(error_fd, UV__ERR(errno));
-    _exit(127);
-  }
-
-  if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
-    /* When dropping privileges from root, the `setgroups` call will
-     * remove any extraneous groups. If we don't call this, then
-     * even though our uid has dropped, we may still have groups
-     * that enable us to do super-user things. This will fail if we
-     * aren't root, so don't bother checking the return value, this
-     * is just done as an optimistic privilege dropping function.
-     */
-    SAVE_ERRNO(setgroups(0, NULL));
-  }
-
-  if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
-    uv__write_int(error_fd, UV__ERR(errno));
-    _exit(127);
-  }
-
-  if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
-    uv__write_int(error_fd, UV__ERR(errno));
-    _exit(127);
-  }
-
-  if (options->env != NULL) {
-    environ = options->env;
-  }
-
-  /* Reset signal disposition.  Use a hard-coded limit because NSIG
-   * is not fixed on Linux: it's either 32, 34 or 64, depending on
-   * whether RT signals are enabled.  We are not allowed to touch
-   * RT signal handlers, glibc uses them internally.
-   */
-  for (n = 1; n < 32; n += 1) {
-    if (n == SIGKILL || n == SIGSTOP)
-      continue;  /* Can't be changed. */
-
-#if defined(__HAIKU__)
-    if (n == SIGKILLTHR)
-      continue;  /* Can't be changed. */
-#endif
-
-    if (SIG_ERR != signal(n, SIG_DFL))
-      continue;
-
-    uv__write_int(error_fd, UV__ERR(errno));
-    _exit(127);
-  }
-
-  /* Reset signal mask. */
-  sigemptyset(&set);
-  err = pthread_sigmask(SIG_SETMASK, &set, NULL);
-
-  if (err != 0) {
-    uv__write_int(error_fd, UV__ERR(err));
-    _exit(127);
-  }
-
-  execvp(options->file, options->args);
-  uv__write_int(error_fd, UV__ERR(errno));
-  _exit(127);
-}
-#endif
-
-
-int uv_spawn(uv_loop_t* loop,
-             uv_process_t* process,
-             const uv_process_options_t* options) {
-#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
-  /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
-  return UV_ENOSYS;
-#else
-  int signal_pipe[2] = { -1, -1 };
-  int pipes_storage[8][2];
-  int (*pipes)[2];
-  int stdio_count;
-  ssize_t r;
-  pid_t pid;
-  int err;
-  int exec_errorno;
-  int i;
-  int status;
-
-  assert(options->file != NULL);
-  assert(!(options->flags & ~(UV_PROCESS_DETACHED |
-                              UV_PROCESS_SETGID |
-                              UV_PROCESS_SETUID |
-                              UV_PROCESS_WINDOWS_HIDE |
-                              UV_PROCESS_WINDOWS_HIDE_CONSOLE |
-                              UV_PROCESS_WINDOWS_HIDE_GUI |
-                              UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
-
-  uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
-  QUEUE_INIT(&process->queue);
-
-  stdio_count = options->stdio_count;
-  if (stdio_count < 3)
-    stdio_count = 3;
-
-  err = UV_ENOMEM;
-  pipes = pipes_storage;
-  if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
-    pipes = (int (*)[2])uv__malloc(stdio_count * sizeof(*pipes));
-
-  if (pipes == NULL)
-    goto error;
-
-  for (i = 0; i < stdio_count; i++) {
-    pipes[i][0] = -1;
-    pipes[i][1] = -1;
-  }
-
-  for (i = 0; i < options->stdio_count; i++) {
-    err = uv__process_init_stdio(options->stdio + i, pipes[i]);
-    if (err)
-      goto error;
-  }
-
-  /* This pipe is used by the parent to wait until
-   * the child has called `execve()`. We need this
-   * to avoid the following race condition:
-   *
-   *    if ((pid = fork()) > 0) {
-   *      kill(pid, SIGTERM);
-   *    }
-   *    else if (pid == 0) {
-   *      execve("/bin/cat", argp, envp);
-   *    }
-   *
-   * The parent sends a signal immediately after forking.
-   * Since the child may not have called `execve()` yet,
-   * there is no telling what process receives the signal,
-   * our fork or /bin/cat.
-   *
-   * To avoid ambiguity, we create a pipe with both ends
-   * marked close-on-exec. Then, after the call to `fork()`,
-   * the parent polls the read end until it EOFs or errors with EPIPE.
-   */
-  err = uv__make_pipe(signal_pipe, 0);
-  if (err)
-    goto error;
-
-  uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
-
-  /* Acquire write lock to prevent opening new fds in worker threads */
-  uv_rwlock_wrlock(&loop->cloexec_lock);
-  pid = fork();
-
-  if (pid == -1) {
-    err = UV__ERR(errno);
-    uv_rwlock_wrunlock(&loop->cloexec_lock);
-    uv__close(signal_pipe[0]);
-    uv__close(signal_pipe[1]);
-    goto error;
-  }
-
-  if (pid == 0) {
-    uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]);
-    abort();
-  }
-
-  /* Release lock in parent process */
-  uv_rwlock_wrunlock(&loop->cloexec_lock);
-  uv__close(signal_pipe[1]);
-
-  process->status = 0;
-  exec_errorno = 0;
-  do
-    r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno));
-  while (r == -1 && errno == EINTR);
-
-  if (r == 0)
-    ; /* okay, EOF */
-  else if (r == sizeof(exec_errorno)) {
-    do
-      err = waitpid(pid, &status, 0); /* okay, read errorno */
-    while (err == -1 && errno == EINTR);
-    assert(err == pid);
-  } else if (r == -1 && errno == EPIPE) {
-    do
-      err = waitpid(pid, &status, 0); /* okay, got EPIPE */
-    while (err == -1 && errno == EINTR);
-    assert(err == pid);
-  } else
-    abort();
-
-  uv__close_nocheckstdio(signal_pipe[0]);
-
-  for (i = 0; i < options->stdio_count; i++) {
-    err = uv__process_open_stream(options->stdio + i, pipes[i]);
-    if (err == 0)
-      continue;
-
-    while (i--)
-      uv__process_close_stream(options->stdio + i);
-
-    goto error;
-  }
-
-  /* Only activate this handle if exec() happened successfully */
-  if (exec_errorno == 0) {
-    QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue);
-    uv__handle_start(process);
-  }
-
-  process->pid = pid;
-  process->exit_cb = options->exit_cb;
-
-  if (pipes != pipes_storage)
-    uv__free(pipes);
-
-  return exec_errorno;
-
-error:
-  if (pipes != NULL) {
-    for (i = 0; i < stdio_count; i++) {
-      if (i < options->stdio_count)
-        if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM))
-          continue;
-      if (pipes[i][0] != -1)
-        uv__close_nocheckstdio(pipes[i][0]);
-      if (pipes[i][1] != -1)
-        uv__close_nocheckstdio(pipes[i][1]);
-    }
-
-    if (pipes != pipes_storage)
-      uv__free(pipes);
-  }
-
-  return err;
-#endif
-}
-
-
-int uv_process_kill(uv_process_t* process, int signum) {
-  return uv_kill(process->pid, signum);
-}
-
-
-int uv_kill(int pid, int signum) {
-  if (kill(pid, signum))
-    return UV__ERR(errno);
-  else
-    return 0;
-}
-
-
-void uv__process_close(uv_process_t* handle) {
-  QUEUE_REMOVE(&handle->queue);
-  uv__handle_stop(handle);
-  if (QUEUE_EMPTY(&handle->loop->process_handles))
-    uv_signal_stop(&handle->loop->child_watcher);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/procfs-exepath.cpp b/wpiutil/src/main/native/libuv/src/unix/procfs-exepath.cpp
deleted file mode 100644
index 00dc021..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/procfs-exepath.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stddef.h>
-#include <unistd.h>
-
-int uv_exepath(char* buffer, size_t* size) {
-  ssize_t n;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  n = *size - 1;
-  if (n > 0)
-    n = readlink("/proc/self/exe", buffer, n);
-
-  if (n == -1)
-    return UV__ERR(errno);
-
-  buffer[n] = '\0';
-  *size = n;
-
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/proctitle.cpp b/wpiutil/src/main/native/libuv/src/unix/proctitle.cpp
deleted file mode 100644
index b09808f..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/proctitle.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-extern void uv__set_process_title_platform_init(void);
-extern void uv__set_process_title(const char* title);
-
-static uv_mutex_t process_title_mutex;
-static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
-static void* args_mem;
-
-static struct {
-  char* str;
-  size_t len;
-} process_title;
-
-
-static void init_process_title_mutex_once(void) {
-  uv_mutex_init(&process_title_mutex);
-#ifdef __APPLE__
-  uv__set_process_title_platform_init();
-#endif
-}
-
-
-char** uv_setup_args(int argc, char** argv) {
-  char** new_argv;
-  size_t size;
-  char* s;
-  int i;
-
-  if (argc <= 0)
-    return argv;
-
-  /* Calculate how much memory we need for the argv strings. */
-  size = 0;
-  for (i = 0; i < argc; i++)
-    size += strlen(argv[i]) + 1;
-
-#if defined(__MVS__)
-  /* argv is not adjacent. So just use argv[0] */
-  process_title.str = argv[0];
-  process_title.len = strlen(argv[0]);
-#else
-  process_title.str = argv[0];
-  process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0];
-  assert(process_title.len + 1 == size);  /* argv memory should be adjacent. */
-#endif
-
-  /* Add space for the argv pointers. */
-  size += (argc + 1) * sizeof(char*);
-
-  new_argv = (char**)uv__malloc(size);
-  if (new_argv == NULL)
-    return argv;
-  args_mem = new_argv;
-
-  /* Copy over the strings and set up the pointer table. */
-  s = (char*) &new_argv[argc + 1];
-  for (i = 0; i < argc; i++) {
-    size = strlen(argv[i]) + 1;
-    memcpy(s, argv[i], size);
-    new_argv[i] = s;
-    s += size;
-  }
-  new_argv[i] = NULL;
-
-  return new_argv;
-}
-
-
-int uv_set_process_title(const char* title) {
-  uv_once(&process_title_mutex_once, init_process_title_mutex_once);
-  uv_mutex_lock(&process_title_mutex);
-
-  if (process_title.len != 0) {
-    /* No need to terminate, byte after is always '\0'. */
-    strncpy(process_title.str, title, process_title.len);
-    uv__set_process_title(title);
-  }
-
-  uv_mutex_unlock(&process_title_mutex);
-
-  return 0;
-}
-
-
-int uv_get_process_title(char* buffer, size_t size) {
-  if (buffer == NULL || size == 0)
-    return UV_EINVAL;
-
-  uv_once(&process_title_mutex_once, init_process_title_mutex_once);
-  uv_mutex_lock(&process_title_mutex);
-
-  if (size <= process_title.len) {
-    uv_mutex_unlock(&process_title_mutex);
-    return UV_ENOBUFS;
-  }
-
-  if (process_title.len != 0)
-    memcpy(buffer, process_title.str, process_title.len + 1);
-
-  buffer[process_title.len] = '\0';
-
-  uv_mutex_unlock(&process_title_mutex);
-
-  return 0;
-}
-
-
-UV_DESTRUCTOR(static void free_args_mem(void)) {
-  uv__free(args_mem);  /* Keep valgrind happy. */
-  args_mem = NULL;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/pthread-fixes.cpp b/wpiutil/src/main/native/libuv/src/unix/pthread-fixes.cpp
deleted file mode 100644
index fb17995..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/pthread-fixes.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (c) 2013, Sony Mobile Communications AB
- * Copyright (c) 2012, Google Inc.
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are
-   met:
-
-     * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-       * Redistributions in binary form must reproduce the above
-   copyright notice, this list of conditions and the following disclaimer
-   in the documentation and/or other materials provided with the
-   distribution.
-       * Neither the name of Google Inc. nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* Android versions < 4.1 have a broken pthread_sigmask. */
-#include <errno.h>
-#include <pthread.h>
-#include <signal.h>
-
-int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset) {
-  static int workaround;
-  int err;
-
-  if (workaround) {
-    return sigprocmask(how, set, oset);
-  } else {
-    err = pthread_sigmask(how, set, oset);
-    if (err) {
-      if (err == EINVAL && sigprocmask(how, set, oset) == 0) {
-        workaround = 1;
-        return 0;
-      } else {
-        return -1;
-      }
-    }
-  }
-
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/signal.cpp b/wpiutil/src/main/native/libuv/src/unix/signal.cpp
deleted file mode 100644
index ec2639a..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/signal.cpp
+++ /dev/null
@@ -1,574 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifndef SA_RESTART
-# define SA_RESTART 0
-#endif
-
-typedef struct {
-  uv_signal_t* handle;
-  int signum;
-} uv__signal_msg_t;
-
-RB_HEAD(uv__signal_tree_s, uv_signal_s);
-
-
-static int uv__signal_unlock(void);
-static int uv__signal_start(uv_signal_t* handle,
-                            uv_signal_cb signal_cb,
-                            int signum,
-                            int oneshot);
-static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events);
-static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
-static void uv__signal_stop(uv_signal_t* handle);
-static void uv__signal_unregister_handler(int signum);
-
-
-static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
-static struct uv__signal_tree_s uv__signal_tree =
-    RB_INITIALIZER(uv__signal_tree);
-static int uv__signal_lock_pipefd[2] = { -1, -1 };
-
-RB_GENERATE_STATIC(uv__signal_tree_s,
-                   uv_signal_s, tree_entry,
-                   uv__signal_compare)
-
-static void uv__signal_global_reinit(void);
-
-static void uv__signal_global_init(void) {
-  if (uv__signal_lock_pipefd[0] == -1)
-    /* pthread_atfork can register before and after handlers, one
-     * for each child. This only registers one for the child. That
-     * state is both persistent and cumulative, so if we keep doing
-     * it the handler functions will be called multiple times. Thus
-     * we only want to do it once.
-     */
-    if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit))
-      abort();
-
-  uv__signal_global_reinit();
-}
-
-
-UV_DESTRUCTOR(static void uv__signal_global_fini(void)) {
-  /* We can only use signal-safe functions here.
-   * That includes read/write and close, fortunately.
-   * We do all of this directly here instead of resetting
-   * uv__signal_global_init_guard because
-   * uv__signal_global_once_init is only called from uv_loop_init
-   * and this needs to function in existing loops.
-   */
-  if (uv__signal_lock_pipefd[0] != -1) {
-    uv__close(uv__signal_lock_pipefd[0]);
-    uv__signal_lock_pipefd[0] = -1;
-  }
-
-  if (uv__signal_lock_pipefd[1] != -1) {
-    uv__close(uv__signal_lock_pipefd[1]);
-    uv__signal_lock_pipefd[1] = -1;
-  }
-}
-
-
-static void uv__signal_global_reinit(void) {
-  uv__signal_global_fini();
-
-  if (uv__make_pipe(uv__signal_lock_pipefd, 0))
-    abort();
-
-  if (uv__signal_unlock())
-    abort();
-}
-
-
-void uv__signal_global_once_init(void) {
-  uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
-}
-
-
-static int uv__signal_lock(void) {
-  int r;
-  char data;
-
-  do {
-    r = read(uv__signal_lock_pipefd[0], &data, sizeof data);
-  } while (r < 0 && errno == EINTR);
-
-  return (r < 0) ? -1 : 0;
-}
-
-
-static int uv__signal_unlock(void) {
-  int r;
-  char data = 42;
-
-  do {
-    r = write(uv__signal_lock_pipefd[1], &data, sizeof data);
-  } while (r < 0 && errno == EINTR);
-
-  return (r < 0) ? -1 : 0;
-}
-
-
-static void uv__signal_block_and_lock(sigset_t* saved_sigmask) {
-  sigset_t new_mask;
-
-  if (sigfillset(&new_mask))
-    abort();
-
-  if (pthread_sigmask(SIG_SETMASK, &new_mask, saved_sigmask))
-    abort();
-
-  if (uv__signal_lock())
-    abort();
-}
-
-
-static void uv__signal_unlock_and_unblock(sigset_t* saved_sigmask) {
-  if (uv__signal_unlock())
-    abort();
-
-  if (pthread_sigmask(SIG_SETMASK, saved_sigmask, NULL))
-    abort();
-}
-
-
-static uv_signal_t* uv__signal_first_handle(int signum) {
-  /* This function must be called with the signal lock held. */
-  uv_signal_t lookup;
-  uv_signal_t* handle;
-
-  lookup.signum = signum;
-  lookup.flags = 0;
-  lookup.loop = NULL;
-
-  handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup);
-
-  if (handle != NULL && handle->signum == signum)
-    return handle;
-
-  return NULL;
-}
-
-
-static void uv__signal_handler(int signum) {
-  uv__signal_msg_t msg;
-  uv_signal_t* handle;
-  int saved_errno;
-
-  saved_errno = errno;
-  memset(&msg, 0, sizeof msg);
-
-  if (uv__signal_lock()) {
-    errno = saved_errno;
-    return;
-  }
-
-  for (handle = uv__signal_first_handle(signum);
-       handle != NULL && handle->signum == signum;
-       handle = RB_NEXT(uv__signal_tree_s, &uv__signal_tree, handle)) {
-    int r;
-
-    msg.signum = signum;
-    msg.handle = handle;
-
-    /* write() should be atomic for small data chunks, so the entire message
-     * should be written at once. In theory the pipe could become full, in
-     * which case the user is out of luck.
-     */
-    do {
-      r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg);
-    } while (r == -1 && errno == EINTR);
-
-    assert(r == sizeof msg ||
-           (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)));
-
-    if (r != -1)
-      handle->caught_signals++;
-  }
-
-  uv__signal_unlock();
-  errno = saved_errno;
-}
-
-
-static int uv__signal_register_handler(int signum, int oneshot) {
-  /* When this function is called, the signal lock must be held. */
-  struct sigaction sa;
-
-  /* XXX use a separate signal stack? */
-  memset(&sa, 0, sizeof(sa));
-  if (sigfillset(&sa.sa_mask))
-    abort();
-  sa.sa_handler = uv__signal_handler;
-  sa.sa_flags = SA_RESTART;
-  if (oneshot)
-    sa.sa_flags |= SA_RESETHAND;
-
-  /* XXX save old action so we can restore it later on? */
-  if (sigaction(signum, &sa, NULL))
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-
-static void uv__signal_unregister_handler(int signum) {
-  /* When this function is called, the signal lock must be held. */
-  struct sigaction sa;
-
-  memset(&sa, 0, sizeof(sa));
-  sa.sa_handler = SIG_DFL;
-
-  /* sigaction can only fail with EINVAL or EFAULT; an attempt to deregister a
-   * signal implies that it was successfully registered earlier, so EINVAL
-   * should never happen.
-   */
-  if (sigaction(signum, &sa, NULL))
-    abort();
-}
-
-
-static int uv__signal_loop_once_init(uv_loop_t* loop) {
-  int err;
-
-  /* Return if already initialized. */
-  if (loop->signal_pipefd[0] != -1)
-    return 0;
-
-  err = uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK);
-  if (err)
-    return err;
-
-  uv__io_init(&loop->signal_io_watcher,
-              uv__signal_event,
-              loop->signal_pipefd[0]);
-  uv__io_start(loop, &loop->signal_io_watcher, POLLIN);
-
-  return 0;
-}
-
-
-int uv__signal_loop_fork(uv_loop_t* loop) {
-  uv__io_stop(loop, &loop->signal_io_watcher, POLLIN);
-  uv__close(loop->signal_pipefd[0]);
-  uv__close(loop->signal_pipefd[1]);
-  loop->signal_pipefd[0] = -1;
-  loop->signal_pipefd[1] = -1;
-  return uv__signal_loop_once_init(loop);
-}
-
-
-void uv__signal_loop_cleanup(uv_loop_t* loop) {
-  QUEUE* q;
-
-  /* Stop all the signal watchers that are still attached to this loop. This
-   * ensures that the (shared) signal tree doesn't contain any invalid entries
-   * entries, and that signal handlers are removed when appropriate.
-   * It's safe to use QUEUE_FOREACH here because the handles and the handle
-   * queue are not modified by uv__signal_stop().
-   */
-  QUEUE_FOREACH(q, &loop->handle_queue) {
-    uv_handle_t* handle = QUEUE_DATA(q, uv_handle_t, handle_queue);
-
-    if (handle->type == UV_SIGNAL)
-      uv__signal_stop((uv_signal_t*) handle);
-  }
-
-  if (loop->signal_pipefd[0] != -1) {
-    uv__close(loop->signal_pipefd[0]);
-    loop->signal_pipefd[0] = -1;
-  }
-
-  if (loop->signal_pipefd[1] != -1) {
-    uv__close(loop->signal_pipefd[1]);
-    loop->signal_pipefd[1] = -1;
-  }
-}
-
-
-int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
-  int err;
-
-  err = uv__signal_loop_once_init(loop);
-  if (err)
-    return err;
-
-  uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
-  handle->signum = 0;
-  handle->caught_signals = 0;
-  handle->dispatched_signals = 0;
-
-  return 0;
-}
-
-
-void uv__signal_close(uv_signal_t* handle) {
-
-  uv__signal_stop(handle);
-
-  /* If there are any caught signals "trapped" in the signal pipe, we can't
-   * call the close callback yet. Otherwise, add the handle to the finish_close
-   * queue.
-   */
-  if (handle->caught_signals == handle->dispatched_signals) {
-    uv__make_close_pending((uv_handle_t*) handle);
-  }
-}
-
-
-int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
-  return uv__signal_start(handle, signal_cb, signum, 0);
-}
-
-
-int uv_signal_start_oneshot(uv_signal_t* handle,
-                            uv_signal_cb signal_cb,
-                            int signum) {
-  return uv__signal_start(handle, signal_cb, signum, 1);
-}
-
-
-static int uv__signal_start(uv_signal_t* handle,
-                            uv_signal_cb signal_cb,
-                            int signum,
-                            int oneshot) {
-  sigset_t saved_sigmask;
-  int err;
-  uv_signal_t* first_handle;
-
-  assert(!uv__is_closing(handle));
-
-  /* If the user supplies signum == 0, then return an error already. If the
-   * signum is otherwise invalid then uv__signal_register will find out
-   * eventually.
-   */
-  if (signum == 0)
-    return UV_EINVAL;
-
-  /* Short circuit: if the signal watcher is already watching {signum} don't
-   * go through the process of deregistering and registering the handler.
-   * Additionally, this avoids pending signals getting lost in the small
-   * time frame that handle->signum == 0.
-   */
-  if (signum == handle->signum) {
-    handle->signal_cb = signal_cb;
-    return 0;
-  }
-
-  /* If the signal handler was already active, stop it first. */
-  if (handle->signum != 0) {
-    uv__signal_stop(handle);
-  }
-
-  uv__signal_block_and_lock(&saved_sigmask);
-
-  /* If at this point there are no active signal watchers for this signum (in
-   * any of the loops), it's time to try and register a handler for it here.
-   * Also in case there's only one-shot handlers and a regular handler comes in.
-   */
-  first_handle = uv__signal_first_handle(signum);
-  if (first_handle == NULL ||
-      (!oneshot && (first_handle->flags & UV_SIGNAL_ONE_SHOT))) {
-    err = uv__signal_register_handler(signum, oneshot);
-    if (err) {
-      /* Registering the signal handler failed. Must be an invalid signal. */
-      uv__signal_unlock_and_unblock(&saved_sigmask);
-      return err;
-    }
-  }
-
-  handle->signum = signum;
-  if (oneshot)
-    handle->flags |= UV_SIGNAL_ONE_SHOT;
-
-  RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
-
-  uv__signal_unlock_and_unblock(&saved_sigmask);
-
-  handle->signal_cb = signal_cb;
-  uv__handle_start(handle);
-
-  return 0;
-}
-
-
-static void uv__signal_event(uv_loop_t* loop,
-                             uv__io_t* w,
-                             unsigned int events) {
-  uv__signal_msg_t* msg;
-  uv_signal_t* handle;
-  char buf[sizeof(uv__signal_msg_t) * 32];
-  size_t bytes, end, i;
-  int r;
-
-  bytes = 0;
-  end = 0;
-
-  do {
-    r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes);
-
-    if (r == -1 && errno == EINTR)
-      continue;
-
-    if (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
-      /* If there are bytes in the buffer already (which really is extremely
-       * unlikely if possible at all) we can't exit the function here. We'll
-       * spin until more bytes are read instead.
-       */
-      if (bytes > 0)
-        continue;
-
-      /* Otherwise, there was nothing there. */
-      return;
-    }
-
-    /* Other errors really should never happen. */
-    if (r == -1)
-      abort();
-
-    bytes += r;
-
-    /* `end` is rounded down to a multiple of sizeof(uv__signal_msg_t). */
-    end = (bytes / sizeof(uv__signal_msg_t)) * sizeof(uv__signal_msg_t);
-
-    for (i = 0; i < end; i += sizeof(uv__signal_msg_t)) {
-      msg = (uv__signal_msg_t*) (buf + i);
-      handle = msg->handle;
-
-      if (msg->signum == handle->signum) {
-        assert(!(handle->flags & UV_HANDLE_CLOSING));
-        handle->signal_cb(handle, handle->signum);
-      }
-
-      handle->dispatched_signals++;
-
-      if (handle->flags & UV_SIGNAL_ONE_SHOT)
-        uv__signal_stop(handle);
-
-      /* If uv_close was called while there were caught signals that were not
-       * yet dispatched, the uv__finish_close was deferred. Make close pending
-       * now if this has happened.
-       */
-      if ((handle->flags & UV_HANDLE_CLOSING) &&
-          (handle->caught_signals == handle->dispatched_signals)) {
-        uv__make_close_pending((uv_handle_t*) handle);
-      }
-    }
-
-    bytes -= end;
-
-    /* If there are any "partial" messages left, move them to the start of the
-     * the buffer, and spin. This should not happen.
-     */
-    if (bytes) {
-      memmove(buf, buf + end, bytes);
-      continue;
-    }
-  } while (end == sizeof buf);
-}
-
-
-static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
-  int f1;
-  int f2;
-  /* Compare signums first so all watchers with the same signnum end up
-   * adjacent.
-   */
-  if (w1->signum < w2->signum) return -1;
-  if (w1->signum > w2->signum) return 1;
-
-  /* Handlers without UV_SIGNAL_ONE_SHOT set will come first, so if the first
-   * handler returned is a one-shot handler, the rest will be too.
-   */
-  f1 = w1->flags & UV_SIGNAL_ONE_SHOT;
-  f2 = w2->flags & UV_SIGNAL_ONE_SHOT;
-  if (f1 < f2) return -1;
-  if (f1 > f2) return 1;
-
-  /* Sort by loop pointer, so we can easily look up the first item after
-   * { .signum = x, .loop = NULL }.
-   */
-  if (w1->loop < w2->loop) return -1;
-  if (w1->loop > w2->loop) return 1;
-
-  if (w1 < w2) return -1;
-  if (w1 > w2) return 1;
-
-  return 0;
-}
-
-
-int uv_signal_stop(uv_signal_t* handle) {
-  assert(!uv__is_closing(handle));
-  uv__signal_stop(handle);
-  return 0;
-}
-
-
-static void uv__signal_stop(uv_signal_t* handle) {
-  uv_signal_t* removed_handle;
-  sigset_t saved_sigmask;
-  uv_signal_t* first_handle;
-  int rem_oneshot;
-  int first_oneshot;
-  int ret;
-
-  /* If the watcher wasn't started, this is a no-op. */
-  if (handle->signum == 0)
-    return;
-
-  uv__signal_block_and_lock(&saved_sigmask);
-
-  removed_handle = RB_REMOVE(uv__signal_tree_s, &uv__signal_tree, handle);
-  assert(removed_handle == handle);
-  (void) removed_handle;
-
-  /* Check if there are other active signal watchers observing this signal. If
-   * not, unregister the signal handler.
-   */
-  first_handle = uv__signal_first_handle(handle->signum);
-  if (first_handle == NULL) {
-    uv__signal_unregister_handler(handle->signum);
-  } else {
-    rem_oneshot = handle->flags & UV_SIGNAL_ONE_SHOT;
-    first_oneshot = first_handle->flags & UV_SIGNAL_ONE_SHOT;
-    if (first_oneshot && !rem_oneshot) {
-      ret = uv__signal_register_handler(handle->signum, 1);
-      assert(ret == 0);
-      (void) ret;
-    }
-  }
-
-  uv__signal_unlock_and_unblock(&saved_sigmask);
-
-  handle->signum = 0;
-  uv__handle_stop(handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/spinlock.h b/wpiutil/src/main/native/libuv/src/unix/spinlock.h
deleted file mode 100644
index a20c83c..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/spinlock.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef UV_SPINLOCK_H_
-#define UV_SPINLOCK_H_
-
-#include "internal.h"  /* ACCESS_ONCE, UV_UNUSED */
-#include "atomic-ops.h"
-
-#define UV_SPINLOCK_INITIALIZER { 0 }
-
-typedef struct {
-  int lock;
-} uv_spinlock_t;
-
-UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock));
-UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock));
-UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock));
-UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock));
-
-UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)) {
-  ACCESS_ONCE(int, spinlock->lock) = 0;
-}
-
-UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)) {
-  while (!uv_spinlock_trylock(spinlock)) cpu_relax();
-}
-
-UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)) {
-  ACCESS_ONCE(int, spinlock->lock) = 0;
-}
-
-UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)) {
-  /* TODO(bnoordhuis) Maybe change to a ticket lock to guarantee fair queueing.
-   * Not really critical until we have locks that are (frequently) contended
-   * for by several threads.
-   */
-  return 0 == cmpxchgi(&spinlock->lock, 0, 1);
-}
-
-#endif  /* UV_SPINLOCK_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/unix/stream.cpp b/wpiutil/src/main/native/libuv/src/unix/stream.cpp
deleted file mode 100644
index f3a8e66..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/stream.cpp
+++ /dev/null
@@ -1,1689 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <limits.h> /* IOV_MAX */
-
-#if defined(__APPLE__)
-# include <sys/event.h>
-# include <sys/time.h>
-# include <sys/select.h>
-
-/* Forward declaration */
-typedef struct uv__stream_select_s uv__stream_select_t;
-
-struct uv__stream_select_s {
-  uv_stream_t* stream;
-  uv_thread_t thread;
-  uv_sem_t close_sem;
-  uv_sem_t async_sem;
-  uv_async_t async;
-  int events;
-  int fake_fd;
-  int int_fd;
-  int fd;
-  fd_set* sread;
-  size_t sread_sz;
-  fd_set* swrite;
-  size_t swrite_sz;
-};
-
-/* Due to a possible kernel bug at least in OS X 10.10 "Yosemite",
- * EPROTOTYPE can be returned while trying to write to a socket that is
- * shutting down. If we retry the write, we should get the expected EPIPE
- * instead.
- */
-# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR || errno == EPROTOTYPE)
-# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
-    (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
-     (errno == EMSGSIZE && send_handle != NULL))
-#else
-# define RETRY_ON_WRITE_ERROR(errno) (errno == EINTR)
-# define IS_TRANSIENT_WRITE_ERROR(errno, send_handle) \
-    (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
-#endif /* defined(__APPLE__) */
-
-static void uv__stream_connect(uv_stream_t*);
-static void uv__write(uv_stream_t* stream);
-static void uv__read(uv_stream_t* stream);
-static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events);
-static void uv__write_callbacks(uv_stream_t* stream);
-static size_t uv__write_req_size(uv_write_t* req);
-
-
-void uv__stream_init(uv_loop_t* loop,
-                     uv_stream_t* stream,
-                     uv_handle_type type) {
-  int err;
-
-  uv__handle_init(loop, (uv_handle_t*)stream, type);
-  stream->read_cb = NULL;
-  stream->alloc_cb = NULL;
-  stream->close_cb = NULL;
-  stream->connection_cb = NULL;
-  stream->connect_req = NULL;
-  stream->shutdown_req = NULL;
-  stream->accepted_fd = -1;
-  stream->queued_fds = NULL;
-  stream->delayed_error = 0;
-  QUEUE_INIT(&stream->write_queue);
-  QUEUE_INIT(&stream->write_completed_queue);
-  stream->write_queue_size = 0;
-
-  if (loop->emfile_fd == -1) {
-    err = uv__open_cloexec("/dev/null", O_RDONLY);
-    if (err < 0)
-        /* In the rare case that "/dev/null" isn't mounted open "/"
-         * instead.
-         */
-        err = uv__open_cloexec("/", O_RDONLY);
-    if (err >= 0)
-      loop->emfile_fd = err;
-  }
-
-#if defined(__APPLE__)
-  stream->select = NULL;
-#endif /* defined(__APPLE_) */
-
-  uv__io_init(&stream->io_watcher, uv__stream_io, -1);
-}
-
-
-static void uv__stream_osx_interrupt_select(uv_stream_t* stream) {
-#if defined(__APPLE__)
-  /* Notify select() thread about state change */
-  uv__stream_select_t* s;
-  int r;
-
-  s = (uv__stream_select_t*)stream->select;
-  if (s == NULL)
-    return;
-
-  /* Interrupt select() loop
-   * NOTE: fake_fd and int_fd are socketpair(), thus writing to one will
-   * emit read event on other side
-   */
-  do
-    r = write(s->fake_fd, "x", 1);
-  while (r == -1 && errno == EINTR);
-
-  assert(r == 1);
-#else  /* !defined(__APPLE__) */
-  /* No-op on any other platform */
-#endif  /* !defined(__APPLE__) */
-}
-
-
-#if defined(__APPLE__)
-static void uv__stream_osx_select(void* arg) {
-  uv_stream_t* stream;
-  uv__stream_select_t* s;
-  char buf[1024];
-  int events;
-  int fd;
-  int r;
-  int max_fd;
-
-  stream = (uv_stream_t*)arg;
-  s = (uv__stream_select_t*)stream->select;
-  fd = s->fd;
-
-  if (fd > s->int_fd)
-    max_fd = fd;
-  else
-    max_fd = s->int_fd;
-
-  while (1) {
-    /* Terminate on semaphore */
-    if (uv_sem_trywait(&s->close_sem) == 0)
-      break;
-
-    /* Watch fd using select(2) */
-    memset(s->sread, 0, s->sread_sz);
-    memset(s->swrite, 0, s->swrite_sz);
-
-    if (uv__io_active(&stream->io_watcher, POLLIN))
-      FD_SET(fd, s->sread);
-    if (uv__io_active(&stream->io_watcher, POLLOUT))
-      FD_SET(fd, s->swrite);
-    FD_SET(s->int_fd, s->sread);
-
-    /* Wait indefinitely for fd events */
-    r = select(max_fd + 1, s->sread, s->swrite, NULL, NULL);
-    if (r == -1) {
-      if (errno == EINTR)
-        continue;
-
-      /* XXX: Possible?! */
-      abort();
-    }
-
-    /* Ignore timeouts */
-    if (r == 0)
-      continue;
-
-    /* Empty socketpair's buffer in case of interruption */
-    if (FD_ISSET(s->int_fd, s->sread))
-      while (1) {
-        r = read(s->int_fd, buf, sizeof(buf));
-
-        if (r == sizeof(buf))
-          continue;
-
-        if (r != -1)
-          break;
-
-        if (errno == EAGAIN || errno == EWOULDBLOCK)
-          break;
-
-        if (errno == EINTR)
-          continue;
-
-        abort();
-      }
-
-    /* Handle events */
-    events = 0;
-    if (FD_ISSET(fd, s->sread))
-      events |= POLLIN;
-    if (FD_ISSET(fd, s->swrite))
-      events |= POLLOUT;
-
-    assert(events != 0 || FD_ISSET(s->int_fd, s->sread));
-    if (events != 0) {
-      ACCESS_ONCE(int, s->events) = events;
-
-      uv_async_send(&s->async);
-      uv_sem_wait(&s->async_sem);
-
-      /* Should be processed at this stage */
-      assert((s->events == 0) || (stream->flags & UV_HANDLE_CLOSING));
-    }
-  }
-}
-
-
-static void uv__stream_osx_select_cb(uv_async_t* handle) {
-  uv__stream_select_t* s;
-  uv_stream_t* stream;
-  int events;
-
-  s = container_of(handle, uv__stream_select_t, async);
-  stream = s->stream;
-
-  /* Get and reset stream's events */
-  events = s->events;
-  ACCESS_ONCE(int, s->events) = 0;
-
-  assert(events != 0);
-  assert(events == (events & (POLLIN | POLLOUT)));
-
-  /* Invoke callback on event-loop */
-  if ((events & POLLIN) && uv__io_active(&stream->io_watcher, POLLIN))
-    uv__stream_io(stream->loop, &stream->io_watcher, POLLIN);
-
-  if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT))
-    uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT);
-
-  if (stream->flags & UV_HANDLE_CLOSING)
-    return;
-
-  /* NOTE: It is important to do it here, otherwise `select()` might be called
-   * before the actual `uv__read()`, leading to the blocking syscall
-   */
-  uv_sem_post(&s->async_sem);
-}
-
-
-static void uv__stream_osx_cb_close(uv_handle_t* async) {
-  uv__stream_select_t* s;
-
-  s = container_of(async, uv__stream_select_t, async);
-  uv__free(s);
-}
-
-
-int uv__stream_try_select(uv_stream_t* stream, int* fd) {
-  /*
-   * kqueue doesn't work with some files from /dev mount on osx.
-   * select(2) in separate thread for those fds
-   */
-
-  struct kevent filter[1];
-  struct kevent events[1];
-  struct timespec timeout;
-  uv__stream_select_t* s;
-  int fds[2];
-  int err;
-  int ret;
-  int kq;
-  int old_fd;
-  int max_fd;
-  size_t sread_sz;
-  size_t swrite_sz;
-
-  kq = kqueue();
-  if (kq == -1) {
-    perror("(libuv) kqueue()");
-    return UV__ERR(errno);
-  }
-
-  EV_SET(&filter[0], *fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
-
-  /* Use small timeout, because we only want to capture EINVALs */
-  timeout.tv_sec = 0;
-  timeout.tv_nsec = 1;
-
-  do
-    ret = kevent(kq, filter, 1, events, 1, &timeout);
-  while (ret == -1 && errno == EINTR);
-
-  uv__close(kq);
-
-  if (ret == -1)
-    return UV__ERR(errno);
-
-  if (ret == 0 || (events[0].flags & EV_ERROR) == 0 || events[0].data != EINVAL)
-    return 0;
-
-  /* At this point we definitely know that this fd won't work with kqueue */
-
-  /*
-   * Create fds for io watcher and to interrupt the select() loop.
-   * NOTE: do it ahead of malloc below to allocate enough space for fd_sets
-   */
-  if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
-    return UV__ERR(errno);
-
-  max_fd = *fd;
-  if (fds[1] > max_fd)
-    max_fd = fds[1];
-
-  sread_sz = ROUND_UP(max_fd + 1, sizeof(uint32_t) * NBBY) / NBBY;
-  swrite_sz = sread_sz;
-
-  s = (uv__stream_select_t*)uv__malloc(sizeof(*s) + sread_sz + swrite_sz);
-  if (s == NULL) {
-    err = UV_ENOMEM;
-    goto failed_malloc;
-  }
-
-  s->events = 0;
-  s->fd = *fd;
-  s->sread = (fd_set*) ((char*) s + sizeof(*s));
-  s->sread_sz = sread_sz;
-  s->swrite = (fd_set*) ((char*) s->sread + sread_sz);
-  s->swrite_sz = swrite_sz;
-
-  err = uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb);
-  if (err)
-    goto failed_async_init;
-
-  s->async.flags |= UV_HANDLE_INTERNAL;
-  uv__handle_unref(&s->async);
-
-  err = uv_sem_init(&s->close_sem, 0);
-  if (err != 0)
-    goto failed_close_sem_init;
-
-  err = uv_sem_init(&s->async_sem, 0);
-  if (err != 0)
-    goto failed_async_sem_init;
-
-  s->fake_fd = fds[0];
-  s->int_fd = fds[1];
-
-  old_fd = *fd;
-  s->stream = stream;
-  stream->select = s;
-  *fd = s->fake_fd;
-
-  err = uv_thread_create(&s->thread, uv__stream_osx_select, stream);
-  if (err != 0)
-    goto failed_thread_create;
-
-  return 0;
-
-failed_thread_create:
-  s->stream = NULL;
-  stream->select = NULL;
-  *fd = old_fd;
-
-  uv_sem_destroy(&s->async_sem);
-
-failed_async_sem_init:
-  uv_sem_destroy(&s->close_sem);
-
-failed_close_sem_init:
-  uv__close(fds[0]);
-  uv__close(fds[1]);
-  uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
-  return err;
-
-failed_async_init:
-  uv__free(s);
-
-failed_malloc:
-  uv__close(fds[0]);
-  uv__close(fds[1]);
-
-  return err;
-}
-#endif /* defined(__APPLE__) */
-
-
-int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
-#if defined(__APPLE__)
-  int enable;
-#endif
-
-  if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd))
-    return UV_EBUSY;
-
-  assert(fd >= 0);
-  stream->flags |= flags;
-
-  if (stream->type == UV_TCP) {
-    if ((stream->flags & UV_HANDLE_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
-      return UV__ERR(errno);
-
-    /* TODO Use delay the user passed in. */
-    if ((stream->flags & UV_HANDLE_TCP_KEEPALIVE) &&
-        uv__tcp_keepalive(fd, 1, 60)) {
-      return UV__ERR(errno);
-    }
-  }
-
-#if defined(__APPLE__)
-  enable = 1;
-  if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
-      errno != ENOTSOCK &&
-      errno != EINVAL) {
-    return UV__ERR(errno);
-  }
-#endif
-
-  stream->io_watcher.fd = fd;
-
-  return 0;
-}
-
-
-void uv__stream_flush_write_queue(uv_stream_t* stream, int error) {
-  uv_write_t* req;
-  QUEUE* q;
-  while (!QUEUE_EMPTY(&stream->write_queue)) {
-    q = QUEUE_HEAD(&stream->write_queue);
-    QUEUE_REMOVE(q);
-
-    req = QUEUE_DATA(q, uv_write_t, queue);
-    req->error = error;
-
-    QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue);
-  }
-}
-
-
-void uv__stream_destroy(uv_stream_t* stream) {
-  assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT));
-  assert(stream->flags & UV_HANDLE_CLOSED);
-
-  if (stream->connect_req) {
-    uv__req_unregister(stream->loop, stream->connect_req);
-    stream->connect_req->cb(stream->connect_req, UV_ECANCELED);
-    stream->connect_req = NULL;
-  }
-
-  uv__stream_flush_write_queue(stream, UV_ECANCELED);
-  uv__write_callbacks(stream);
-
-  if (stream->shutdown_req) {
-    /* The ECANCELED error code is a lie, the shutdown(2) syscall is a
-     * fait accompli at this point. Maybe we should revisit this in v0.11.
-     * A possible reason for leaving it unchanged is that it informs the
-     * callee that the handle has been destroyed.
-     */
-    uv__req_unregister(stream->loop, stream->shutdown_req);
-    stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED);
-    stream->shutdown_req = NULL;
-  }
-
-  assert(stream->write_queue_size == 0);
-}
-
-
-/* Implements a best effort approach to mitigating accept() EMFILE errors.
- * We have a spare file descriptor stashed away that we close to get below
- * the EMFILE limit. Next, we accept all pending connections and close them
- * immediately to signal the clients that we're overloaded - and we are, but
- * we still keep on trucking.
- *
- * There is one caveat: it's not reliable in a multi-threaded environment.
- * The file descriptor limit is per process. Our party trick fails if another
- * thread opens a file or creates a socket in the time window between us
- * calling close() and accept().
- */
-static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
-  int err;
-  int emfile_fd;
-
-  if (loop->emfile_fd == -1)
-    return UV_EMFILE;
-
-  uv__close(loop->emfile_fd);
-  loop->emfile_fd = -1;
-
-  do {
-    err = uv__accept(accept_fd);
-    if (err >= 0)
-      uv__close(err);
-  } while (err >= 0 || err == UV_EINTR);
-
-  emfile_fd = uv__open_cloexec("/", O_RDONLY);
-  if (emfile_fd >= 0)
-    loop->emfile_fd = emfile_fd;
-
-  return err;
-}
-
-
-#if defined(UV_HAVE_KQUEUE)
-# define UV_DEC_BACKLOG(w) w->rcount--;
-#else
-# define UV_DEC_BACKLOG(w) /* no-op */
-#endif /* defined(UV_HAVE_KQUEUE) */
-
-
-void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
-  uv_stream_t* stream;
-  int err;
-
-  stream = container_of(w, uv_stream_t, io_watcher);
-  assert(events & POLLIN);
-  assert(stream->accepted_fd == -1);
-  assert(!(stream->flags & UV_HANDLE_CLOSING));
-
-  uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
-
-  /* connection_cb can close the server socket while we're
-   * in the loop so check it on each iteration.
-   */
-  while (uv__stream_fd(stream) != -1) {
-    assert(stream->accepted_fd == -1);
-
-#if defined(UV_HAVE_KQUEUE)
-    if (w->rcount <= 0)
-      return;
-#endif /* defined(UV_HAVE_KQUEUE) */
-
-    err = uv__accept(uv__stream_fd(stream));
-    if (err < 0) {
-      if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
-        return;  /* Not an error. */
-
-      if (err == UV_ECONNABORTED)
-        continue;  /* Ignore. Nothing we can do about that. */
-
-      if (err == UV_EMFILE || err == UV_ENFILE) {
-        err = uv__emfile_trick(loop, uv__stream_fd(stream));
-        if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
-          break;
-      }
-
-      stream->connection_cb(stream, err);
-      continue;
-    }
-
-    UV_DEC_BACKLOG(w)
-    stream->accepted_fd = err;
-    stream->connection_cb(stream, 0);
-
-    if (stream->accepted_fd != -1) {
-      /* The user hasn't yet accepted called uv_accept() */
-      uv__io_stop(loop, &stream->io_watcher, POLLIN);
-      return;
-    }
-
-    if (stream->type == UV_TCP &&
-        (stream->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {
-      /* Give other processes a chance to accept connections. */
-      struct timespec timeout = { 0, 1 };
-      nanosleep(&timeout, NULL);
-    }
-  }
-}
-
-
-#undef UV_DEC_BACKLOG
-
-
-int uv_accept(uv_stream_t* server, uv_stream_t* client) {
-  int err;
-
-  assert(server->loop == client->loop);
-
-  if (server->accepted_fd == -1)
-    return UV_EAGAIN;
-
-  switch (client->type) {
-    case UV_NAMED_PIPE:
-    case UV_TCP:
-      err = uv__stream_open(client,
-                            server->accepted_fd,
-                            UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
-      if (err) {
-        /* TODO handle error */
-        uv__close(server->accepted_fd);
-        goto done;
-      }
-      break;
-
-    case UV_UDP:
-      err = uv_udp_open((uv_udp_t*) client, server->accepted_fd);
-      if (err) {
-        uv__close(server->accepted_fd);
-        goto done;
-      }
-      break;
-
-    default:
-      return UV_EINVAL;
-  }
-
-  client->flags |= UV_HANDLE_BOUND;
-
-done:
-  /* Process queued fds */
-  if (server->queued_fds != NULL) {
-    uv__stream_queued_fds_t* queued_fds;
-
-    queued_fds = (uv__stream_queued_fds_t*)(server->queued_fds);
-
-    /* Read first */
-    server->accepted_fd = queued_fds->fds[0];
-
-    /* All read, free */
-    assert(queued_fds->offset > 0);
-    if (--queued_fds->offset == 0) {
-      uv__free(queued_fds);
-      server->queued_fds = NULL;
-    } else {
-      /* Shift rest */
-      memmove(queued_fds->fds,
-              queued_fds->fds + 1,
-              queued_fds->offset * sizeof(*queued_fds->fds));
-    }
-  } else {
-    server->accepted_fd = -1;
-    if (err == 0)
-      uv__io_start(server->loop, &server->io_watcher, POLLIN);
-  }
-  return err;
-}
-
-
-int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
-  int err;
-
-  switch (stream->type) {
-  case UV_TCP:
-    err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
-    break;
-
-  case UV_NAMED_PIPE:
-    err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
-    break;
-
-  default:
-    err = UV_EINVAL;
-  }
-
-  if (err == 0)
-    uv__handle_start(stream);
-
-  return err;
-}
-
-
-static void uv__drain(uv_stream_t* stream) {
-  uv_shutdown_t* req;
-  int err;
-
-  assert(QUEUE_EMPTY(&stream->write_queue));
-  uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
-  uv__stream_osx_interrupt_select(stream);
-
-  /* Shutdown? */
-  if ((stream->flags & UV_HANDLE_SHUTTING) &&
-      !(stream->flags & UV_HANDLE_CLOSING) &&
-      !(stream->flags & UV_HANDLE_SHUT)) {
-    assert(stream->shutdown_req);
-
-    req = stream->shutdown_req;
-    stream->shutdown_req = NULL;
-    stream->flags &= ~UV_HANDLE_SHUTTING;
-    uv__req_unregister(stream->loop, req);
-
-    err = 0;
-    if (shutdown(uv__stream_fd(stream), SHUT_WR))
-      err = UV__ERR(errno);
-
-    if (err == 0)
-      stream->flags |= UV_HANDLE_SHUT;
-
-    if (req->cb != NULL)
-      req->cb(req, err);
-  }
-}
-
-
-static ssize_t uv__writev(int fd, struct iovec* vec, size_t n) {
-  if (n == 1)
-    return write(fd, vec->iov_base, vec->iov_len);
-  else
-    return writev(fd, vec, n);
-}
-
-
-static size_t uv__write_req_size(uv_write_t* req) {
-  size_t size;
-
-  assert(req->bufs != NULL);
-  size = uv__count_bufs(req->bufs + req->write_index,
-                        req->nbufs - req->write_index);
-  assert(req->handle->write_queue_size >= size);
-
-  return size;
-}
-
-
-/* Returns 1 if all write request data has been written, or 0 if there is still
- * more data to write.
- *
- * Note: the return value only says something about the *current* request.
- * There may still be other write requests sitting in the queue.
- */
-static int uv__write_req_update(uv_stream_t* stream,
-                                uv_write_t* req,
-                                size_t n) {
-  uv_buf_t* buf;
-  size_t len;
-
-  assert(n <= stream->write_queue_size);
-  stream->write_queue_size -= n;
-
-  buf = req->bufs + req->write_index;
-
-  do {
-    len = n < buf->len ? n : buf->len;
-    buf->base += len;
-    buf->len -= len;
-    buf += (buf->len == 0);  /* Advance to next buffer if this one is empty. */
-    n -= len;
-  } while (n > 0);
-
-  req->write_index = buf - req->bufs;
-
-  return req->write_index == req->nbufs;
-}
-
-
-static void uv__write_req_finish(uv_write_t* req) {
-  uv_stream_t* stream = req->handle;
-
-  /* Pop the req off tcp->write_queue. */
-  QUEUE_REMOVE(&req->queue);
-
-  /* Only free when there was no error. On error, we touch up write_queue_size
-   * right before making the callback. The reason we don't do that right away
-   * is that a write_queue_size > 0 is our only way to signal to the user that
-   * they should stop writing - which they should if we got an error. Something
-   * to revisit in future revisions of the libuv API.
-   */
-  if (req->error == 0) {
-    if (req->bufs != req->bufsml)
-      uv__free(req->bufs);
-    req->bufs = NULL;
-  }
-
-  /* Add it to the write_completed_queue where it will have its
-   * callback called in the near future.
-   */
-  QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue);
-  uv__io_feed(stream->loop, &stream->io_watcher);
-}
-
-
-static int uv__handle_fd(uv_handle_t* handle) {
-  switch (handle->type) {
-    case UV_NAMED_PIPE:
-    case UV_TCP:
-      return ((uv_stream_t*) handle)->io_watcher.fd;
-
-    case UV_UDP:
-      return ((uv_udp_t*) handle)->io_watcher.fd;
-
-    default:
-      return -1;
-  }
-}
-
-static void uv__write(uv_stream_t* stream) {
-  struct iovec* iov;
-  QUEUE* q;
-  uv_write_t* req;
-  int iovmax;
-  int iovcnt;
-  ssize_t n;
-  int err;
-
-start:
-
-  assert(uv__stream_fd(stream) >= 0);
-
-  if (QUEUE_EMPTY(&stream->write_queue))
-    return;
-
-  q = QUEUE_HEAD(&stream->write_queue);
-  req = QUEUE_DATA(q, uv_write_t, queue);
-  assert(req->handle == stream);
-
-  /*
-   * Cast to iovec. We had to have our own uv_buf_t instead of iovec
-   * because Windows's WSABUF is not an iovec.
-   */
-  assert(sizeof(uv_buf_t) == sizeof(struct iovec));
-  iov = (struct iovec*) &(req->bufs[req->write_index]);
-  iovcnt = req->nbufs - req->write_index;
-
-  iovmax = uv__getiovmax();
-
-  /* Limit iov count to avoid EINVALs from writev() */
-  if (iovcnt > iovmax)
-    iovcnt = iovmax;
-
-  /*
-   * Now do the actual writev. Note that we've been updating the pointers
-   * inside the iov each time we write. So there is no need to offset it.
-   */
-
-  if (req->send_handle) {
-    int fd_to_send;
-    struct msghdr msg;
-    struct cmsghdr *cmsg;
-    union {
-      char data[64];
-      struct cmsghdr alias;
-    } scratch;
-
-    if (uv__is_closing(req->send_handle)) {
-      err = UV_EBADF;
-      goto error;
-    }
-
-    fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
-
-    memset(&scratch, 0, sizeof(scratch));
-
-    assert(fd_to_send >= 0);
-
-    msg.msg_name = NULL;
-    msg.msg_namelen = 0;
-    msg.msg_iov = iov;
-    msg.msg_iovlen = iovcnt;
-    msg.msg_flags = 0;
-
-    msg.msg_control = &scratch.alias;
-    msg.msg_controllen = CMSG_SPACE(sizeof(fd_to_send));
-
-    cmsg = CMSG_FIRSTHDR(&msg);
-    cmsg->cmsg_level = SOL_SOCKET;
-    cmsg->cmsg_type = SCM_RIGHTS;
-    cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send));
-
-    /* silence aliasing warning */
-    {
-      void* pv = CMSG_DATA(cmsg);
-      int* pi = (int*)pv;
-      *pi = fd_to_send;
-    }
-
-    do
-      n = sendmsg(uv__stream_fd(stream), &msg, 0);
-    while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
-
-    /* Ensure the handle isn't sent again in case this is a partial write. */
-    if (n >= 0)
-      req->send_handle = NULL;
-  } else {
-    do
-      n = uv__writev(uv__stream_fd(stream), iov, iovcnt);
-    while (n == -1 && RETRY_ON_WRITE_ERROR(errno));
-  }
-
-  if (n == -1 && !IS_TRANSIENT_WRITE_ERROR(errno, req->send_handle)) {
-    err = UV__ERR(errno);
-    goto error;
-  }
-
-  if (n >= 0 && uv__write_req_update(stream, req, n)) {
-    uv__write_req_finish(req);
-    return;  /* TODO(bnoordhuis) Start trying to write the next request. */
-  }
-
-  /* If this is a blocking stream, try again. */
-  if (stream->flags & UV_HANDLE_BLOCKING_WRITES)
-    goto start;
-
-  /* We're not done. */
-  uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
-
-  /* Notify select() thread about state change */
-  uv__stream_osx_interrupt_select(stream);
-
-  return;
-
-error:
-  req->error = err;
-  uv__write_req_finish(req);
-  uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
-  if (!uv__io_active(&stream->io_watcher, POLLIN))
-    uv__handle_stop(stream);
-  uv__stream_osx_interrupt_select(stream);
-}
-
-
-static void uv__write_callbacks(uv_stream_t* stream) {
-  uv_write_t* req;
-  QUEUE* q;
-  QUEUE pq;
-
-  if (QUEUE_EMPTY(&stream->write_completed_queue))
-    return;
-
-  QUEUE_MOVE(&stream->write_completed_queue, &pq);
-
-  while (!QUEUE_EMPTY(&pq)) {
-    /* Pop a req off write_completed_queue. */
-    q = QUEUE_HEAD(&pq);
-    req = QUEUE_DATA(q, uv_write_t, queue);
-    QUEUE_REMOVE(q);
-    uv__req_unregister(stream->loop, req);
-
-    if (req->bufs != NULL) {
-      stream->write_queue_size -= uv__write_req_size(req);
-      if (req->bufs != req->bufsml)
-        uv__free(req->bufs);
-      req->bufs = NULL;
-    }
-
-    /* NOTE: call callback AFTER freeing the request data. */
-    if (req->cb)
-      req->cb(req, req->error);
-  }
-}
-
-
-uv_handle_type uv__handle_type(int fd) {
-  struct sockaddr_storage ss;
-  socklen_t sslen;
-  socklen_t len;
-  int type;
-
-  memset(&ss, 0, sizeof(ss));
-  sslen = sizeof(ss);
-
-  if (getsockname(fd, (struct sockaddr*)&ss, &sslen))
-    return UV_UNKNOWN_HANDLE;
-
-  len = sizeof type;
-
-  if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len))
-    return UV_UNKNOWN_HANDLE;
-
-  if (type == SOCK_STREAM) {
-#if defined(_AIX) || defined(__DragonFly__)
-    /* on AIX/DragonFly the getsockname call returns an empty sa structure
-     * for sockets of type AF_UNIX.  For all other types it will
-     * return a properly filled in structure.
-     */
-    if (sslen == 0)
-      return UV_NAMED_PIPE;
-#endif
-    switch (ss.ss_family) {
-      case AF_UNIX:
-        return UV_NAMED_PIPE;
-      case AF_INET:
-      case AF_INET6:
-        return UV_TCP;
-      }
-  }
-
-  if (type == SOCK_DGRAM &&
-      (ss.ss_family == AF_INET || ss.ss_family == AF_INET6))
-    return UV_UDP;
-
-  return UV_UNKNOWN_HANDLE;
-}
-
-
-static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
-  stream->flags |= UV_HANDLE_READ_EOF;
-  uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
-  if (!uv__io_active(&stream->io_watcher, POLLOUT))
-    uv__handle_stop(stream);
-  uv__stream_osx_interrupt_select(stream);
-  stream->read_cb(stream, UV_EOF, buf);
-  stream->flags &= ~UV_HANDLE_READING;
-}
-
-
-static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
-  uv__stream_queued_fds_t* queued_fds;
-  unsigned int queue_size;
-
-  queued_fds = (uv__stream_queued_fds_t*)stream->queued_fds;
-  if (queued_fds == NULL) {
-    queue_size = 8;
-    queued_fds = (uv__stream_queued_fds_t*)
-        uv__malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
-                   sizeof(*queued_fds));
-    if (queued_fds == NULL)
-      return UV_ENOMEM;
-    queued_fds->size = queue_size;
-    queued_fds->offset = 0;
-    stream->queued_fds = queued_fds;
-
-    /* Grow */
-  } else if (queued_fds->size == queued_fds->offset) {
-    queue_size = queued_fds->size + 8;
-    queued_fds = (uv__stream_queued_fds_t*)
-        uv__realloc(queued_fds, (queue_size - 1) * sizeof(*queued_fds->fds) +
-                    sizeof(*queued_fds));
-
-    /*
-     * Allocation failure, report back.
-     * NOTE: if it is fatal - sockets will be closed in uv__stream_close
-     */
-    if (queued_fds == NULL)
-      return UV_ENOMEM;
-    queued_fds->size = queue_size;
-    stream->queued_fds = queued_fds;
-  }
-
-  /* Put fd in a queue */
-  queued_fds->fds[queued_fds->offset++] = fd;
-
-  return 0;
-}
-
-
-#define UV__CMSG_FD_COUNT 64
-#define UV__CMSG_FD_SIZE (UV__CMSG_FD_COUNT * sizeof(int))
-
-
-static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) {
-  struct cmsghdr* cmsg;
-
-  for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
-    char* start;
-    char* end;
-    int err;
-    void* pv;
-    int* pi;
-    unsigned int i;
-    unsigned int count;
-
-    if (cmsg->cmsg_type != SCM_RIGHTS) {
-      fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n",
-          cmsg->cmsg_type);
-      continue;
-    }
-
-    /* silence aliasing warning */
-    pv = CMSG_DATA(cmsg);
-    pi = (int*)pv;
-
-    /* Count available fds */
-    start = (char*) cmsg;
-    end = (char*) cmsg + cmsg->cmsg_len;
-    count = 0;
-    while (start + CMSG_LEN(count * sizeof(*pi)) < end)
-      count++;
-    assert(start + CMSG_LEN(count * sizeof(*pi)) == end);
-
-    for (i = 0; i < count; i++) {
-      /* Already has accepted fd, queue now */
-      if (stream->accepted_fd != -1) {
-        err = uv__stream_queue_fd(stream, pi[i]);
-        if (err != 0) {
-          /* Close rest */
-          for (; i < count; i++)
-            uv__close(pi[i]);
-          return err;
-        }
-      } else {
-        stream->accepted_fd = pi[i];
-      }
-    }
-  }
-
-  return 0;
-}
-
-
-#ifdef __clang__
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wgnu-folding-constant"
-# pragma clang diagnostic ignored "-Wvla-extension"
-#endif
-
-static void uv__read(uv_stream_t* stream) {
-  uv_buf_t buf;
-  ssize_t nread;
-  struct msghdr msg;
-  char cmsg_space[CMSG_SPACE(UV__CMSG_FD_SIZE)];
-  int count;
-  int err;
-  int is_ipc;
-
-  stream->flags &= ~UV_HANDLE_READ_PARTIAL;
-
-  /* Prevent loop starvation when the data comes in as fast as (or faster than)
-   * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
-   */
-  count = 32;
-
-  is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc;
-
-  /* XXX: Maybe instead of having UV_HANDLE_READING we just test if
-   * tcp->read_cb is NULL or not?
-   */
-  while (stream->read_cb
-      && (stream->flags & UV_HANDLE_READING)
-      && (count-- > 0)) {
-    assert(stream->alloc_cb != NULL);
-
-    buf = uv_buf_init(NULL, 0);
-    stream->alloc_cb((uv_handle_t*)stream, 64 * 1024, &buf);
-    if (buf.base == NULL || buf.len == 0) {
-      /* User indicates it can't or won't handle the read. */
-      stream->read_cb(stream, UV_ENOBUFS, &buf);
-      return;
-    }
-
-    assert(buf.base != NULL);
-    assert(uv__stream_fd(stream) >= 0);
-
-    if (!is_ipc) {
-      do {
-        nread = read(uv__stream_fd(stream), buf.base, buf.len);
-      }
-      while (nread < 0 && errno == EINTR);
-    } else {
-      /* ipc uses recvmsg */
-      msg.msg_flags = 0;
-      msg.msg_iov = (struct iovec*) &buf;
-      msg.msg_iovlen = 1;
-      msg.msg_name = NULL;
-      msg.msg_namelen = 0;
-      /* Set up to receive a descriptor even if one isn't in the message */
-      msg.msg_controllen = sizeof(cmsg_space);
-      msg.msg_control = cmsg_space;
-
-      do {
-        nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
-      }
-      while (nread < 0 && errno == EINTR);
-    }
-
-    if (nread < 0) {
-      /* Error */
-      if (errno == EAGAIN || errno == EWOULDBLOCK) {
-        /* Wait for the next one. */
-        if (stream->flags & UV_HANDLE_READING) {
-          uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
-          uv__stream_osx_interrupt_select(stream);
-        }
-        stream->read_cb(stream, 0, &buf);
-#if defined(__CYGWIN__) || defined(__MSYS__)
-      } else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) {
-        uv__stream_eof(stream, &buf);
-        return;
-#endif
-      } else {
-        /* Error. User should call uv_close(). */
-        stream->read_cb(stream, UV__ERR(errno), &buf);
-        if (stream->flags & UV_HANDLE_READING) {
-          stream->flags &= ~UV_HANDLE_READING;
-          uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
-          if (!uv__io_active(&stream->io_watcher, POLLOUT))
-            uv__handle_stop(stream);
-          uv__stream_osx_interrupt_select(stream);
-        }
-      }
-      return;
-    } else if (nread == 0) {
-      uv__stream_eof(stream, &buf);
-      return;
-    } else {
-      /* Successful read */
-      ssize_t buflen = buf.len;
-
-      if (is_ipc) {
-        err = uv__stream_recv_cmsg(stream, &msg);
-        if (err != 0) {
-          stream->read_cb(stream, err, &buf);
-          return;
-        }
-      }
-
-#if defined(__MVS__)
-      if (is_ipc && msg.msg_controllen > 0) {
-        uv_buf_t blankbuf;
-        int nread;
-        struct iovec *old;
-
-        blankbuf.base = 0;
-        blankbuf.len = 0;
-        old = msg.msg_iov;
-        msg.msg_iov = (struct iovec*) &blankbuf;
-        nread = 0;
-        do {
-          nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
-          err = uv__stream_recv_cmsg(stream, &msg);
-          if (err != 0) {
-            stream->read_cb(stream, err, &buf);
-            msg.msg_iov = old;
-            return;
-          }
-        } while (nread == 0 && msg.msg_controllen > 0);
-        msg.msg_iov = old;
-      }
-#endif
-      stream->read_cb(stream, nread, &buf);
-
-      /* Return if we didn't fill the buffer, there is no more data to read. */
-      if (nread < buflen) {
-        stream->flags |= UV_HANDLE_READ_PARTIAL;
-        return;
-      }
-    }
-  }
-}
-
-
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
-
-#undef UV__CMSG_FD_COUNT
-#undef UV__CMSG_FD_SIZE
-
-
-int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
-  assert(stream->type == UV_TCP ||
-         stream->type == UV_TTY ||
-         stream->type == UV_NAMED_PIPE);
-
-  if (!(stream->flags & UV_HANDLE_WRITABLE) ||
-      stream->flags & UV_HANDLE_SHUT ||
-      stream->flags & UV_HANDLE_SHUTTING ||
-      uv__is_closing(stream)) {
-    return UV_ENOTCONN;
-  }
-
-  assert(uv__stream_fd(stream) >= 0);
-
-  /* Initialize request */
-  uv__req_init(stream->loop, req, UV_SHUTDOWN);
-  req->handle = stream;
-  req->cb = cb;
-  stream->shutdown_req = req;
-  stream->flags |= UV_HANDLE_SHUTTING;
-
-  uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
-  uv__stream_osx_interrupt_select(stream);
-
-  return 0;
-}
-
-
-static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
-  uv_stream_t* stream;
-
-  stream = container_of(w, uv_stream_t, io_watcher);
-
-  assert(stream->type == UV_TCP ||
-         stream->type == UV_NAMED_PIPE ||
-         stream->type == UV_TTY);
-  assert(!(stream->flags & UV_HANDLE_CLOSING));
-
-  if (stream->connect_req) {
-    uv__stream_connect(stream);
-    return;
-  }
-
-  assert(uv__stream_fd(stream) >= 0);
-
-  /* Ignore POLLHUP here. Even if it's set, there may still be data to read. */
-  if (events & (POLLIN | POLLERR | POLLHUP))
-    uv__read(stream);
-
-  if (uv__stream_fd(stream) == -1)
-    return;  /* read_cb closed stream. */
-
-  /* Short-circuit iff POLLHUP is set, the user is still interested in read
-   * events and uv__read() reported a partial read but not EOF. If the EOF
-   * flag is set, uv__read() called read_cb with err=UV_EOF and we don't
-   * have to do anything. If the partial read flag is not set, we can't
-   * report the EOF yet because there is still data to read.
-   */
-  if ((events & POLLHUP) &&
-      (stream->flags & UV_HANDLE_READING) &&
-      (stream->flags & UV_HANDLE_READ_PARTIAL) &&
-      !(stream->flags & UV_HANDLE_READ_EOF)) {
-    uv_buf_t buf = { NULL, 0 };
-    uv__stream_eof(stream, &buf);
-  }
-
-  if (uv__stream_fd(stream) == -1)
-    return;  /* read_cb closed stream. */
-
-  if (events & (POLLOUT | POLLERR | POLLHUP)) {
-    uv__write(stream);
-    uv__write_callbacks(stream);
-
-    /* Write queue drained. */
-    if (QUEUE_EMPTY(&stream->write_queue))
-      uv__drain(stream);
-  }
-}
-
-
-/**
- * We get called here from directly following a call to connect(2).
- * In order to determine if we've errored out or succeeded must call
- * getsockopt.
- */
-static void uv__stream_connect(uv_stream_t* stream) {
-  int error;
-  uv_connect_t* req = stream->connect_req;
-  socklen_t errorsize = sizeof(int);
-
-  assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE);
-  assert(req);
-
-  if (stream->delayed_error) {
-    /* To smooth over the differences between unixes errors that
-     * were reported synchronously on the first connect can be delayed
-     * until the next tick--which is now.
-     */
-    error = stream->delayed_error;
-    stream->delayed_error = 0;
-  } else {
-    /* Normal situation: we need to get the socket error from the kernel. */
-    assert(uv__stream_fd(stream) >= 0);
-    getsockopt(uv__stream_fd(stream),
-               SOL_SOCKET,
-               SO_ERROR,
-               &error,
-               &errorsize);
-    error = UV__ERR(error);
-  }
-
-  if (error == UV__ERR(EINPROGRESS))
-    return;
-
-  stream->connect_req = NULL;
-  uv__req_unregister(stream->loop, req);
-
-  if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) {
-    uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
-  }
-
-  if (req->cb)
-    req->cb(req, error);
-
-  if (uv__stream_fd(stream) == -1)
-    return;
-
-  if (error < 0) {
-    uv__stream_flush_write_queue(stream, UV_ECANCELED);
-    uv__write_callbacks(stream);
-  }
-}
-
-
-int uv_write2(uv_write_t* req,
-              uv_stream_t* stream,
-              const uv_buf_t bufs[],
-              unsigned int nbufs,
-              uv_stream_t* send_handle,
-              uv_write_cb cb) {
-  int empty_queue;
-
-  assert(nbufs > 0);
-  assert((stream->type == UV_TCP ||
-          stream->type == UV_NAMED_PIPE ||
-          stream->type == UV_TTY) &&
-         "uv_write (unix) does not yet support other types of streams");
-
-  if (uv__stream_fd(stream) < 0)
-    return UV_EBADF;
-
-  if (!(stream->flags & UV_HANDLE_WRITABLE))
-    return -EPIPE;
-
-  if (send_handle) {
-    if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
-      return UV_EINVAL;
-
-    /* XXX We abuse uv_write2() to send over UDP handles to child processes.
-     * Don't call uv__stream_fd() on those handles, it's a macro that on OS X
-     * evaluates to a function that operates on a uv_stream_t with a couple of
-     * OS X specific fields. On other Unices it does (handle)->io_watcher.fd,
-     * which works but only by accident.
-     */
-    if (uv__handle_fd((uv_handle_t*) send_handle) < 0)
-      return UV_EBADF;
-
-#if defined(__CYGWIN__) || defined(__MSYS__)
-    /* Cygwin recvmsg always sets msg_controllen to zero, so we cannot send it.
-       See https://github.com/mirror/newlib-cygwin/blob/86fc4bf0/winsup/cygwin/fhandler_socket.cc#L1736-L1743 */
-    return UV_ENOSYS;
-#endif
-  }
-
-  /* It's legal for write_queue_size > 0 even when the write_queue is empty;
-   * it means there are error-state requests in the write_completed_queue that
-   * will touch up write_queue_size later, see also uv__write_req_finish().
-   * We could check that write_queue is empty instead but that implies making
-   * a write() syscall when we know that the handle is in error mode.
-   */
-  empty_queue = (stream->write_queue_size == 0);
-
-  /* Initialize the req */
-  uv__req_init(stream->loop, req, UV_WRITE);
-  req->cb = cb;
-  req->handle = stream;
-  req->error = 0;
-  req->send_handle = send_handle;
-  QUEUE_INIT(&req->queue);
-
-  req->bufs = req->bufsml;
-  if (nbufs > ARRAY_SIZE(req->bufsml))
-    req->bufs = (uv_buf_t*)uv__malloc(nbufs * sizeof(bufs[0]));
-
-  if (req->bufs == NULL)
-    return UV_ENOMEM;
-
-  memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
-  req->nbufs = nbufs;
-  req->write_index = 0;
-  stream->write_queue_size += uv__count_bufs(bufs, nbufs);
-
-  /* Append the request to write_queue. */
-  QUEUE_INSERT_TAIL(&stream->write_queue, &req->queue);
-
-  /* If the queue was empty when this function began, we should attempt to
-   * do the write immediately. Otherwise start the write_watcher and wait
-   * for the fd to become writable.
-   */
-  if (stream->connect_req) {
-    /* Still connecting, do nothing. */
-  }
-  else if (empty_queue) {
-    uv__write(stream);
-  }
-  else {
-    /*
-     * blocking streams should never have anything in the queue.
-     * if this assert fires then somehow the blocking stream isn't being
-     * sufficiently flushed in uv__write.
-     */
-    assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES));
-    uv__io_start(stream->loop, &stream->io_watcher, POLLOUT);
-    uv__stream_osx_interrupt_select(stream);
-  }
-
-  return 0;
-}
-
-
-/* The buffers to be written must remain valid until the callback is called.
- * This is not required for the uv_buf_t array.
- */
-int uv_write(uv_write_t* req,
-             uv_stream_t* handle,
-             const uv_buf_t bufs[],
-             unsigned int nbufs,
-             uv_write_cb cb) {
-  return uv_write2(req, handle, bufs, nbufs, NULL, cb);
-}
-
-
-void uv_try_write_cb(uv_write_t* req, int status) {
-  /* Should not be called */
-  abort();
-}
-
-
-int uv_try_write(uv_stream_t* stream,
-                 const uv_buf_t bufs[],
-                 unsigned int nbufs) {
-  int r;
-  int has_pollout;
-  size_t written;
-  size_t req_size;
-  uv_write_t req;
-
-  /* Connecting or already writing some data */
-  if (stream->connect_req != NULL || stream->write_queue_size != 0)
-    return UV_EAGAIN;
-
-  has_pollout = uv__io_active(&stream->io_watcher, POLLOUT);
-
-  r = uv_write(&req, stream, bufs, nbufs, uv_try_write_cb);
-  if (r != 0)
-    return r;
-
-  /* Remove not written bytes from write queue size */
-  written = uv__count_bufs(bufs, nbufs);
-  if (req.bufs != NULL)
-    req_size = uv__write_req_size(&req);
-  else
-    req_size = 0;
-  written -= req_size;
-  stream->write_queue_size -= req_size;
-
-  /* Unqueue request, regardless of immediateness */
-  QUEUE_REMOVE(&req.queue);
-  uv__req_unregister(stream->loop, &req);
-  if (req.bufs != req.bufsml)
-    uv__free(req.bufs);
-  req.bufs = NULL;
-
-  /* Do not poll for writable, if we wasn't before calling this */
-  if (!has_pollout) {
-    uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
-    uv__stream_osx_interrupt_select(stream);
-  }
-
-  if (written == 0 && req_size != 0)
-    return req.error < 0 ? req.error : UV_EAGAIN;
-  else
-    return written;
-}
-
-
-int uv_read_start(uv_stream_t* stream,
-                  uv_alloc_cb alloc_cb,
-                  uv_read_cb read_cb) {
-  assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
-      stream->type == UV_TTY);
-
-  if (stream->flags & UV_HANDLE_CLOSING)
-    return UV_EINVAL;
-
-  if (!(stream->flags & UV_HANDLE_READABLE))
-    return -ENOTCONN;
-
-  /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just
-   * expresses the desired state of the user.
-   */
-  stream->flags |= UV_HANDLE_READING;
-
-  /* TODO: try to do the read inline? */
-  /* TODO: keep track of tcp state. If we've gotten a EOF then we should
-   * not start the IO watcher.
-   */
-  assert(uv__stream_fd(stream) >= 0);
-  assert(alloc_cb);
-
-  stream->read_cb = read_cb;
-  stream->alloc_cb = alloc_cb;
-
-  uv__io_start(stream->loop, &stream->io_watcher, POLLIN);
-  uv__handle_start(stream);
-  uv__stream_osx_interrupt_select(stream);
-
-  return 0;
-}
-
-
-int uv_read_stop(uv_stream_t* stream) {
-  if (!(stream->flags & UV_HANDLE_READING))
-    return 0;
-
-  stream->flags &= ~UV_HANDLE_READING;
-  uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
-  if (!uv__io_active(&stream->io_watcher, POLLOUT))
-    uv__handle_stop(stream);
-  uv__stream_osx_interrupt_select(stream);
-
-  stream->read_cb = NULL;
-  stream->alloc_cb = NULL;
-  return 0;
-}
-
-
-int uv_is_readable(const uv_stream_t* stream) {
-  return !!(stream->flags & UV_HANDLE_READABLE);
-}
-
-
-int uv_is_writable(const uv_stream_t* stream) {
-  return !!(stream->flags & UV_HANDLE_WRITABLE);
-}
-
-
-#if defined(__APPLE__)
-int uv___stream_fd(const uv_stream_t* handle) {
-  const uv__stream_select_t* s;
-
-  assert(handle->type == UV_TCP ||
-         handle->type == UV_TTY ||
-         handle->type == UV_NAMED_PIPE);
-
-  s = (const uv__stream_select_t*)handle->select;
-  if (s != NULL)
-    return s->fd;
-
-  return handle->io_watcher.fd;
-}
-#endif /* defined(__APPLE__) */
-
-
-void uv__stream_close(uv_stream_t* handle) {
-  unsigned int i;
-  uv__stream_queued_fds_t* queued_fds;
-
-#if defined(__APPLE__)
-  /* Terminate select loop first */
-  if (handle->select != NULL) {
-    uv__stream_select_t* s;
-
-    s = (uv__stream_select_t*)handle->select;
-
-    uv_sem_post(&s->close_sem);
-    uv_sem_post(&s->async_sem);
-    uv__stream_osx_interrupt_select(handle);
-    uv_thread_join(&s->thread);
-    uv_sem_destroy(&s->close_sem);
-    uv_sem_destroy(&s->async_sem);
-    uv__close(s->fake_fd);
-    uv__close(s->int_fd);
-    uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close);
-
-    handle->select = NULL;
-  }
-#endif /* defined(__APPLE__) */
-
-  uv__io_close(handle->loop, &handle->io_watcher);
-  uv_read_stop(handle);
-  uv__handle_stop(handle);
-  handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
-
-  if (handle->io_watcher.fd != -1) {
-    /* Don't close stdio file descriptors.  Nothing good comes from it. */
-    if (handle->io_watcher.fd > STDERR_FILENO)
-      uv__close(handle->io_watcher.fd);
-    handle->io_watcher.fd = -1;
-  }
-
-  if (handle->accepted_fd != -1) {
-    uv__close(handle->accepted_fd);
-    handle->accepted_fd = -1;
-  }
-
-  /* Close all queued fds */
-  if (handle->queued_fds != NULL) {
-    queued_fds = (uv__stream_queued_fds_t*)(handle->queued_fds);
-    for (i = 0; i < queued_fds->offset; i++)
-      uv__close(queued_fds->fds[i]);
-    uv__free(handle->queued_fds);
-    handle->queued_fds = NULL;
-  }
-
-  assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT));
-}
-
-
-int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
-  /* Don't need to check the file descriptor, uv__nonblock()
-   * will fail with EBADF if it's not valid.
-   */
-  return uv__nonblock(uv__stream_fd(handle), !blocking);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/sysinfo-loadavg.cpp b/wpiutil/src/main/native/libuv/src/unix/sysinfo-loadavg.cpp
deleted file mode 100644
index ebad0e8..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/sysinfo-loadavg.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stdint.h>
-#include <sys/sysinfo.h>
-
-void uv_loadavg(double avg[3]) {
-  struct sysinfo info;
-
-  if (sysinfo(&info) < 0) return;
-
-  avg[0] = (double) info.loads[0] / 65536.0;
-  avg[1] = (double) info.loads[1] / 65536.0;
-  avg[2] = (double) info.loads[2] / 65536.0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/tcp.cpp b/wpiutil/src/main/native/libuv/src/unix/tcp.cpp
deleted file mode 100644
index 8cedcd6..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/tcp.cpp
+++ /dev/null
@@ -1,433 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-
-
-static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
-  struct sockaddr_storage saddr;
-  socklen_t slen;
-  int sockfd;
-  int err;
-
-  err = uv__socket(domain, SOCK_STREAM, 0);
-  if (err < 0)
-    return err;
-  sockfd = err;
-
-  err = uv__stream_open((uv_stream_t*) handle, sockfd, flags);
-  if (err) {
-    uv__close(sockfd);
-    return err;
-  }
-
-  if (flags & UV_HANDLE_BOUND) {
-    /* Bind this new socket to an arbitrary port */
-    slen = sizeof(saddr);
-    memset(&saddr, 0, sizeof(saddr));
-    if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) {
-      uv__close(sockfd);
-      return UV__ERR(errno);
-    }
-
-    if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
-      uv__close(sockfd);
-      return UV__ERR(errno);
-    }
-  }
-
-  return 0;
-}
-
-
-static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
-  struct sockaddr_storage saddr;
-  socklen_t slen;
-
-  if (domain == AF_UNSPEC) {
-    handle->flags |= flags;
-    return 0;
-  }
-
-  if (uv__stream_fd(handle) != -1) {
-
-    if (flags & UV_HANDLE_BOUND) {
-
-      if (handle->flags & UV_HANDLE_BOUND) {
-        /* It is already bound to a port. */
-        handle->flags |= flags;
-        return 0;
-      }
-
-      /* Query to see if tcp socket is bound. */
-      slen = sizeof(saddr);
-      memset(&saddr, 0, sizeof(saddr));
-      if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
-        return UV__ERR(errno);
-
-      if ((saddr.ss_family == AF_INET6 &&
-          ((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
-          (saddr.ss_family == AF_INET &&
-          ((struct sockaddr_in*) &saddr)->sin_port != 0)) {
-        /* Handle is already bound to a port. */
-        handle->flags |= flags;
-        return 0;
-      }
-
-      /* Bind to arbitrary port */
-      if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
-        return UV__ERR(errno);
-    }
-
-    handle->flags |= flags;
-    return 0;
-  }
-
-  return new_socket(handle, domain, flags);
-}
-
-
-int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
-  int domain;
-
-  /* Use the lower 8 bits for the domain */
-  domain = flags & 0xFF;
-  if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
-    return UV_EINVAL;
-
-  if (flags & ~0xFF)
-    return UV_EINVAL;
-
-  uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
-
-  /* If anything fails beyond this point we need to remove the handle from
-   * the handle queue, since it was added by uv__handle_init in uv_stream_init.
-   */
-
-  if (domain != AF_UNSPEC) {
-    int err = maybe_new_socket(tcp, domain, 0);
-    if (err) {
-      QUEUE_REMOVE(&tcp->handle_queue);
-      return err;
-    }
-  }
-
-  return 0;
-}
-
-
-int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
-  return uv_tcp_init_ex(loop, tcp, AF_UNSPEC);
-}
-
-
-int uv__tcp_bind(uv_tcp_t* tcp,
-                 const struct sockaddr* addr,
-                 unsigned int addrlen,
-                 unsigned int flags) {
-  int err;
-  int on;
-
-  /* Cannot set IPv6-only mode on non-IPv6 socket. */
-  if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
-    return UV_EINVAL;
-
-  err = maybe_new_socket(tcp, addr->sa_family, 0);
-  if (err)
-    return err;
-
-  on = 1;
-  if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
-    return UV__ERR(errno);
-
-#ifndef __OpenBSD__
-#ifdef IPV6_V6ONLY
-  if (addr->sa_family == AF_INET6) {
-    on = (flags & UV_TCP_IPV6ONLY) != 0;
-    if (setsockopt(tcp->io_watcher.fd,
-                   IPPROTO_IPV6,
-                   IPV6_V6ONLY,
-                   &on,
-                   sizeof on) == -1) {
-#if defined(__MVS__)
-      if (errno == EOPNOTSUPP)
-        return UV_EINVAL;
-#endif
-      return UV__ERR(errno);
-    }
-  }
-#endif
-#endif
-
-  errno = 0;
-  if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
-    if (errno == EAFNOSUPPORT)
-      /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
-       * socket created with AF_INET to an AF_INET6 address or vice versa. */
-      return UV_EINVAL;
-    return UV__ERR(errno);
-  }
-  tcp->delayed_error = UV__ERR(errno);
-
-  tcp->flags |= UV_HANDLE_BOUND;
-  if (addr->sa_family == AF_INET6)
-    tcp->flags |= UV_HANDLE_IPV6;
-
-  return 0;
-}
-
-
-int uv__tcp_connect(uv_connect_t* req,
-                    uv_tcp_t* handle,
-                    const struct sockaddr* addr,
-                    unsigned int addrlen,
-                    uv_connect_cb cb) {
-  int err;
-  int r;
-
-  assert(handle->type == UV_TCP);
-
-  if (handle->connect_req != NULL)
-    return UV_EALREADY;  /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
-
-  err = maybe_new_socket(handle,
-                         addr->sa_family,
-                         UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
-  if (err)
-    return err;
-
-  handle->delayed_error = 0;
-
-  do {
-    errno = 0;
-    r = connect(uv__stream_fd(handle), addr, addrlen);
-  } while (r == -1 && errno == EINTR);
-
-  /* We not only check the return value, but also check the errno != 0.
-   * Because in rare cases connect() will return -1 but the errno
-   * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227)
-   * and actually the tcp three-way handshake is completed.
-   */
-  if (r == -1 && errno != 0) {
-    if (errno == EINPROGRESS)
-      ; /* not an error */
-    else if (errno == ECONNREFUSED
-#if defined(__OpenBSD__)
-      || errno == EINVAL
-#endif
-      )
-    /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the
-     * next tick to report the error. Solaris and OpenBSD wants to report
-     * immediately -- other unixes want to wait.
-     */
-      handle->delayed_error = UV__ERR(ECONNREFUSED);
-    else
-      return UV__ERR(errno);
-  }
-
-  uv__req_init(handle->loop, req, UV_CONNECT);
-  req->cb = cb;
-  req->handle = (uv_stream_t*) handle;
-  QUEUE_INIT(&req->queue);
-  handle->connect_req = req;
-
-  uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
-
-  if (handle->delayed_error)
-    uv__io_feed(handle->loop, &handle->io_watcher);
-
-  return 0;
-}
-
-
-int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
-  int err;
-
-  if (uv__fd_exists(handle->loop, sock))
-    return UV_EEXIST;
-
-  err = uv__nonblock(sock, 1);
-  if (err)
-    return err;
-
-  return uv__stream_open((uv_stream_t*)handle,
-                         sock,
-                         UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
-}
-
-
-int uv_tcp_getsockname(const uv_tcp_t* handle,
-                       struct sockaddr* name,
-                       int* namelen) {
-
-  if (handle->delayed_error)
-    return handle->delayed_error;
-
-  return uv__getsockpeername((const uv_handle_t*) handle,
-                             getsockname,
-                             name,
-                             namelen);
-}
-
-
-int uv_tcp_getpeername(const uv_tcp_t* handle,
-                       struct sockaddr* name,
-                       int* namelen) {
-
-  if (handle->delayed_error)
-    return handle->delayed_error;
-
-  return uv__getsockpeername((const uv_handle_t*) handle,
-                             getpeername,
-                             name,
-                             namelen);
-}
-
-
-int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
-  static int single_accept = -1;
-  unsigned long flags;
-  int err;
-
-  if (tcp->delayed_error)
-    return tcp->delayed_error;
-
-  if (single_accept == -1) {
-    const char* val = getenv("UV_TCP_SINGLE_ACCEPT");
-    single_accept = (val != NULL && atoi(val) != 0);  /* Off by default. */
-  }
-
-  if (single_accept)
-    tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
-
-  flags = 0;
-#if defined(__MVS__)
-  /* on zOS the listen call does not bind automatically
-     if the socket is unbound. Hence the manual binding to
-     an arbitrary port is required to be done manually
-  */
-  flags |= UV_HANDLE_BOUND;
-#endif
-  err = maybe_new_socket(tcp, AF_INET, flags);
-  if (err)
-    return err;
-
-  if (listen(tcp->io_watcher.fd, backlog))
-    return UV__ERR(errno);
-
-  tcp->connection_cb = cb;
-  tcp->flags |= UV_HANDLE_BOUND;
-
-  /* Start listening for connections. */
-  tcp->io_watcher.cb = uv__server_io;
-  uv__io_start(tcp->loop, &tcp->io_watcher, POLLIN);
-
-  return 0;
-}
-
-
-int uv__tcp_nodelay(int fd, int on) {
-  if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
-    return UV__ERR(errno);
-  return 0;
-}
-
-
-int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
-  if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
-    return UV__ERR(errno);
-
-#ifdef TCP_KEEPIDLE
-  if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
-    return UV__ERR(errno);
-#endif
-
-  /* Solaris/SmartOS, if you don't support keep-alive,
-   * then don't advertise it in your system headers...
-   */
-  /* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
-#if defined(TCP_KEEPALIVE) && !defined(__sun)
-  if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
-    return UV__ERR(errno);
-#endif
-
-  return 0;
-}
-
-
-int uv_tcp_nodelay(uv_tcp_t* handle, int on) {
-  int err;
-
-  if (uv__stream_fd(handle) != -1) {
-    err = uv__tcp_nodelay(uv__stream_fd(handle), on);
-    if (err)
-      return err;
-  }
-
-  if (on)
-    handle->flags |= UV_HANDLE_TCP_NODELAY;
-  else
-    handle->flags &= ~UV_HANDLE_TCP_NODELAY;
-
-  return 0;
-}
-
-
-int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) {
-  int err;
-
-  if (uv__stream_fd(handle) != -1) {
-    err =uv__tcp_keepalive(uv__stream_fd(handle), on, delay);
-    if (err)
-      return err;
-  }
-
-  if (on)
-    handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
-  else
-    handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
-
-  /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge
-   *      uv_tcp_t with an int that's almost never used...
-   */
-
-  return 0;
-}
-
-
-int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
-  if (enable)
-    handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT;
-  else
-    handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
-  return 0;
-}
-
-
-void uv__tcp_close(uv_tcp_t* handle) {
-  uv__stream_close((uv_stream_t*)handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/thread.cpp b/wpiutil/src/main/native/libuv/src/unix/thread.cpp
deleted file mode 100644
index 012cd6a..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/thread.cpp
+++ /dev/null
@@ -1,844 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <pthread.h>
-#include <assert.h>
-#include <errno.h>
-
-#include <sys/time.h>
-#include <sys/resource.h>  /* getrlimit() */
-#include <unistd.h>  /* getpagesize() */
-
-#include <limits.h>
-
-#ifdef __MVS__
-#include <sys/ipc.h>
-#include <sys/sem.h>
-#endif
-
-#if defined(__GLIBC__) && !defined(__UCLIBC__)
-#include <gnu/libc-version.h>  /* gnu_get_libc_version() */
-#endif
-
-#undef NANOSEC
-#define NANOSEC ((uint64_t) 1e9)
-
-#if defined(PTHREAD_BARRIER_SERIAL_THREAD)
-STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
-#endif
-
-/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
-#if defined(_AIX) || \
-    defined(__OpenBSD__) || \
-    !defined(PTHREAD_BARRIER_SERIAL_THREAD)
-int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
-  struct _uv_barrier* b;
-  int rc;
-
-  if (barrier == NULL || count == 0)
-    return UV_EINVAL;
-
-  b = (_uv_barrier*)uv__malloc(sizeof(*b));
-  if (b == NULL)
-    return UV_ENOMEM;
-
-  b->in = 0;
-  b->out = 0;
-  b->threshold = count;
-
-  rc = uv_mutex_init(&b->mutex);
-  if (rc != 0)
-    goto error2;
-
-  rc = uv_cond_init(&b->cond);
-  if (rc != 0)
-    goto error;
-
-  barrier->b = b;
-  return 0;
-
-error:
-  uv_mutex_destroy(&b->mutex);
-error2:
-  uv__free(b);
-  return rc;
-}
-
-int uv_barrier_wait(uv_barrier_t* barrier) {
-  struct _uv_barrier* b;
-  int last;
-
-  if (barrier == NULL || barrier->b == NULL)
-    return UV_EINVAL;
-
-  b = barrier->b;
-  /* Lock the mutex*/
-  uv_mutex_lock(&b->mutex);
-
-  if (++b->in == b->threshold) {
-    b->in = 0;
-    b->out = b->threshold;
-    uv_cond_signal(&b->cond);
-  } else {
-    do
-      uv_cond_wait(&b->cond, &b->mutex);
-    while (b->in != 0);
-  }
-
-  last = (--b->out == 0);
-  if (!last)
-    uv_cond_signal(&b->cond);  /* Not needed for last thread. */
-
-  uv_mutex_unlock(&b->mutex);
-  return last;
-}
-
-void uv_barrier_destroy(uv_barrier_t* barrier) {
-  struct _uv_barrier* b;
-
-  b = barrier->b;
-  uv_mutex_lock(&b->mutex);
-
-  assert(b->in == 0);
-  assert(b->out == 0);
-
-  if (b->in != 0 || b->out != 0)
-    abort();
-
-  uv_mutex_unlock(&b->mutex);
-  uv_mutex_destroy(&b->mutex);
-  uv_cond_destroy(&b->cond);
-
-  uv__free(barrier->b);
-  barrier->b = NULL;
-}
-
-#else
-
-int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
-  return UV__ERR(pthread_barrier_init(barrier, NULL, count));
-}
-
-
-int uv_barrier_wait(uv_barrier_t* barrier) {
-  int rc;
-
-  rc = pthread_barrier_wait(barrier);
-  if (rc != 0)
-    if (rc != PTHREAD_BARRIER_SERIAL_THREAD)
-      abort();
-
-  return rc == PTHREAD_BARRIER_SERIAL_THREAD;
-}
-
-
-void uv_barrier_destroy(uv_barrier_t* barrier) {
-  if (pthread_barrier_destroy(barrier))
-    abort();
-}
-
-#endif
-
-
-/* On MacOS, threads other than the main thread are created with a reduced
- * stack size by default.  Adjust to RLIMIT_STACK aligned to the page size.
- *
- * On Linux, threads created by musl have a much smaller stack than threads
- * created by glibc (80 vs. 2048 or 4096 kB.)  Follow glibc for consistency.
- */
-static size_t thread_stack_size(void) {
-#if defined(__APPLE__) || defined(__linux__)
-  struct rlimit lim;
-
-  if (getrlimit(RLIMIT_STACK, &lim))
-    abort();
-
-  if (lim.rlim_cur != RLIM_INFINITY) {
-    /* pthread_attr_setstacksize() expects page-aligned values. */
-    lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
-
-    /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
-     * too small to safely receive signals on.
-     *
-     * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
-     * the largest MINSIGSTKSZ of the architectures that musl supports) so
-     * let's use that as a lower bound.
-     *
-     * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
-     * is between 28 and 133 KB when compiling against glibc, depending
-     * on the architecture.
-     */
-    if (lim.rlim_cur >= 8192)
-      if (lim.rlim_cur >= (rlim_t) PTHREAD_STACK_MIN)
-        return lim.rlim_cur;
-  }
-#endif
-
-#if !defined(__linux__)
-  return 0;
-#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
-  return 4 << 20;  /* glibc default. */
-#else
-  return 2 << 20;  /* glibc default. */
-#endif
-}
-
-
-int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
-  uv_thread_options_t params;
-  params.flags = UV_THREAD_NO_FLAGS;
-  return uv_thread_create_ex(tid, &params, entry, arg);
-}
-
-int uv_thread_create_ex(uv_thread_t* tid,
-                        const uv_thread_options_t* params,
-                        void (*entry)(void *arg),
-                        void *arg) {
-  int err;
-  pthread_attr_t* attr;
-  pthread_attr_t attr_storage;
-  size_t pagesize;
-  size_t stack_size;
-
-  stack_size =
-      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
-
-  attr = NULL;
-  if (stack_size == 0) {
-    stack_size = thread_stack_size();
-  } else {
-    pagesize = (size_t)getpagesize();
-    /* Round up to the nearest page boundary. */
-    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
-#ifdef PTHREAD_STACK_MIN
-    if (stack_size < (size_t) PTHREAD_STACK_MIN)
-      stack_size = PTHREAD_STACK_MIN;
-#endif
-  }
-
-  if (stack_size > 0) {
-    attr = &attr_storage;
-
-    if (pthread_attr_init(attr))
-      abort();
-
-    if (pthread_attr_setstacksize(attr, stack_size))
-      abort();
-  }
-
-  err = pthread_create(tid, attr, (void*(*)(void*)) (void(*)(void)) entry, arg);
-
-  if (attr != NULL)
-    pthread_attr_destroy(attr);
-
-  return UV__ERR(err);
-}
-
-
-uv_thread_t uv_thread_self(void) {
-  return pthread_self();
-}
-
-int uv_thread_join(uv_thread_t *tid) {
-  return UV__ERR(pthread_join(*tid, NULL));
-}
-
-
-int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
-  return pthread_equal(*t1, *t2);
-}
-
-
-int uv_mutex_init(uv_mutex_t* mutex) {
-#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
-  return UV__ERR(pthread_mutex_init(mutex, NULL));
-#else
-  pthread_mutexattr_t attr;
-  int err;
-
-  if (pthread_mutexattr_init(&attr))
-    abort();
-
-  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK))
-    abort();
-
-  err = pthread_mutex_init(mutex, &attr);
-
-  if (pthread_mutexattr_destroy(&attr))
-    abort();
-
-  return UV__ERR(err);
-#endif
-}
-
-
-int uv_mutex_init_recursive(uv_mutex_t* mutex) {
-  pthread_mutexattr_t attr;
-  int err;
-
-  if (pthread_mutexattr_init(&attr))
-    abort();
-
-  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
-    abort();
-
-  err = pthread_mutex_init(mutex, &attr);
-
-  if (pthread_mutexattr_destroy(&attr))
-    abort();
-
-  return UV__ERR(err);
-}
-
-
-void uv_mutex_destroy(uv_mutex_t* mutex) {
-  if (pthread_mutex_destroy(mutex))
-    abort();
-}
-
-
-void uv_mutex_lock(uv_mutex_t* mutex) {
-  if (pthread_mutex_lock(mutex))
-    abort();
-}
-
-
-int uv_mutex_trylock(uv_mutex_t* mutex) {
-  int err;
-
-  err = pthread_mutex_trylock(mutex);
-  if (err) {
-    if (err != EBUSY && err != EAGAIN)
-      abort();
-    return UV_EBUSY;
-  }
-
-  return 0;
-}
-
-
-void uv_mutex_unlock(uv_mutex_t* mutex) {
-  if (pthread_mutex_unlock(mutex))
-    abort();
-}
-
-
-int uv_rwlock_init(uv_rwlock_t* rwlock) {
-  return UV__ERR(pthread_rwlock_init(rwlock, NULL));
-}
-
-
-void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
-  if (pthread_rwlock_destroy(rwlock))
-    abort();
-}
-
-
-void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
-  if (pthread_rwlock_rdlock(rwlock))
-    abort();
-}
-
-
-int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
-  int err;
-
-  err = pthread_rwlock_tryrdlock(rwlock);
-  if (err) {
-    if (err != EBUSY && err != EAGAIN)
-      abort();
-    return UV_EBUSY;
-  }
-
-  return 0;
-}
-
-
-void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
-  if (pthread_rwlock_unlock(rwlock))
-    abort();
-}
-
-
-void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
-  if (pthread_rwlock_wrlock(rwlock))
-    abort();
-}
-
-
-int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
-  int err;
-
-  err = pthread_rwlock_trywrlock(rwlock);
-  if (err) {
-    if (err != EBUSY && err != EAGAIN)
-      abort();
-    return UV_EBUSY;
-  }
-
-  return 0;
-}
-
-
-void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
-  if (pthread_rwlock_unlock(rwlock))
-    abort();
-}
-
-
-void uv_once(uv_once_t* guard, void (*callback)(void)) {
-  if (pthread_once(guard, callback))
-    abort();
-}
-
-#if defined(__APPLE__) && defined(__MACH__)
-
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
-  kern_return_t err;
-
-  err = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value);
-  if (err == KERN_SUCCESS)
-    return 0;
-  if (err == KERN_INVALID_ARGUMENT)
-    return UV_EINVAL;
-  if (err == KERN_RESOURCE_SHORTAGE)
-    return UV_ENOMEM;
-
-  abort();
-  return UV_EINVAL;  /* Satisfy the compiler. */
-}
-
-
-void uv_sem_destroy(uv_sem_t* sem) {
-  if (semaphore_destroy(mach_task_self(), *sem))
-    abort();
-}
-
-
-void uv_sem_post(uv_sem_t* sem) {
-  if (semaphore_signal(*sem))
-    abort();
-}
-
-
-void uv_sem_wait(uv_sem_t* sem) {
-  int r;
-
-  do
-    r = semaphore_wait(*sem);
-  while (r == KERN_ABORTED);
-
-  if (r != KERN_SUCCESS)
-    abort();
-}
-
-
-int uv_sem_trywait(uv_sem_t* sem) {
-  mach_timespec_t interval;
-  kern_return_t err;
-
-  interval.tv_sec = 0;
-  interval.tv_nsec = 0;
-
-  err = semaphore_timedwait(*sem, interval);
-  if (err == KERN_SUCCESS)
-    return 0;
-  if (err == KERN_OPERATION_TIMED_OUT)
-    return UV_EAGAIN;
-
-  abort();
-  return UV_EINVAL;  /* Satisfy the compiler. */
-}
-
-#else /* !(defined(__APPLE__) && defined(__MACH__)) */
-
-#if defined(__GLIBC__) && !defined(__UCLIBC__)
-
-/* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
- * by providing a custom implementation for glibc < 2.21 in terms of other
- * concurrency primitives.
- * Refs: https://github.com/nodejs/node/issues/19903 */
-
-/* To preserve ABI compatibility, we treat the uv_sem_t as storage for
- * a pointer to the actual struct we're using underneath. */
-
-static uv_once_t glibc_version_check_once = UV_ONCE_INIT;
-static int platform_needs_custom_semaphore = 0;
-
-static void glibc_version_check(void) {
-  const char* version = gnu_get_libc_version();
-  platform_needs_custom_semaphore =
-      version[0] == '2' && version[1] == '.' &&
-      atoi(version + 2) < 21;
-}
-
-#elif defined(__MVS__)
-
-#define platform_needs_custom_semaphore 1
-
-#else /* !defined(__GLIBC__) && !defined(__MVS__) */
-
-#define platform_needs_custom_semaphore 0
-
-#endif
-
-typedef struct uv_semaphore_s {
-  uv_mutex_t mutex;
-  uv_cond_t cond;
-  unsigned int value;
-} uv_semaphore_t;
-
-#if (defined(__GLIBC__) && !defined(__UCLIBC__)) || \
-    platform_needs_custom_semaphore
-STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
-#endif
-
-static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
-  int err;
-  uv_semaphore_t* sem;
-
-  sem = (uv_semaphore_t*)uv__malloc(sizeof(*sem));
-  if (sem == NULL)
-    return UV_ENOMEM;
-
-  if ((err = uv_mutex_init(&sem->mutex)) != 0) {
-    uv__free(sem);
-    return err;
-  }
-
-  if ((err = uv_cond_init(&sem->cond)) != 0) {
-    uv_mutex_destroy(&sem->mutex);
-    uv__free(sem);
-    return err;
-  }
-
-  sem->value = value;
-  *(uv_semaphore_t**)sem_ = sem;
-  return 0;
-}
-
-
-static void uv__custom_sem_destroy(uv_sem_t* sem_) {
-  uv_semaphore_t* sem;
-
-  sem = *(uv_semaphore_t**)sem_;
-  uv_cond_destroy(&sem->cond);
-  uv_mutex_destroy(&sem->mutex);
-  uv__free(sem);
-}
-
-
-static void uv__custom_sem_post(uv_sem_t* sem_) {
-  uv_semaphore_t* sem;
-
-  sem = *(uv_semaphore_t**)sem_;
-  uv_mutex_lock(&sem->mutex);
-  sem->value++;
-  if (sem->value == 1)
-    uv_cond_signal(&sem->cond);
-  uv_mutex_unlock(&sem->mutex);
-}
-
-
-static void uv__custom_sem_wait(uv_sem_t* sem_) {
-  uv_semaphore_t* sem;
-
-  sem = *(uv_semaphore_t**)sem_;
-  uv_mutex_lock(&sem->mutex);
-  while (sem->value == 0)
-    uv_cond_wait(&sem->cond, &sem->mutex);
-  sem->value--;
-  uv_mutex_unlock(&sem->mutex);
-}
-
-
-static int uv__custom_sem_trywait(uv_sem_t* sem_) {
-  uv_semaphore_t* sem;
-
-  sem = *(uv_semaphore_t**)sem_;
-  if (uv_mutex_trylock(&sem->mutex) != 0)
-    return UV_EAGAIN;
-
-  if (sem->value == 0) {
-    uv_mutex_unlock(&sem->mutex);
-    return UV_EAGAIN;
-  }
-
-  sem->value--;
-  uv_mutex_unlock(&sem->mutex);
-
-  return 0;
-}
-
-static int uv__sem_init(uv_sem_t* sem, unsigned int value) {
-  if (sem_init(sem, 0, value))
-    return UV__ERR(errno);
-  return 0;
-}
-
-
-static void uv__sem_destroy(uv_sem_t* sem) {
-  if (sem_destroy(sem))
-    abort();
-}
-
-
-static void uv__sem_post(uv_sem_t* sem) {
-  if (sem_post(sem))
-    abort();
-}
-
-
-static void uv__sem_wait(uv_sem_t* sem) {
-  int r;
-
-  do
-    r = sem_wait(sem);
-  while (r == -1 && errno == EINTR);
-
-  if (r)
-    abort();
-}
-
-
-static int uv__sem_trywait(uv_sem_t* sem) {
-  int r;
-
-  do
-    r = sem_trywait(sem);
-  while (r == -1 && errno == EINTR);
-
-  if (r) {
-    if (errno == EAGAIN)
-      return UV_EAGAIN;
-    abort();
-  }
-
-  return 0;
-}
-
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
-#if defined(__GLIBC__) && !defined(__UCLIBC__)
-  uv_once(&glibc_version_check_once, glibc_version_check);
-#endif
-
-  if (platform_needs_custom_semaphore)
-    return uv__custom_sem_init(sem, value);
-  else
-    return uv__sem_init(sem, value);
-}
-
-
-void uv_sem_destroy(uv_sem_t* sem) {
-  if (platform_needs_custom_semaphore)
-    uv__custom_sem_destroy(sem);
-  else
-    uv__sem_destroy(sem);
-}
-
-
-void uv_sem_post(uv_sem_t* sem) {
-  if (platform_needs_custom_semaphore)
-    uv__custom_sem_post(sem);
-  else
-    uv__sem_post(sem);
-}
-
-
-void uv_sem_wait(uv_sem_t* sem) {
-  if (platform_needs_custom_semaphore)
-    uv__custom_sem_wait(sem);
-  else
-    uv__sem_wait(sem);
-}
-
-
-int uv_sem_trywait(uv_sem_t* sem) {
-  if (platform_needs_custom_semaphore)
-    return uv__custom_sem_trywait(sem);
-  else
-    return uv__sem_trywait(sem);
-}
-
-#endif /* defined(__APPLE__) && defined(__MACH__) */
-
-
-#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__)
-
-int uv_cond_init(uv_cond_t* cond) {
-  return UV__ERR(pthread_cond_init(cond, NULL));
-}
-
-#else /* !(defined(__APPLE__) && defined(__MACH__)) */
-
-int uv_cond_init(uv_cond_t* cond) {
-  pthread_condattr_t attr;
-  int err;
-
-  err = pthread_condattr_init(&attr);
-  if (err)
-    return UV__ERR(err);
-
-#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21)
-  err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
-  if (err)
-    goto error2;
-#endif
-
-  err = pthread_cond_init(cond, &attr);
-  if (err)
-    goto error2;
-
-  err = pthread_condattr_destroy(&attr);
-  if (err)
-    goto error;
-
-  return 0;
-
-error:
-  pthread_cond_destroy(cond);
-error2:
-  pthread_condattr_destroy(&attr);
-  return UV__ERR(err);
-}
-
-#endif /* defined(__APPLE__) && defined(__MACH__) */
-
-void uv_cond_destroy(uv_cond_t* cond) {
-#if defined(__APPLE__) && defined(__MACH__)
-  /* It has been reported that destroying condition variables that have been
-   * signalled but not waited on can sometimes result in application crashes.
-   * See https://codereview.chromium.org/1323293005.
-   */
-  pthread_mutex_t mutex;
-  struct timespec ts;
-  int err;
-
-  if (pthread_mutex_init(&mutex, NULL))
-    abort();
-
-  if (pthread_mutex_lock(&mutex))
-    abort();
-
-  ts.tv_sec = 0;
-  ts.tv_nsec = 1;
-
-  err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
-  if (err != 0 && err != ETIMEDOUT)
-    abort();
-
-  if (pthread_mutex_unlock(&mutex))
-    abort();
-
-  if (pthread_mutex_destroy(&mutex))
-    abort();
-#endif /* defined(__APPLE__) && defined(__MACH__) */
-
-  if (pthread_cond_destroy(cond))
-    abort();
-}
-
-void uv_cond_signal(uv_cond_t* cond) {
-  if (pthread_cond_signal(cond))
-    abort();
-}
-
-void uv_cond_broadcast(uv_cond_t* cond) {
-  if (pthread_cond_broadcast(cond))
-    abort();
-}
-
-void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
-  if (pthread_cond_wait(cond, mutex))
-    abort();
-}
-
-
-int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
-  int r;
-  struct timespec ts;
-#if defined(__MVS__)
-  struct timeval tv;
-#endif
-
-#if defined(__APPLE__) && defined(__MACH__)
-  ts.tv_sec = timeout / NANOSEC;
-  ts.tv_nsec = timeout % NANOSEC;
-  r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
-#else
-#if defined(__MVS__)
-  if (gettimeofday(&tv, NULL))
-    abort();
-  timeout += tv.tv_sec * NANOSEC + tv.tv_usec * 1e3;
-#else
-  timeout += uv__hrtime(UV_CLOCK_PRECISE);
-#endif
-  ts.tv_sec = timeout / NANOSEC;
-  ts.tv_nsec = timeout % NANOSEC;
-#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
-
-  /*
-   * The bionic pthread implementation doesn't support CLOCK_MONOTONIC,
-   * but has this alternative function instead.
-   */
-  r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts);
-#else
-  r = pthread_cond_timedwait(cond, mutex, &ts);
-#endif /* __ANDROID_API__ */
-#endif
-
-
-  if (r == 0)
-    return 0;
-
-  if (r == ETIMEDOUT)
-    return UV_ETIMEDOUT;
-
-  abort();
-#ifndef __SUNPRO_C
-  return UV_EINVAL;  /* Satisfy the compiler. */
-#endif
-}
-
-
-int uv_key_create(uv_key_t* key) {
-  return UV__ERR(pthread_key_create(key, NULL));
-}
-
-
-void uv_key_delete(uv_key_t* key) {
-  if (pthread_key_delete(*key))
-    abort();
-}
-
-
-void* uv_key_get(uv_key_t* key) {
-  return pthread_getspecific(*key);
-}
-
-
-void uv_key_set(uv_key_t* key, void* value) {
-  if (pthread_setspecific(*key, value))
-    abort();
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/tty.cpp b/wpiutil/src/main/native/libuv/src/unix/tty.cpp
deleted file mode 100644
index 5f68140..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/tty.cpp
+++ /dev/null
@@ -1,368 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-#include "spinlock.h"
-
-#include <stdlib.h>
-#include <assert.h>
-#include <unistd.h>
-#include <termios.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-#if defined(__MVS__) && !defined(IMAXBEL)
-#define IMAXBEL 0
-#endif
-
-static int orig_termios_fd = -1;
-static struct termios orig_termios;
-static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER;
-
-static int uv__tty_is_peripheral(const int fd) {
-  int result;
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-  int dummy;
-
-  result = ioctl(fd, TIOCGPTN, &dummy) != 0;
-#elif defined(__APPLE__)
-  char dummy[256];
-
-  result = ioctl(fd, TIOCPTYGNAME, &dummy) != 0;
-#elif defined(__NetBSD__)
-  /*
-   * NetBSD as an extension returns with ptsname(3) and ptsname_r(3) the
-   * peripheral device name for both descriptors, the controller one and
-   * peripheral one.
-   *
-   * Implement function to compare major device number with pts devices.
-   *
-   * The major numbers are machine-dependent, on NetBSD/amd64 they are
-   * respectively:
-   *  - controller tty: ptc - major 6
-   *  - peripheral tty:  pts - major 5
-   */
-
-  struct stat sb;
-  /* Lookup device's major for the pts driver and cache it. */
-  static devmajor_t pts = NODEVMAJOR;
-
-  if (pts == NODEVMAJOR) {
-    pts = getdevmajor("pts", S_IFCHR);
-    if (pts == NODEVMAJOR)
-      abort();
-  }
-
-  /* Lookup stat structure behind the file descriptor. */
-  if (fstat(fd, &sb) != 0)
-    abort();
-
-  /* Assert character device. */
-  if (!S_ISCHR(sb.st_mode))
-    abort();
-
-  /* Assert valid major. */
-  if (major(sb.st_rdev) == NODEVMAJOR)
-    abort();
-
-  result = (pts == major(sb.st_rdev));
-#else
-  /* Fallback to ptsname
-   */
-  result = ptsname(fd) == NULL;
-#endif
-  return result;
-}
-
-int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) {
-  uv_handle_type type;
-  int flags;
-  int newfd;
-  int r;
-  int saved_flags;
-  int mode;
-  char path[256];
-  (void)unused; /* deprecated parameter is no longer needed */
-
-  /* File descriptors that refer to files cannot be monitored with epoll.
-   * That restriction also applies to character devices like /dev/random
-   * (but obviously not /dev/tty.)
-   */
-  type = uv_guess_handle(fd);
-  if (type == UV_FILE || type == UV_UNKNOWN_HANDLE)
-    return UV_EINVAL;
-
-  flags = 0;
-  newfd = -1;
-
-  /* Save the fd flags in case we need to restore them due to an error. */
-  do
-    saved_flags = fcntl(fd, F_GETFL);
-  while (saved_flags == -1 && errno == EINTR);
-
-  if (saved_flags == -1)
-    return UV__ERR(errno);
-  mode = saved_flags & O_ACCMODE;
-
-  /* Reopen the file descriptor when it refers to a tty. This lets us put the
-   * tty in non-blocking mode without affecting other processes that share it
-   * with us.
-   *
-   * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also
-   * affects fd 1 of `cat` because both file descriptors refer to the same
-   * struct file in the kernel. When we reopen our fd 0, it points to a
-   * different struct file, hence changing its properties doesn't affect
-   * other processes.
-   */
-  if (type == UV_TTY) {
-    /* Reopening a pty in controller mode won't work either because the reopened
-     * pty will be in peripheral mode (*BSD) or reopening will allocate a new
-     * controller/peripheral pair (Linux). Therefore check if the fd points to a
-     * peripheral device.
-     */
-    if (uv__tty_is_peripheral(fd) && ttyname_r(fd, path, sizeof(path)) == 0)
-      r = uv__open_cloexec(path, mode);
-    else
-      r = -1;
-
-    if (r < 0) {
-      /* fallback to using blocking writes */
-      if (mode != O_RDONLY)
-        flags |= UV_HANDLE_BLOCKING_WRITES;
-      goto skip;
-    }
-
-    newfd = r;
-
-    r = uv__dup2_cloexec(newfd, fd);
-    if (r < 0 && r != UV_EINVAL) {
-      /* EINVAL means newfd == fd which could conceivably happen if another
-       * thread called close(fd) between our calls to isatty() and open().
-       * That's a rather unlikely event but let's handle it anyway.
-       */
-      uv__close(newfd);
-      return r;
-    }
-
-    fd = newfd;
-  }
-
-skip:
-  uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY);
-
-  /* If anything fails beyond this point we need to remove the handle from
-   * the handle queue, since it was added by uv__handle_init in uv_stream_init.
-   */
-
-  if (!(flags & UV_HANDLE_BLOCKING_WRITES))
-    uv__nonblock(fd, 1);
-
-#if defined(__APPLE__)
-  r = uv__stream_try_select((uv_stream_t*) tty, &fd);
-  if (r) {
-    int rc = r;
-    if (newfd != -1)
-      uv__close(newfd);
-    QUEUE_REMOVE(&tty->handle_queue);
-    do
-      r = fcntl(fd, F_SETFL, saved_flags);
-    while (r == -1 && errno == EINTR);
-    return rc;
-  }
-#endif
-
-  if (mode != O_WRONLY)
-    flags |= UV_HANDLE_READABLE;
-  if (mode != O_RDONLY)
-    flags |= UV_HANDLE_WRITABLE;
-
-  uv__stream_open((uv_stream_t*) tty, fd, flags);
-  tty->mode = UV_TTY_MODE_NORMAL;
-
-  return 0;
-}
-
-static void uv__tty_make_raw(struct termios* tio) {
-  assert(tio != NULL);
-
-#if defined __sun || defined __MVS__
-  /*
-   * This implementation of cfmakeraw for Solaris and derivatives is taken from
-   * http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html.
-   */
-  tio->c_iflag &= ~(IMAXBEL | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR |
-                    IGNCR | ICRNL | IXON);
-  tio->c_oflag &= ~OPOST;
-  tio->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
-  tio->c_cflag &= ~(CSIZE | PARENB);
-  tio->c_cflag |= CS8;
-#else
-  cfmakeraw(tio);
-#endif /* #ifdef __sun */
-}
-
-int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
-  struct termios tmp;
-  int fd;
-
-  if (tty->mode == (int) mode)
-    return 0;
-
-  fd = uv__stream_fd(tty);
-  if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
-    if (tcgetattr(fd, &tty->orig_termios))
-      return UV__ERR(errno);
-
-    /* This is used for uv_tty_reset_mode() */
-    uv_spinlock_lock(&termios_spinlock);
-    if (orig_termios_fd == -1) {
-      orig_termios = tty->orig_termios;
-      orig_termios_fd = fd;
-    }
-    uv_spinlock_unlock(&termios_spinlock);
-  }
-
-  tmp = tty->orig_termios;
-  switch (mode) {
-    case UV_TTY_MODE_NORMAL:
-      break;
-    case UV_TTY_MODE_RAW:
-      tmp.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
-      tmp.c_oflag |= (ONLCR);
-      tmp.c_cflag |= (CS8);
-      tmp.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
-      tmp.c_cc[VMIN] = 1;
-      tmp.c_cc[VTIME] = 0;
-      break;
-    case UV_TTY_MODE_IO:
-      uv__tty_make_raw(&tmp);
-      break;
-  }
-
-  /* Apply changes after draining */
-  if (tcsetattr(fd, TCSADRAIN, &tmp))
-    return UV__ERR(errno);
-
-  tty->mode = mode;
-  return 0;
-}
-
-
-int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
-  struct winsize ws;
-  int err;
-
-  do
-    err = ioctl(uv__stream_fd(tty), TIOCGWINSZ, &ws);
-  while (err == -1 && errno == EINTR);
-
-  if (err == -1)
-    return UV__ERR(errno);
-
-  *width = ws.ws_col;
-  *height = ws.ws_row;
-
-  return 0;
-}
-
-
-uv_handle_type uv_guess_handle(uv_file file) {
-  struct sockaddr sa;
-  struct stat s;
-  socklen_t len;
-  int type;
-
-  if (file < 0)
-    return UV_UNKNOWN_HANDLE;
-
-  if (isatty(file))
-    return UV_TTY;
-
-  if (fstat(file, &s))
-    return UV_UNKNOWN_HANDLE;
-
-  if (S_ISREG(s.st_mode))
-    return UV_FILE;
-
-  if (S_ISCHR(s.st_mode))
-    return UV_FILE;  /* XXX UV_NAMED_PIPE? */
-
-  if (S_ISFIFO(s.st_mode))
-    return UV_NAMED_PIPE;
-
-  if (!S_ISSOCK(s.st_mode))
-    return UV_UNKNOWN_HANDLE;
-
-  len = sizeof(type);
-  if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len))
-    return UV_UNKNOWN_HANDLE;
-
-  len = sizeof(sa);
-  if (getsockname(file, &sa, &len))
-    return UV_UNKNOWN_HANDLE;
-
-  if (type == SOCK_DGRAM)
-    if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
-      return UV_UDP;
-
-  if (type == SOCK_STREAM) {
-#if defined(_AIX) || defined(__DragonFly__)
-    /* on AIX/DragonFly the getsockname call returns an empty sa structure
-     * for sockets of type AF_UNIX.  For all other types it will
-     * return a properly filled in structure.
-     */
-    if (len == 0)
-      return UV_NAMED_PIPE;
-#endif /* defined(_AIX) || defined(__DragonFly__) */
-
-    if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6)
-      return UV_TCP;
-    if (sa.sa_family == AF_UNIX)
-      return UV_NAMED_PIPE;
-  }
-
-  return UV_UNKNOWN_HANDLE;
-}
-
-
-/* This function is async signal-safe, meaning that it's safe to call from
- * inside a signal handler _unless_ execution was inside uv_tty_set_mode()'s
- * critical section when the signal was raised.
- */
-int uv_tty_reset_mode(void) {
-  int saved_errno;
-  int err;
-
-  saved_errno = errno;
-  if (!uv_spinlock_trylock(&termios_spinlock))
-    return UV_EBUSY;  /* In uv_tty_set_mode(). */
-
-  err = 0;
-  if (orig_termios_fd != -1)
-    if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios))
-      err = UV__ERR(errno);
-
-  uv_spinlock_unlock(&termios_spinlock);
-  errno = saved_errno;
-
-  return err;
-}
diff --git a/wpiutil/src/main/native/libuv/src/unix/udp.cpp b/wpiutil/src/main/native/libuv/src/unix/udp.cpp
deleted file mode 100644
index 5c03ae1..0000000
--- a/wpiutil/src/main/native/libuv/src/unix/udp.cpp
+++ /dev/null
@@ -1,999 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-#include <assert.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#if defined(__MVS__)
-#include <xti.h>
-#endif
-#include <sys/un.h>
-
-#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
-# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
-#endif
-
-#if defined(IPV6_LEAVE_GROUP) && !defined(IPV6_DROP_MEMBERSHIP)
-# define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
-#endif
-
-
-static void uv__udp_run_completed(uv_udp_t* handle);
-static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents);
-static void uv__udp_recvmsg(uv_udp_t* handle);
-static void uv__udp_sendmsg(uv_udp_t* handle);
-static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
-                                       int domain,
-                                       unsigned int flags);
-
-
-void uv__udp_close(uv_udp_t* handle) {
-  uv__io_close(handle->loop, &handle->io_watcher);
-  uv__handle_stop(handle);
-
-  if (handle->io_watcher.fd != -1) {
-    uv__close(handle->io_watcher.fd);
-    handle->io_watcher.fd = -1;
-  }
-}
-
-
-void uv__udp_finish_close(uv_udp_t* handle) {
-  uv_udp_send_t* req;
-  QUEUE* q;
-
-  assert(!uv__io_active(&handle->io_watcher, POLLIN | POLLOUT));
-  assert(handle->io_watcher.fd == -1);
-
-  while (!QUEUE_EMPTY(&handle->write_queue)) {
-    q = QUEUE_HEAD(&handle->write_queue);
-    QUEUE_REMOVE(q);
-
-    req = QUEUE_DATA(q, uv_udp_send_t, queue);
-    req->status = UV_ECANCELED;
-    QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
-  }
-
-  uv__udp_run_completed(handle);
-
-  assert(handle->send_queue_size == 0);
-  assert(handle->send_queue_count == 0);
-
-  /* Now tear down the handle. */
-  handle->recv_cb = NULL;
-  handle->alloc_cb = NULL;
-  /* but _do not_ touch close_cb */
-}
-
-
-static void uv__udp_run_completed(uv_udp_t* handle) {
-  uv_udp_send_t* req;
-  QUEUE* q;
-
-  assert(!(handle->flags & UV_HANDLE_UDP_PROCESSING));
-  handle->flags |= UV_HANDLE_UDP_PROCESSING;
-
-  while (!QUEUE_EMPTY(&handle->write_completed_queue)) {
-    q = QUEUE_HEAD(&handle->write_completed_queue);
-    QUEUE_REMOVE(q);
-
-    req = QUEUE_DATA(q, uv_udp_send_t, queue);
-    uv__req_unregister(handle->loop, req);
-
-    handle->send_queue_size -= uv__count_bufs(req->bufs, req->nbufs);
-    handle->send_queue_count--;
-
-    if (req->bufs != req->bufsml)
-      uv__free(req->bufs);
-    req->bufs = NULL;
-
-    if (req->send_cb == NULL)
-      continue;
-
-    /* req->status >= 0 == bytes written
-     * req->status <  0 == errno
-     */
-    if (req->status >= 0)
-      req->send_cb(req, 0);
-    else
-      req->send_cb(req, req->status);
-  }
-
-  if (QUEUE_EMPTY(&handle->write_queue)) {
-    /* Pending queue and completion queue empty, stop watcher. */
-    uv__io_stop(handle->loop, &handle->io_watcher, POLLOUT);
-    if (!uv__io_active(&handle->io_watcher, POLLIN))
-      uv__handle_stop(handle);
-  }
-
-  handle->flags &= ~UV_HANDLE_UDP_PROCESSING;
-}
-
-
-static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) {
-  uv_udp_t* handle;
-
-  handle = container_of(w, uv_udp_t, io_watcher);
-  assert(handle->type == UV_UDP);
-
-  if (revents & POLLIN)
-    uv__udp_recvmsg(handle);
-
-  if (revents & POLLOUT) {
-    uv__udp_sendmsg(handle);
-    uv__udp_run_completed(handle);
-  }
-}
-
-
-static void uv__udp_recvmsg(uv_udp_t* handle) {
-  struct sockaddr_storage peer;
-  struct msghdr h;
-  ssize_t nread;
-  uv_buf_t buf;
-  int flags;
-  int count;
-
-  assert(handle->recv_cb != NULL);
-  assert(handle->alloc_cb != NULL);
-
-  /* Prevent loop starvation when the data comes in as fast as (or faster than)
-   * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
-   */
-  count = 32;
-
-  memset(&h, 0, sizeof(h));
-  h.msg_name = &peer;
-
-  do {
-    buf = uv_buf_init(NULL, 0);
-    handle->alloc_cb((uv_handle_t*) handle, 64 * 1024, &buf);
-    if (buf.base == NULL || buf.len == 0) {
-      handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
-      return;
-    }
-    assert(buf.base != NULL);
-
-    h.msg_namelen = sizeof(peer);
-    h.msg_iov = (iovec*) &buf;
-    h.msg_iovlen = 1;
-
-    do {
-      nread = recvmsg(handle->io_watcher.fd, &h, 0);
-    }
-    while (nread == -1 && errno == EINTR);
-
-    if (nread == -1) {
-      if (errno == EAGAIN || errno == EWOULDBLOCK)
-        handle->recv_cb(handle, 0, &buf, NULL, 0);
-      else
-        handle->recv_cb(handle, UV__ERR(errno), &buf, NULL, 0);
-    }
-    else {
-      const struct sockaddr *addr;
-      if (h.msg_namelen == 0)
-        addr = NULL;
-      else
-        addr = (const struct sockaddr*) &peer;
-
-      flags = 0;
-      if (h.msg_flags & MSG_TRUNC)
-        flags |= UV_UDP_PARTIAL;
-
-      handle->recv_cb(handle, nread, &buf, addr, flags);
-    }
-  }
-  /* recv_cb callback may decide to pause or close the handle */
-  while (nread != -1
-      && count-- > 0
-      && handle->io_watcher.fd != -1
-      && handle->recv_cb != NULL);
-}
-
-
-static void uv__udp_sendmsg(uv_udp_t* handle) {
-  uv_udp_send_t* req;
-  QUEUE* q;
-  struct msghdr h;
-  ssize_t size;
-
-  while (!QUEUE_EMPTY(&handle->write_queue)) {
-    q = QUEUE_HEAD(&handle->write_queue);
-    assert(q != NULL);
-
-    req = QUEUE_DATA(q, uv_udp_send_t, queue);
-    assert(req != NULL);
-
-    memset(&h, 0, sizeof h);
-    if (req->addr.ss_family == AF_UNSPEC) {
-      h.msg_name = NULL;
-      h.msg_namelen = 0;
-    } else {
-      h.msg_name = &req->addr;
-      if (req->addr.ss_family == AF_INET6)
-        h.msg_namelen = sizeof(struct sockaddr_in6);
-      else if (req->addr.ss_family == AF_INET)
-        h.msg_namelen = sizeof(struct sockaddr_in);
-      else if (req->addr.ss_family == AF_UNIX)
-        h.msg_namelen = sizeof(struct sockaddr_un);
-      else {
-        assert(0 && "unsupported address family");
-        abort();
-      }
-    }
-    h.msg_iov = (struct iovec*) req->bufs;
-    h.msg_iovlen = req->nbufs;
-
-    do {
-      size = sendmsg(handle->io_watcher.fd, &h, 0);
-    } while (size == -1 && errno == EINTR);
-
-    if (size == -1) {
-      if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
-        break;
-    }
-
-    req->status = (size == -1 ? UV__ERR(errno) : size);
-
-    /* Sending a datagram is an atomic operation: either all data
-     * is written or nothing is (and EMSGSIZE is raised). That is
-     * why we don't handle partial writes. Just pop the request
-     * off the write queue and onto the completed queue, done.
-     */
-    QUEUE_REMOVE(&req->queue);
-    QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
-    uv__io_feed(handle->loop, &handle->io_watcher);
-  }
-}
-
-
-/* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional
- * refinements for programs that use multicast.
- *
- * Linux as of 3.9 has a SO_REUSEPORT socket option but with semantics that
- * are different from the BSDs: it _shares_ the port rather than steal it
- * from the current listener.  While useful, it's not something we can emulate
- * on other platforms so we don't enable it.
- *
- * zOS does not support getsockname with SO_REUSEPORT option when using
- * AF_UNIX.
- */
-static int uv__set_reuse(int fd) {
-  int yes;
-  yes = 1;
-
-#if defined(SO_REUSEPORT) && defined(__MVS__)
-  struct sockaddr_in sockfd;
-  unsigned int sockfd_len = sizeof(sockfd);
-  if (getsockname(fd, (struct sockaddr*) &sockfd, &sockfd_len) == -1)
-      return UV__ERR(errno);
-  if (sockfd.sin_family == AF_UNIX) {
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
-      return UV__ERR(errno);
-  } else {
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
-       return UV__ERR(errno);
-  }
-#elif defined(SO_REUSEPORT) && !defined(__linux__)
-  if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
-    return UV__ERR(errno);
-#else
-  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
-    return UV__ERR(errno);
-#endif
-
-  return 0;
-}
-
-
-int uv__udp_bind(uv_udp_t* handle,
-                 const struct sockaddr* addr,
-                 unsigned int addrlen,
-                 unsigned int flags) {
-  int err;
-  int yes;
-  int fd;
-
-  /* Check for bad flags. */
-  if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR))
-    return UV_EINVAL;
-
-  /* Cannot set IPv6-only mode on non-IPv6 socket. */
-  if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6)
-    return UV_EINVAL;
-
-  fd = handle->io_watcher.fd;
-  if (fd == -1) {
-    err = uv__socket(addr->sa_family, SOCK_DGRAM, 0);
-    if (err < 0)
-      return err;
-    fd = err;
-    handle->io_watcher.fd = fd;
-  }
-
-  if (flags & UV_UDP_REUSEADDR) {
-    err = uv__set_reuse(fd);
-    if (err)
-      return err;
-  }
-
-  if (flags & UV_UDP_IPV6ONLY) {
-#ifdef IPV6_V6ONLY
-    yes = 1;
-    if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) {
-      err = UV__ERR(errno);
-      return err;
-    }
-#else
-    err = UV_ENOTSUP;
-    return err;
-#endif
-  }
-
-  if (bind(fd, addr, addrlen)) {
-    err = UV__ERR(errno);
-    if (errno == EAFNOSUPPORT)
-      /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
-       * socket created with AF_INET to an AF_INET6 address or vice versa. */
-      err = UV_EINVAL;
-    return err;
-  }
-
-  if (addr->sa_family == AF_INET6)
-    handle->flags |= UV_HANDLE_IPV6;
-
-  handle->flags |= UV_HANDLE_BOUND;
-  return 0;
-}
-
-
-static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
-                                       int domain,
-                                       unsigned int flags) {
-  union {
-    struct sockaddr_in6 in6;
-    struct sockaddr_in in;
-    struct sockaddr addr;
-  } taddr;
-  socklen_t addrlen;
-
-  if (handle->io_watcher.fd != -1)
-    return 0;
-
-  switch (domain) {
-  case AF_INET:
-  {
-    struct sockaddr_in* addr = &taddr.in;
-    memset(addr, 0, sizeof *addr);
-    addr->sin_family = AF_INET;
-    addr->sin_addr.s_addr = INADDR_ANY;
-    addrlen = sizeof *addr;
-    break;
-  }
-  case AF_INET6:
-  {
-    struct sockaddr_in6* addr = &taddr.in6;
-    memset(addr, 0, sizeof *addr);
-    addr->sin6_family = AF_INET6;
-    addr->sin6_addr = in6addr_any;
-    addrlen = sizeof *addr;
-    break;
-  }
-  default:
-    assert(0 && "unsupported address family");
-    abort();
-  }
-
-  return uv__udp_bind(handle, &taddr.addr, addrlen, flags);
-}
-
-
-int uv__udp_connect(uv_udp_t* handle,
-                    const struct sockaddr* addr,
-                    unsigned int addrlen) {
-  int err;
-
-  err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
-  if (err)
-    return err;
-
-  do {
-    errno = 0;
-    err = connect(handle->io_watcher.fd, addr, addrlen);
-  } while (err == -1 && errno == EINTR);
-
-  if (err)
-    return UV__ERR(errno);
-
-  handle->flags |= UV_HANDLE_UDP_CONNECTED;
-
-  return 0;
-}
-
-
-int uv__udp_disconnect(uv_udp_t* handle) {
-    int r;
-    struct sockaddr addr;
-
-    memset(&addr, 0, sizeof(addr));
-
-    addr.sa_family = AF_UNSPEC;
-
-    do {
-      errno = 0;
-      r = connect(handle->io_watcher.fd, &addr, sizeof(addr));
-    } while (r == -1 && errno == EINTR);
-
-    if (r == -1 && errno != EAFNOSUPPORT)
-      return UV__ERR(errno);
-
-    handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
-    return 0;
-}
-
-
-int uv__udp_send(uv_udp_send_t* req,
-                 uv_udp_t* handle,
-                 const uv_buf_t bufs[],
-                 unsigned int nbufs,
-                 const struct sockaddr* addr,
-                 unsigned int addrlen,
-                 uv_udp_send_cb send_cb) {
-  int err;
-  int empty_queue;
-
-  assert(nbufs > 0);
-
-  if (addr) {
-    err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
-    if (err)
-      return err;
-  }
-
-  /* It's legal for send_queue_count > 0 even when the write_queue is empty;
-   * it means there are error-state requests in the write_completed_queue that
-   * will touch up send_queue_size/count later.
-   */
-  empty_queue = (handle->send_queue_count == 0);
-
-  uv__req_init(handle->loop, req, UV_UDP_SEND);
-  assert(addrlen <= sizeof(req->addr));
-  if (addr == NULL)
-    req->addr.ss_family = AF_UNSPEC;
-  else
-    memcpy(&req->addr, addr, addrlen);
-  req->send_cb = send_cb;
-  req->handle = handle;
-  req->nbufs = nbufs;
-
-  req->bufs = req->bufsml;
-  if (nbufs > ARRAY_SIZE(req->bufsml))
-    req->bufs = (uv_buf_t*)uv__malloc(nbufs * sizeof(bufs[0]));
-
-  if (req->bufs == NULL) {
-    uv__req_unregister(handle->loop, req);
-    return UV_ENOMEM;
-  }
-
-  memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
-  handle->send_queue_size += uv__count_bufs(req->bufs, req->nbufs);
-  handle->send_queue_count++;
-  QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue);
-  uv__handle_start(handle);
-
-  if (empty_queue && !(handle->flags & UV_HANDLE_UDP_PROCESSING)) {
-    uv__udp_sendmsg(handle);
-
-    /* `uv__udp_sendmsg` may not be able to do non-blocking write straight
-     * away. In such cases the `io_watcher` has to be queued for asynchronous
-     * write.
-     */
-    if (!QUEUE_EMPTY(&handle->write_queue))
-      uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
-  } else {
-    uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
-  }
-
-  return 0;
-}
-
-
-int uv__udp_try_send(uv_udp_t* handle,
-                     const uv_buf_t bufs[],
-                     unsigned int nbufs,
-                     const struct sockaddr* addr,
-                     unsigned int addrlen) {
-  int err;
-  struct msghdr h;
-  ssize_t size;
-
-  assert(nbufs > 0);
-
-  /* already sending a message */
-  if (handle->send_queue_count != 0)
-    return UV_EAGAIN;
-
-  if (addr) {
-    err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
-    if (err)
-      return err;
-  } else {
-    assert(handle->flags & UV_HANDLE_UDP_CONNECTED);
-  }
-
-  memset(&h, 0, sizeof h);
-  h.msg_name = (struct sockaddr*) addr;
-  h.msg_namelen = addrlen;
-  h.msg_iov = (struct iovec*) bufs;
-  h.msg_iovlen = nbufs;
-
-  do {
-    size = sendmsg(handle->io_watcher.fd, &h, 0);
-  } while (size == -1 && errno == EINTR);
-
-  if (size == -1) {
-    if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
-      return UV_EAGAIN;
-    else
-      return UV__ERR(errno);
-  }
-
-  return size;
-}
-
-
-static int uv__udp_set_membership4(uv_udp_t* handle,
-                                   const struct sockaddr_in* multicast_addr,
-                                   const char* interface_addr,
-                                   uv_membership membership) {
-  struct ip_mreq mreq;
-  int optname;
-  int err;
-
-  memset(&mreq, 0, sizeof mreq);
-
-  if (interface_addr) {
-    err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
-    if (err)
-      return err;
-  } else {
-    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
-  }
-
-  mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
-
-  switch (membership) {
-  case UV_JOIN_GROUP:
-    optname = IP_ADD_MEMBERSHIP;
-    break;
-  case UV_LEAVE_GROUP:
-    optname = IP_DROP_MEMBERSHIP;
-    break;
-  default:
-    return UV_EINVAL;
-  }
-
-  if (setsockopt(handle->io_watcher.fd,
-                 IPPROTO_IP,
-                 optname,
-                 &mreq,
-                 sizeof(mreq))) {
-#if defined(__MVS__)
-  if (errno == ENXIO)
-    return UV_ENODEV;
-#endif
-    return UV__ERR(errno);
-  }
-
-  return 0;
-}
-
-
-static int uv__udp_set_membership6(uv_udp_t* handle,
-                                   const struct sockaddr_in6* multicast_addr,
-                                   const char* interface_addr,
-                                   uv_membership membership) {
-  int optname;
-  struct ipv6_mreq mreq;
-  struct sockaddr_in6 addr6;
-
-  memset(&mreq, 0, sizeof mreq);
-
-  if (interface_addr) {
-    if (uv_ip6_addr(interface_addr, 0, &addr6))
-      return UV_EINVAL;
-    mreq.ipv6mr_interface = addr6.sin6_scope_id;
-  } else {
-    mreq.ipv6mr_interface = 0;
-  }
-
-  mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr;
-
-  switch (membership) {
-  case UV_JOIN_GROUP:
-    optname = IPV6_ADD_MEMBERSHIP;
-    break;
-  case UV_LEAVE_GROUP:
-    optname = IPV6_DROP_MEMBERSHIP;
-    break;
-  default:
-    return UV_EINVAL;
-  }
-
-  if (setsockopt(handle->io_watcher.fd,
-                 IPPROTO_IPV6,
-                 optname,
-                 &mreq,
-                 sizeof(mreq))) {
-#if defined(__MVS__)
-  if (errno == ENXIO)
-    return UV_ENODEV;
-#endif
-    return UV__ERR(errno);
-  }
-
-  return 0;
-}
-
-
-int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
-  int domain;
-  int err;
-  int fd;
-
-  /* Use the lower 8 bits for the domain */
-  domain = flags & 0xFF;
-  if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
-    return UV_EINVAL;
-
-  if (flags & ~0xFF)
-    return UV_EINVAL;
-
-  if (domain != AF_UNSPEC) {
-    err = uv__socket(domain, SOCK_DGRAM, 0);
-    if (err < 0)
-      return err;
-    fd = err;
-  } else {
-    fd = -1;
-  }
-
-  uv__handle_init(loop, (uv_handle_t*)handle, UV_UDP);
-  handle->alloc_cb = NULL;
-  handle->recv_cb = NULL;
-  handle->send_queue_size = 0;
-  handle->send_queue_count = 0;
-  uv__io_init(&handle->io_watcher, uv__udp_io, fd);
-  QUEUE_INIT(&handle->write_queue);
-  QUEUE_INIT(&handle->write_completed_queue);
-
-  return 0;
-}
-
-
-int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
-  return uv_udp_init_ex(loop, handle, AF_UNSPEC);
-}
-
-
-int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
-  int err;
-
-  /* Check for already active socket. */
-  if (handle->io_watcher.fd != -1)
-    return UV_EBUSY;
-
-  if (uv__fd_exists(handle->loop, sock))
-    return UV_EEXIST;
-
-  err = uv__nonblock(sock, 1);
-  if (err)
-    return err;
-
-  err = uv__set_reuse(sock);
-  if (err)
-    return err;
-
-  handle->io_watcher.fd = sock;
-  if (uv__udp_is_connected(handle))
-    handle->flags |= UV_HANDLE_UDP_CONNECTED;
-
-  return 0;
-}
-
-
-int uv_udp_set_membership(uv_udp_t* handle,
-                          const char* multicast_addr,
-                          const char* interface_addr,
-                          uv_membership membership) {
-  int err;
-  struct sockaddr_in addr4;
-  struct sockaddr_in6 addr6;
-
-  if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0) {
-    err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR);
-    if (err)
-      return err;
-    return uv__udp_set_membership4(handle, &addr4, interface_addr, membership);
-  } else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0) {
-    err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR);
-    if (err)
-      return err;
-    return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
-  } else {
-    return UV_EINVAL;
-  }
-}
-
-static int uv__setsockopt(uv_udp_t* handle,
-                         int option4,
-                         int option6,
-                         const void* val,
-                         size_t size) {
-  int r;
-
-  if (handle->flags & UV_HANDLE_IPV6)
-    r = setsockopt(handle->io_watcher.fd,
-                   IPPROTO_IPV6,
-                   option6,
-                   val,
-                   size);
-  else
-    r = setsockopt(handle->io_watcher.fd,
-                   IPPROTO_IP,
-                   option4,
-                   val,
-                   size);
-  if (r)
-    return UV__ERR(errno);
-
-  return 0;
-}
-
-static int uv__setsockopt_maybe_char(uv_udp_t* handle,
-                                     int option4,
-                                     int option6,
-                                     int val) {
-#if defined(__sun) || defined(_AIX) || defined(__MVS__)
-  char arg = val;
-#elif defined(__OpenBSD__)
-  unsigned char arg = val;
-#else
-  int arg = val;
-#endif
-
-  if (val < 0 || val > 255)
-    return UV_EINVAL;
-
-  return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg));
-}
-
-
-int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
-  if (setsockopt(handle->io_watcher.fd,
-                 SOL_SOCKET,
-                 SO_BROADCAST,
-                 &on,
-                 sizeof(on))) {
-    return UV__ERR(errno);
-  }
-
-  return 0;
-}
-
-
-int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
-  if (ttl < 1 || ttl > 255)
-    return UV_EINVAL;
-
-#if defined(__MVS__)
-  if (!(handle->flags & UV_HANDLE_IPV6))
-    return UV_ENOTSUP;  /* zOS does not support setting ttl for IPv4 */
-#endif
-
-/*
- * On Solaris and derivatives such as SmartOS, the length of socket options
- * is sizeof(int) for IP_TTL and IPV6_UNICAST_HOPS,
- * so hardcode the size of these options on this platform,
- * and use the general uv__setsockopt_maybe_char call on other platforms.
- */
-#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
-    defined(__MVS__)
-
-  return uv__setsockopt(handle,
-                        IP_TTL,
-                        IPV6_UNICAST_HOPS,
-                        &ttl,
-                        sizeof(ttl));
-
-#else /* !(defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
-           defined(__MVS__)) */
-
-  return uv__setsockopt_maybe_char(handle,
-                                   IP_TTL,
-                                   IPV6_UNICAST_HOPS,
-                                   ttl);
-
-#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) ||
-          defined(__MVS__) */
-}
-
-
-int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) {
-/*
- * On Solaris and derivatives such as SmartOS, the length of socket options
- * is sizeof(int) for IPV6_MULTICAST_HOPS and sizeof(char) for
- * IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case,
- * and use the general uv__setsockopt_maybe_char call otherwise.
- */
-#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
-    defined(__MVS__)
-  if (handle->flags & UV_HANDLE_IPV6)
-    return uv__setsockopt(handle,
-                          IP_MULTICAST_TTL,
-                          IPV6_MULTICAST_HOPS,
-                          &ttl,
-                          sizeof(ttl));
-#endif /* defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
-    defined(__MVS__) */
-
-  return uv__setsockopt_maybe_char(handle,
-                                   IP_MULTICAST_TTL,
-                                   IPV6_MULTICAST_HOPS,
-                                   ttl);
-}
-
-
-int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
-/*
- * On Solaris and derivatives such as SmartOS, the length of socket options
- * is sizeof(int) for IPV6_MULTICAST_LOOP and sizeof(char) for
- * IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case,
- * and use the general uv__setsockopt_maybe_char call otherwise.
- */
-#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
-    defined(__MVS__) 
-  if (handle->flags & UV_HANDLE_IPV6)
-    return uv__setsockopt(handle,
-                          IP_MULTICAST_LOOP,
-                          IPV6_MULTICAST_LOOP,
-                          &on,
-                          sizeof(on));
-#endif /* defined(__sun) || defined(_AIX) ||defined(__OpenBSD__) ||
-    defined(__MVS__) */
-
-  return uv__setsockopt_maybe_char(handle,
-                                   IP_MULTICAST_LOOP,
-                                   IPV6_MULTICAST_LOOP,
-                                   on);
-}
-
-int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
-  struct sockaddr_storage addr_st;
-  struct sockaddr_in* addr4;
-  struct sockaddr_in6* addr6;
-
-  addr4 = (struct sockaddr_in*) &addr_st;
-  addr6 = (struct sockaddr_in6*) &addr_st;
-
-  if (!interface_addr) {
-    memset(&addr_st, 0, sizeof addr_st);
-    if (handle->flags & UV_HANDLE_IPV6) {
-      addr_st.ss_family = AF_INET6;
-      addr6->sin6_scope_id = 0;
-    } else {
-      addr_st.ss_family = AF_INET;
-      addr4->sin_addr.s_addr = htonl(INADDR_ANY);
-    }
-  } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) {
-    /* nothing, address was parsed */
-  } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
-    /* nothing, address was parsed */
-  } else {
-    return UV_EINVAL;
-  }
-
-  if (addr_st.ss_family == AF_INET) {
-    if (setsockopt(handle->io_watcher.fd,
-                   IPPROTO_IP,
-                   IP_MULTICAST_IF,
-                   (void*) &addr4->sin_addr,
-                   sizeof(addr4->sin_addr)) == -1) {
-      return UV__ERR(errno);
-    }
-  } else if (addr_st.ss_family == AF_INET6) {
-    if (setsockopt(handle->io_watcher.fd,
-                   IPPROTO_IPV6,
-                   IPV6_MULTICAST_IF,
-                   &addr6->sin6_scope_id,
-                   sizeof(addr6->sin6_scope_id)) == -1) {
-      return UV__ERR(errno);
-    }
-  } else {
-    assert(0 && "unexpected address family");
-    abort();
-  }
-
-  return 0;
-}
-
-int uv_udp_getpeername(const uv_udp_t* handle,
-                       struct sockaddr* name,
-                       int* namelen) {
-
-  return uv__getsockpeername((const uv_handle_t*) handle,
-                             getpeername,
-                             name,
-                             namelen);
-}
-
-int uv_udp_getsockname(const uv_udp_t* handle,
-                       struct sockaddr* name,
-                       int* namelen) {
-
-  return uv__getsockpeername((const uv_handle_t*) handle,
-                             getsockname,
-                             name,
-                             namelen);
-}
-
-
-int uv__udp_recv_start(uv_udp_t* handle,
-                       uv_alloc_cb alloc_cb,
-                       uv_udp_recv_cb recv_cb) {
-  int err;
-
-  if (alloc_cb == NULL || recv_cb == NULL)
-    return UV_EINVAL;
-
-  if (uv__io_active(&handle->io_watcher, POLLIN))
-    return UV_EALREADY;  /* FIXME(bnoordhuis) Should be UV_EBUSY. */
-
-  err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0);
-  if (err)
-    return err;
-
-  handle->alloc_cb = alloc_cb;
-  handle->recv_cb = recv_cb;
-
-  uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
-  uv__handle_start(handle);
-
-  return 0;
-}
-
-
-int uv__udp_recv_stop(uv_udp_t* handle) {
-  uv__io_stop(handle->loop, &handle->io_watcher, POLLIN);
-
-  if (!uv__io_active(&handle->io_watcher, POLLOUT))
-    uv__handle_stop(handle);
-
-  handle->alloc_cb = NULL;
-  handle->recv_cb = NULL;
-
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/uv-common.cpp b/wpiutil/src/main/native/libuv/src/uv-common.cpp
deleted file mode 100644
index 3c65476..0000000
--- a/wpiutil/src/main/native/libuv/src/uv-common.cpp
+++ /dev/null
@@ -1,797 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "uv-common.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stddef.h> /* NULL */
-#include <stdio.h>
-#include <stdlib.h> /* malloc */
-#include <string.h> /* memset */
-
-#if defined(_WIN32)
-# include <malloc.h> /* malloc */
-#else
-# include <net/if.h> /* if_nametoindex */
-# include <sys/un.h> /* AF_UNIX, sockaddr_un */
-#endif
-
-
-typedef struct {
-  uv_malloc_func local_malloc;
-  uv_realloc_func local_realloc;
-  uv_calloc_func local_calloc;
-  uv_free_func local_free;
-} uv__allocator_t;
-
-static uv__allocator_t uv__allocator = {
-  malloc,
-  realloc,
-  calloc,
-  free,
-};
-
-char* uv__strdup(const char* s) {
-  size_t len = strlen(s) + 1;
-  char* m = (char*)uv__malloc(len);
-  if (m == NULL)
-    return NULL;
-  return (char*)memcpy(m, s, len);
-}
-
-char* uv__strndup(const char* s, size_t n) {
-  char* m;
-  size_t len = strlen(s);
-  if (n < len)
-    len = n;
-  m = (char*)uv__malloc(len + 1);
-  if (m == NULL)
-    return NULL;
-  m[len] = '\0';
-  return (char*)memcpy(m, s, len);
-}
-
-void* uv__malloc(size_t size) {
-  if (size > 0)
-    return uv__allocator.local_malloc(size);
-  return NULL;
-}
-
-void uv__free(void* ptr) {
-  int saved_errno;
-
-  /* Libuv expects that free() does not clobber errno.  The system allocator
-   * honors that assumption but custom allocators may not be so careful.
-   */
-  saved_errno = errno;
-  uv__allocator.local_free(ptr);
-  errno = saved_errno;
-}
-
-void* uv__calloc(size_t count, size_t size) {
-  return uv__allocator.local_calloc(count, size);
-}
-
-void* uv__realloc(void* ptr, size_t size) {
-  if (size > 0)
-    return uv__allocator.local_realloc(ptr, size);
-  uv__free(ptr);
-  return NULL;
-}
-
-int uv_replace_allocator(uv_malloc_func malloc_func,
-                         uv_realloc_func realloc_func,
-                         uv_calloc_func calloc_func,
-                         uv_free_func free_func) {
-  if (malloc_func == NULL || realloc_func == NULL ||
-      calloc_func == NULL || free_func == NULL) {
-    return UV_EINVAL;
-  }
-
-  uv__allocator.local_malloc = malloc_func;
-  uv__allocator.local_realloc = realloc_func;
-  uv__allocator.local_calloc = calloc_func;
-  uv__allocator.local_free = free_func;
-
-  return 0;
-}
-
-#define XX(uc, lc) case UV_##uc: return sizeof(uv_##lc##_t);
-
-size_t uv_handle_size(uv_handle_type type) {
-  switch (type) {
-    UV_HANDLE_TYPE_MAP(XX)
-    default:
-      return -1;
-  }
-}
-
-size_t uv_req_size(uv_req_type type) {
-  switch(type) {
-    UV_REQ_TYPE_MAP(XX)
-    default:
-      return -1;
-  }
-}
-
-#undef XX
-
-
-size_t uv_loop_size(void) {
-  return sizeof(uv_loop_t);
-}
-
-
-uv_buf_t uv_buf_init(char* base, unsigned int len) {
-  uv_buf_t buf;
-  buf.base = base;
-  buf.len = len;
-  return buf;
-}
-
-
-static const char* uv__unknown_err_code(int err) {
-  char buf[32];
-  char* copy;
-
-  snprintf(buf, sizeof(buf), "Unknown system error %d", err);
-  copy = uv__strdup(buf);
-
-  return copy != NULL ? copy : "Unknown system error";
-}
-
-#define UV_ERR_NAME_GEN_R(name, _) \
-case UV_## name: \
-  uv__strscpy(buf, #name, buflen); break;
-char* uv_err_name_r(int err, char* buf, size_t buflen) {
-  switch (err) {
-    UV_ERRNO_MAP(UV_ERR_NAME_GEN_R)
-    default: snprintf(buf, buflen, "Unknown system error %d", err);
-  }
-  return buf;
-}
-#undef UV_ERR_NAME_GEN_R
-
-
-#define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name;
-const char* uv_err_name(int err) {
-  switch (err) {
-    UV_ERRNO_MAP(UV_ERR_NAME_GEN)
-  }
-  return uv__unknown_err_code(err);
-}
-#undef UV_ERR_NAME_GEN
-
-
-#define UV_STRERROR_GEN_R(name, msg) \
-case UV_ ## name: \
-  snprintf(buf, buflen, "%s", msg); break;
-char* uv_strerror_r(int err, char* buf, size_t buflen) {
-  switch (err) {
-    UV_ERRNO_MAP(UV_STRERROR_GEN_R)
-    default: snprintf(buf, buflen, "Unknown system error %d", err);
-  }
-  return buf;
-}
-#undef UV_STRERROR_GEN_R
-
-
-#define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg;
-const char* uv_strerror(int err) {
-  switch (err) {
-    UV_ERRNO_MAP(UV_STRERROR_GEN)
-  }
-  return uv__unknown_err_code(err);
-}
-#undef UV_STRERROR_GEN
-
-
-int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) {
-  memset(addr, 0, sizeof(*addr));
-  addr->sin_family = AF_INET;
-  addr->sin_port = htons(port);
-  return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr));
-}
-
-
-int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) {
-  char address_part[40];
-  size_t address_part_size;
-  const char* zone_index;
-
-  memset(addr, 0, sizeof(*addr));
-  addr->sin6_family = AF_INET6;
-  addr->sin6_port = htons(port);
-#ifdef SIN6_LEN
-  addr->sin6_len = sizeof(*addr);
-#endif
-
-  zone_index = strchr(ip, '%');
-  if (zone_index != NULL) {
-    address_part_size = zone_index - ip;
-    if (address_part_size >= sizeof(address_part))
-      address_part_size = sizeof(address_part) - 1;
-
-    memcpy(address_part, ip, address_part_size);
-    address_part[address_part_size] = '\0';
-    ip = address_part;
-
-    zone_index++; /* skip '%' */
-    /* NOTE: unknown interface (id=0) is silently ignored */
-#ifdef _WIN32
-    addr->sin6_scope_id = atoi(zone_index);
-#else
-    addr->sin6_scope_id = if_nametoindex(zone_index);
-#endif
-  }
-
-  return uv_inet_pton(AF_INET6, ip, &addr->sin6_addr);
-}
-
-
-int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size) {
-  return uv_inet_ntop(AF_INET, &src->sin_addr, dst, size);
-}
-
-
-int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) {
-  return uv_inet_ntop(AF_INET6, &src->sin6_addr, dst, size);
-}
-
-
-int uv_tcp_bind(uv_tcp_t* handle,
-                const struct sockaddr* addr,
-                unsigned int flags) {
-  unsigned int addrlen;
-
-  if (handle->type != UV_TCP)
-    return UV_EINVAL;
-
-  if (addr->sa_family == AF_INET)
-    addrlen = sizeof(struct sockaddr_in);
-  else if (addr->sa_family == AF_INET6)
-    addrlen = sizeof(struct sockaddr_in6);
-  else
-    return UV_EINVAL;
-
-  return uv__tcp_bind(handle, addr, addrlen, flags);
-}
-
-
-int uv_udp_bind(uv_udp_t* handle,
-                const struct sockaddr* addr,
-                unsigned int flags) {
-  unsigned int addrlen;
-
-  if (handle->type != UV_UDP)
-    return UV_EINVAL;
-
-  if (addr->sa_family == AF_INET)
-    addrlen = sizeof(struct sockaddr_in);
-  else if (addr->sa_family == AF_INET6)
-    addrlen = sizeof(struct sockaddr_in6);
-  else
-    return UV_EINVAL;
-
-  return uv__udp_bind(handle, addr, addrlen, flags);
-}
-
-
-int uv_tcp_connect(uv_connect_t* req,
-                   uv_tcp_t* handle,
-                   const struct sockaddr* addr,
-                   uv_connect_cb cb) {
-  unsigned int addrlen;
-
-  if (handle->type != UV_TCP)
-    return UV_EINVAL;
-
-  if (addr->sa_family == AF_INET)
-    addrlen = sizeof(struct sockaddr_in);
-  else if (addr->sa_family == AF_INET6)
-    addrlen = sizeof(struct sockaddr_in6);
-  else
-    return UV_EINVAL;
-
-  return uv__tcp_connect(req, handle, addr, addrlen, cb);
-}
-
-
-int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) {
-  unsigned int addrlen;
-
-  if (handle->type != UV_UDP)
-    return UV_EINVAL;
-
-  /* Disconnect the handle */
-  if (addr == NULL) {
-    if (!(handle->flags & UV_HANDLE_UDP_CONNECTED))
-      return UV_ENOTCONN;
-
-    return uv__udp_disconnect(handle);
-  }
-
-  if (addr->sa_family == AF_INET)
-    addrlen = sizeof(struct sockaddr_in);
-  else if (addr->sa_family == AF_INET6)
-    addrlen = sizeof(struct sockaddr_in6);
-  else
-    return UV_EINVAL;
-
-  if (handle->flags & UV_HANDLE_UDP_CONNECTED)
-    return UV_EISCONN;
-
-  return uv__udp_connect(handle, addr, addrlen);
-}
-
-
-int uv__udp_is_connected(uv_udp_t* handle) {
-  struct sockaddr_storage addr;
-  int addrlen;
-  if (handle->type != UV_UDP)
-    return 0;
-
-  addrlen = sizeof(addr);
-  if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0)
-    return 0;
-
-  return addrlen > 0;
-}
-
-
-int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) {
-  unsigned int addrlen;
-
-  if (handle->type != UV_UDP)
-    return UV_EINVAL;
-
-  if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED))
-    return UV_EISCONN;
-
-  if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED))
-    return UV_EDESTADDRREQ;
-
-  if (addr != NULL) {
-    if (addr->sa_family == AF_INET)
-      addrlen = sizeof(struct sockaddr_in);
-    else if (addr->sa_family == AF_INET6)
-      addrlen = sizeof(struct sockaddr_in6);
-#if defined(AF_UNIX) && !defined(_WIN32)
-    else if (addr->sa_family == AF_UNIX)
-      addrlen = sizeof(struct sockaddr_un);
-#endif
-    else
-      return UV_EINVAL;
-  } else {
-    addrlen = 0;
-  }
-
-  return addrlen;
-}
-
-
-int uv_udp_send(uv_udp_send_t* req,
-                uv_udp_t* handle,
-                const uv_buf_t bufs[],
-                unsigned int nbufs,
-                const struct sockaddr* addr,
-                uv_udp_send_cb send_cb) {
-  int addrlen;
-
-  addrlen = uv__udp_check_before_send(handle, addr);
-  if (addrlen < 0)
-    return addrlen;
-
-  return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
-}
-
-
-int uv_udp_try_send(uv_udp_t* handle,
-                    const uv_buf_t bufs[],
-                    unsigned int nbufs,
-                    const struct sockaddr* addr) {
-  int addrlen;
-
-  addrlen = uv__udp_check_before_send(handle, addr);
-  if (addrlen < 0)
-    return addrlen;
-
-  return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen);
-}
-
-
-int uv_udp_recv_start(uv_udp_t* handle,
-                      uv_alloc_cb alloc_cb,
-                      uv_udp_recv_cb recv_cb) {
-  if (handle->type != UV_UDP || alloc_cb == NULL || recv_cb == NULL)
-    return UV_EINVAL;
-  else
-    return uv__udp_recv_start(handle, alloc_cb, recv_cb);
-}
-
-
-int uv_udp_recv_stop(uv_udp_t* handle) {
-  if (handle->type != UV_UDP)
-    return UV_EINVAL;
-  else
-    return uv__udp_recv_stop(handle);
-}
-
-
-void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) {
-  QUEUE queue;
-  QUEUE* q;
-  uv_handle_t* h;
-
-  QUEUE_MOVE(&loop->handle_queue, &queue);
-  while (!QUEUE_EMPTY(&queue)) {
-    q = QUEUE_HEAD(&queue);
-    h = QUEUE_DATA(q, uv_handle_t, handle_queue);
-
-    QUEUE_REMOVE(q);
-    QUEUE_INSERT_TAIL(&loop->handle_queue, q);
-
-    if (h->flags & UV_HANDLE_INTERNAL) continue;
-    walk_cb(h, arg);
-  }
-}
-
-
-static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
-  const char* type;
-  QUEUE* q;
-  uv_handle_t* h;
-
-  if (loop == NULL)
-    loop = uv_default_loop();
-
-  QUEUE_FOREACH(q, &loop->handle_queue) {
-    h = QUEUE_DATA(q, uv_handle_t, handle_queue);
-
-    if (only_active && !uv__is_active(h))
-      continue;
-
-    switch (h->type) {
-#define X(uc, lc) case UV_##uc: type = #lc; break;
-      UV_HANDLE_TYPE_MAP(X)
-#undef X
-      default: type = "<unknown>";
-    }
-
-    fprintf(stream,
-            "[%c%c%c] %-8s %p\n",
-            "R-"[!(h->flags & UV_HANDLE_REF)],
-            "A-"[!(h->flags & UV_HANDLE_ACTIVE)],
-            "I-"[!(h->flags & UV_HANDLE_INTERNAL)],
-            type,
-            (void*)h);
-  }
-}
-
-
-void uv_print_all_handles(uv_loop_t* loop, FILE* stream) {
-  uv__print_handles(loop, 0, stream);
-}
-
-
-void uv_print_active_handles(uv_loop_t* loop, FILE* stream) {
-  uv__print_handles(loop, 1, stream);
-}
-
-
-void uv_ref(uv_handle_t* handle) {
-  uv__handle_ref(handle);
-}
-
-
-void uv_unref(uv_handle_t* handle) {
-  uv__handle_unref(handle);
-}
-
-
-int uv_has_ref(const uv_handle_t* handle) {
-  return uv__has_ref(handle);
-}
-
-
-void uv_stop(uv_loop_t* loop) {
-  loop->stop_flag = 1;
-}
-
-
-uint64_t uv_now(const uv_loop_t* loop) {
-  return loop->time;
-}
-
-
-
-size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs) {
-  unsigned int i;
-  size_t bytes;
-
-  bytes = 0;
-  for (i = 0; i < nbufs; i++)
-    bytes += (size_t) bufs[i].len;
-
-  return bytes;
-}
-
-int uv_recv_buffer_size(uv_handle_t* handle, int* value) {
-  return uv__socket_sockopt(handle, SO_RCVBUF, value);
-}
-
-int uv_send_buffer_size(uv_handle_t* handle, int *value) {
-  return uv__socket_sockopt(handle, SO_SNDBUF, value);
-}
-
-int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size) {
-  size_t required_len;
-
-  if (!uv__is_active(handle)) {
-    *size = 0;
-    return UV_EINVAL;
-  }
-
-  required_len = strlen(handle->path);
-  if (required_len >= *size) {
-    *size = required_len + 1;
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, handle->path, required_len);
-  *size = required_len;
-  buffer[required_len] = '\0';
-
-  return 0;
-}
-
-/* The windows implementation does not have the same structure layout as
- * the unix implementation (nbufs is not directly inside req but is
- * contained in a nested union/struct) so this function locates it.
-*/
-static unsigned int* uv__get_nbufs(uv_fs_t* req) {
-#ifdef _WIN32
-  return &req->fs.info.nbufs;
-#else
-  return &req->nbufs;
-#endif
-}
-
-/* uv_fs_scandir() uses the system allocator to allocate memory on non-Windows
- * systems. So, the memory should be released using free(). On Windows,
- * uv__malloc() is used, so use uv__free() to free memory.
-*/
-#ifdef _WIN32
-# define uv__fs_scandir_free uv__free
-#else
-# define uv__fs_scandir_free free
-#endif
-
-void uv__fs_scandir_cleanup(uv_fs_t* req) {
-  uv__dirent_t** dents;
-
-  unsigned int* nbufs = uv__get_nbufs(req);
-
-  dents = (uv__dirent_t**)(req->ptr);
-  if (*nbufs > 0 && *nbufs != (unsigned int) req->result)
-    (*nbufs)--;
-  for (; *nbufs < (unsigned int) req->result; (*nbufs)++)
-    uv__fs_scandir_free(dents[*nbufs]);
-
-  uv__fs_scandir_free(req->ptr);
-  req->ptr = NULL;
-}
-
-
-int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
-  uv__dirent_t** dents;
-  uv__dirent_t* dent;
-  unsigned int* nbufs;
-
-  /* Check to see if req passed */
-  if (req->result < 0)
-    return req->result;
-
-  /* Ptr will be null if req was canceled or no files found */
-  if (!req->ptr)
-    return UV_EOF;
-
-  nbufs = uv__get_nbufs(req);
-  assert(nbufs);
-
-  dents = (uv__dirent_t**)(req->ptr);
-
-  /* Free previous entity */
-  if (*nbufs > 0)
-    uv__fs_scandir_free(dents[*nbufs - 1]);
-
-  /* End was already reached */
-  if (*nbufs == (unsigned int) req->result) {
-    uv__fs_scandir_free(dents);
-    req->ptr = NULL;
-    return UV_EOF;
-  }
-
-  dent = dents[(*nbufs)++];
-
-  ent->name = dent->d_name;
-  ent->type = uv__fs_get_dirent_type(dent);
-
-  return 0;
-}
-
-uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) {
-  uv_dirent_type_t type;
-
-#ifdef HAVE_DIRENT_TYPES
-  switch (dent->d_type) {
-    case UV__DT_DIR:
-      type = UV_DIRENT_DIR;
-      break;
-    case UV__DT_FILE:
-      type = UV_DIRENT_FILE;
-      break;
-    case UV__DT_LINK:
-      type = UV_DIRENT_LINK;
-      break;
-    case UV__DT_FIFO:
-      type = UV_DIRENT_FIFO;
-      break;
-    case UV__DT_SOCKET:
-      type = UV_DIRENT_SOCKET;
-      break;
-    case UV__DT_CHAR:
-      type = UV_DIRENT_CHAR;
-      break;
-    case UV__DT_BLOCK:
-      type = UV_DIRENT_BLOCK;
-      break;
-    default:
-      type = UV_DIRENT_UNKNOWN;
-  }
-#else
-  type = UV_DIRENT_UNKNOWN;
-#endif
-
-  return type;
-}
-
-void uv__fs_readdir_cleanup(uv_fs_t* req) {
-  uv_dir_t* dir;
-  uv_dirent_t* dirents;
-  int i;
-
-  if (req->ptr == NULL)
-    return;
-
-  dir = (uv_dir_t*)req->ptr;
-  dirents = dir->dirents;
-  req->ptr = NULL;
-
-  if (dirents == NULL)
-    return;
-
-  for (i = 0; i < req->result; ++i) {
-    uv__free((char*) dirents[i].name);
-    dirents[i].name = NULL;
-  }
-}
-
-
-#ifdef __clang__
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wvarargs"
-#endif
-
-int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) {
-  va_list ap;
-  int err;
-
-  va_start(ap, option);
-  /* Any platform-agnostic options should be handled here. */
-  err = uv__loop_configure(loop, option, ap);
-  va_end(ap);
-
-  return err;
-}
-
-#ifdef __clang__
-# pragma clang diagnostic pop
-#endif
-
-
-static uv_loop_t default_loop_struct;
-static uv_loop_t* default_loop_ptr;
-
-
-uv_loop_t* uv_default_loop(void) {
-  if (default_loop_ptr != NULL)
-    return default_loop_ptr;
-
-  if (uv_loop_init(&default_loop_struct))
-    return NULL;
-
-  default_loop_ptr = &default_loop_struct;
-  return default_loop_ptr;
-}
-
-
-uv_loop_t* uv_loop_new(void) {
-  uv_loop_t* loop;
-
-  loop = (uv_loop_t*)uv__malloc(sizeof(*loop));
-  if (loop == NULL)
-    return NULL;
-
-  if (uv_loop_init(loop)) {
-    uv__free(loop);
-    return NULL;
-  }
-
-  return loop;
-}
-
-
-int uv_loop_close(uv_loop_t* loop) {
-  QUEUE* q;
-  uv_handle_t* h;
-#ifndef NDEBUG
-  void* saved_data;
-#endif
-
-  if (uv__has_active_reqs(loop))
-    return UV_EBUSY;
-
-  QUEUE_FOREACH(q, &loop->handle_queue) {
-    h = QUEUE_DATA(q, uv_handle_t, handle_queue);
-    if (!(h->flags & UV_HANDLE_INTERNAL))
-      return UV_EBUSY;
-  }
-
-  uv__loop_close(loop);
-
-#ifndef NDEBUG
-  saved_data = loop->data;
-  memset(loop, -1, sizeof(*loop));
-  loop->data = saved_data;
-#endif
-  if (loop == default_loop_ptr)
-    default_loop_ptr = NULL;
-
-  return 0;
-}
-
-
-void uv_loop_delete(uv_loop_t* loop) {
-  uv_loop_t* default_loop;
-  int err;
-
-  default_loop = default_loop_ptr;
-
-  err = uv_loop_close(loop);
-  (void) err;    /* Squelch compiler warnings. */
-  assert(err == 0);
-  if (loop != default_loop)
-    uv__free(loop);
-}
diff --git a/wpiutil/src/main/native/libuv/src/uv-common.h b/wpiutil/src/main/native/libuv/src/uv-common.h
deleted file mode 100644
index f788161..0000000
--- a/wpiutil/src/main/native/libuv/src/uv-common.h
+++ /dev/null
@@ -1,326 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-/*
- * This file is private to libuv. It provides common functionality to both
- * Windows and Unix backends.
- */
-
-#ifndef UV_COMMON_H_
-#define UV_COMMON_H_
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stddef.h>
-
-#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "uv/stdint-msvc2008.h"
-#else
-# include <stdint.h>
-#endif
-
-#include "uv.h"
-#include "uv/tree.h"
-#include "queue.h"
-#include "strscpy.h"
-
-#if EDOM > 0
-# define UV__ERR(x) (-(x))
-#else
-# define UV__ERR(x) (x)
-#endif
-
-#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
-extern int snprintf(char*, size_t, const char*, ...);
-#endif
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-#define container_of(ptr, type, member) \
-  ((type *) ((char *) (ptr) - offsetof(type, member)))
-
-#define STATIC_ASSERT(expr)                                                   \
-  void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)])
-
-/* Handle flags. Some flags are specific to Windows or UNIX. */
-enum {
-  /* Used by all handles. */
-  UV_HANDLE_CLOSING                     = 0x00000001,
-  UV_HANDLE_CLOSED                      = 0x00000002,
-  UV_HANDLE_ACTIVE                      = 0x00000004,
-  UV_HANDLE_REF                         = 0x00000008,
-  UV_HANDLE_INTERNAL                    = 0x00000010,
-  UV_HANDLE_ENDGAME_QUEUED              = 0x00000020,
-
-  /* Used by streams. */
-  UV_HANDLE_LISTENING                   = 0x00000040,
-  UV_HANDLE_CONNECTION                  = 0x00000080,
-  UV_HANDLE_SHUTTING                    = 0x00000100,
-  UV_HANDLE_SHUT                        = 0x00000200,
-  UV_HANDLE_READ_PARTIAL                = 0x00000400,
-  UV_HANDLE_READ_EOF                    = 0x00000800,
-
-  /* Used by streams and UDP handles. */
-  UV_HANDLE_READING                     = 0x00001000,
-  UV_HANDLE_BOUND                       = 0x00002000,
-  UV_HANDLE_READABLE                    = 0x00004000,
-  UV_HANDLE_WRITABLE                    = 0x00008000,
-  UV_HANDLE_READ_PENDING                = 0x00010000,
-  UV_HANDLE_SYNC_BYPASS_IOCP            = 0x00020000,
-  UV_HANDLE_ZERO_READ                   = 0x00040000,
-  UV_HANDLE_EMULATE_IOCP                = 0x00080000,
-  UV_HANDLE_BLOCKING_WRITES             = 0x00100000,
-  UV_HANDLE_CANCELLATION_PENDING        = 0x00200000,
-
-  /* Used by uv_tcp_t and uv_udp_t handles */
-  UV_HANDLE_IPV6                        = 0x00400000,
-
-  /* Only used by uv_tcp_t handles. */
-  UV_HANDLE_TCP_NODELAY                 = 0x01000000,
-  UV_HANDLE_TCP_KEEPALIVE               = 0x02000000,
-  UV_HANDLE_TCP_SINGLE_ACCEPT           = 0x04000000,
-  UV_HANDLE_TCP_ACCEPT_STATE_CHANGING   = 0x08000000,
-  UV_HANDLE_TCP_SOCKET_CLOSED           = 0x10000000,
-  UV_HANDLE_SHARED_TCP_SOCKET           = 0x20000000,
-
-  /* Only used by uv_udp_t handles. */
-  UV_HANDLE_UDP_PROCESSING              = 0x01000000,
-  UV_HANDLE_UDP_CONNECTED               = 0x02000000,
-
-  /* Only used by uv_pipe_t handles. */
-  UV_HANDLE_NON_OVERLAPPED_PIPE         = 0x01000000,
-  UV_HANDLE_PIPESERVER                  = 0x02000000,
-
-  /* Only used by uv_tty_t handles. */
-  UV_HANDLE_TTY_READABLE                = 0x01000000,
-  UV_HANDLE_TTY_RAW                     = 0x02000000,
-  UV_HANDLE_TTY_SAVED_POSITION          = 0x04000000,
-  UV_HANDLE_TTY_SAVED_ATTRIBUTES        = 0x08000000,
-
-  /* Only used by uv_signal_t handles. */
-  UV_SIGNAL_ONE_SHOT_DISPATCHED         = 0x01000000,
-  UV_SIGNAL_ONE_SHOT                    = 0x02000000,
-
-  /* Only used by uv_poll_t handles. */
-  UV_HANDLE_POLL_SLOW                   = 0x01000000
-};
-
-int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
-
-void uv__loop_close(uv_loop_t* loop);
-
-int uv__tcp_bind(uv_tcp_t* tcp,
-                 const struct sockaddr* addr,
-                 unsigned int addrlen,
-                 unsigned int flags);
-
-int uv__tcp_connect(uv_connect_t* req,
-                   uv_tcp_t* handle,
-                   const struct sockaddr* addr,
-                   unsigned int addrlen,
-                   uv_connect_cb cb);
-
-int uv__udp_bind(uv_udp_t* handle,
-                 const struct sockaddr* addr,
-                 unsigned int  addrlen,
-                 unsigned int flags);
-
-int uv__udp_connect(uv_udp_t* handle,
-                    const struct sockaddr* addr,
-                    unsigned int addrlen);
-
-int uv__udp_disconnect(uv_udp_t* handle);
-
-int uv__udp_is_connected(uv_udp_t* handle);
-
-int uv__udp_send(uv_udp_send_t* req,
-                 uv_udp_t* handle,
-                 const uv_buf_t bufs[],
-                 unsigned int nbufs,
-                 const struct sockaddr* addr,
-                 unsigned int addrlen,
-                 uv_udp_send_cb send_cb);
-
-int uv__udp_try_send(uv_udp_t* handle,
-                     const uv_buf_t bufs[],
-                     unsigned int nbufs,
-                     const struct sockaddr* addr,
-                     unsigned int addrlen);
-
-int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloccb,
-                       uv_udp_recv_cb recv_cb);
-
-int uv__udp_recv_stop(uv_udp_t* handle);
-
-void uv__fs_poll_close(uv_fs_poll_t* handle);
-
-int uv__getaddrinfo_translate_error(int sys_err);    /* EAI_* error. */
-
-enum uv__work_kind {
-  UV__WORK_CPU,
-  UV__WORK_FAST_IO,
-  UV__WORK_SLOW_IO
-};
-
-void uv__work_submit(uv_loop_t* loop,
-                     struct uv__work *w,
-                     enum uv__work_kind kind,
-                     void (*work)(struct uv__work *w),
-                     void (*done)(struct uv__work *w, int status));
-
-void uv__work_done(uv_async_t* handle);
-
-size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs);
-
-int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
-
-void uv__fs_scandir_cleanup(uv_fs_t* req);
-void uv__fs_readdir_cleanup(uv_fs_t* req);
-uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent);
-
-int uv__next_timeout(const uv_loop_t* loop);
-void uv__run_timers(uv_loop_t* loop);
-void uv__timer_close(uv_timer_t* handle);
-
-#define uv__has_active_reqs(loop)                                             \
-  ((loop)->active_reqs.count > 0)
-
-#define uv__req_register(loop, req)                                           \
-  do {                                                                        \
-    (loop)->active_reqs.count++;                                              \
-  }                                                                           \
-  while (0)
-
-#define uv__req_unregister(loop, req)                                         \
-  do {                                                                        \
-    assert(uv__has_active_reqs(loop));                                        \
-    (loop)->active_reqs.count--;                                              \
-  }                                                                           \
-  while (0)
-
-#define uv__has_active_handles(loop)                                          \
-  ((loop)->active_handles > 0)
-
-#define uv__active_handle_add(h)                                              \
-  do {                                                                        \
-    (h)->loop->active_handles++;                                              \
-  }                                                                           \
-  while (0)
-
-#define uv__active_handle_rm(h)                                               \
-  do {                                                                        \
-    (h)->loop->active_handles--;                                              \
-  }                                                                           \
-  while (0)
-
-#define uv__is_active(h)                                                      \
-  (((h)->flags & UV_HANDLE_ACTIVE) != 0)
-
-#define uv__is_closing(h)                                                     \
-  (((h)->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)) != 0)
-
-#define uv__handle_start(h)                                                   \
-  do {                                                                        \
-    if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break;                          \
-    (h)->flags |= UV_HANDLE_ACTIVE;                                           \
-    if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h);          \
-  }                                                                           \
-  while (0)
-
-#define uv__handle_stop(h)                                                    \
-  do {                                                                        \
-    if (((h)->flags & UV_HANDLE_ACTIVE) == 0) break;                          \
-    (h)->flags &= ~UV_HANDLE_ACTIVE;                                          \
-    if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_rm(h);           \
-  }                                                                           \
-  while (0)
-
-#define uv__handle_ref(h)                                                     \
-  do {                                                                        \
-    if (((h)->flags & UV_HANDLE_REF) != 0) break;                             \
-    (h)->flags |= UV_HANDLE_REF;                                              \
-    if (((h)->flags & UV_HANDLE_CLOSING) != 0) break;                         \
-    if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_add(h);       \
-  }                                                                           \
-  while (0)
-
-#define uv__handle_unref(h)                                                   \
-  do {                                                                        \
-    if (((h)->flags & UV_HANDLE_REF) == 0) break;                             \
-    (h)->flags &= ~UV_HANDLE_REF;                                             \
-    if (((h)->flags & UV_HANDLE_CLOSING) != 0) break;                         \
-    if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_rm(h);        \
-  }                                                                           \
-  while (0)
-
-#define uv__has_ref(h)                                                        \
-  (((h)->flags & UV_HANDLE_REF) != 0)
-
-#if defined(_WIN32)
-# define uv__handle_platform_init(h) ((h)->u.fd = -1)
-#else
-# define uv__handle_platform_init(h) ((h)->next_closing = NULL)
-#endif
-
-#define uv__handle_init(loop_, h, type_)                                      \
-  do {                                                                        \
-    (h)->loop = (loop_);                                                      \
-    (h)->type = (type_);                                                      \
-    (h)->flags = UV_HANDLE_REF;  /* Ref the loop when active. */              \
-    QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue);            \
-    uv__handle_platform_init(h);                                              \
-  }                                                                           \
-  while (0)
-
-/* Note: uses an open-coded version of SET_REQ_SUCCESS() because of
- * a circular dependency between src/uv-common.h and src/win/internal.h.
- */
-#if defined(_WIN32)
-# define UV_REQ_INIT(req, typ)                                                \
-  do {                                                                        \
-    (req)->type = (typ);                                                      \
-    (req)->u.io.overlapped.Internal = 0;  /* SET_REQ_SUCCESS() */             \
-  }                                                                           \
-  while (0)
-#else
-# define UV_REQ_INIT(req, typ)                                                \
-  do {                                                                        \
-    (req)->type = (typ);                                                      \
-  }                                                                           \
-  while (0)
-#endif
-
-#define uv__req_init(loop, req, typ)                                          \
-  do {                                                                        \
-    UV_REQ_INIT(req, typ);                                                    \
-    uv__req_register(loop, req);                                              \
-  }                                                                           \
-  while (0)
-
-/* Allocator prototypes */
-void *uv__calloc(size_t count, size_t size);
-char *uv__strdup(const char* s);
-char *uv__strndup(const char* s, size_t n);
-void* uv__malloc(size_t size);
-void uv__free(void* ptr);
-void* uv__realloc(void* ptr, size_t size);
-
-#endif /* UV_COMMON_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/uv-data-getter-setters.cpp b/wpiutil/src/main/native/libuv/src/uv-data-getter-setters.cpp
deleted file mode 100644
index c302566..0000000
--- a/wpiutil/src/main/native/libuv/src/uv-data-getter-setters.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "uv.h"
-
-const char* uv_handle_type_name(uv_handle_type type) {
-  switch (type) {
-#define XX(uc,lc) case UV_##uc: return #lc;
-  UV_HANDLE_TYPE_MAP(XX)
-#undef XX
-  case UV_FILE: return "file";
-  case UV_HANDLE_TYPE_MAX:
-  case UV_UNKNOWN_HANDLE: return NULL;
-  }
-  return NULL;
-}
-
-uv_handle_type uv_handle_get_type(const uv_handle_t* handle) {
-  return handle->type;
-}
-
-void* uv_handle_get_data(const uv_handle_t* handle) {
-  return handle->data;
-}
-
-uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle) {
-  return handle->loop;
-}
-
-void uv_handle_set_data(uv_handle_t* handle, void* data) {
-  handle->data = data;
-}
-
-const char* uv_req_type_name(uv_req_type type) {
-  switch (type) {
-#define XX(uc,lc) case UV_##uc: return #lc;
-  UV_REQ_TYPE_MAP(XX)
-#undef XX
-  case UV_REQ_TYPE_MAX:
-  case UV_UNKNOWN_REQ:
-  default: /* UV_REQ_TYPE_PRIVATE */
-    break;
-  }
-  return NULL;
-}
-
-uv_req_type uv_req_get_type(const uv_req_t* req) {
-  return req->type;
-}
-
-void* uv_req_get_data(const uv_req_t* req) {
-  return req->data;
-}
-
-void uv_req_set_data(uv_req_t* req, void* data) {
-  req->data = data;
-}
-
-size_t uv_stream_get_write_queue_size(const uv_stream_t* stream) {
-  return stream->write_queue_size;
-}
-
-size_t uv_udp_get_send_queue_size(const uv_udp_t* handle) {
-  return handle->send_queue_size;
-}
-
-size_t uv_udp_get_send_queue_count(const uv_udp_t* handle) {
-  return handle->send_queue_count;
-}
-
-uv_pid_t uv_process_get_pid(const uv_process_t* proc) {
-  return proc->pid;
-}
-
-uv_fs_type uv_fs_get_type(const uv_fs_t* req) {
-  return req->fs_type;
-}
-
-ssize_t uv_fs_get_result(const uv_fs_t* req) {
-  return req->result;
-}
-
-void* uv_fs_get_ptr(const uv_fs_t* req) {
-  return req->ptr;
-}
-
-const char* uv_fs_get_path(const uv_fs_t* req) {
-  return req->path;
-}
-
-uv_stat_t* uv_fs_get_statbuf(uv_fs_t* req) {
-  return &req->statbuf;
-}
-
-void* uv_loop_get_data(const uv_loop_t* loop) {
-  return loop->data;
-}
-
-void uv_loop_set_data(uv_loop_t* loop, void* data) {
-  loop->data = data;
-}
diff --git a/wpiutil/src/main/native/libuv/src/version.cpp b/wpiutil/src/main/native/libuv/src/version.cpp
deleted file mode 100644
index 686dedd..0000000
--- a/wpiutil/src/main/native/libuv/src/version.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-
-#define UV_STRINGIFY(v) UV_STRINGIFY_HELPER(v)
-#define UV_STRINGIFY_HELPER(v) #v
-
-#define UV_VERSION_STRING_BASE  UV_STRINGIFY(UV_VERSION_MAJOR) "." \
-                                UV_STRINGIFY(UV_VERSION_MINOR) "." \
-                                UV_STRINGIFY(UV_VERSION_PATCH)
-
-#if UV_VERSION_IS_RELEASE
-# define UV_VERSION_STRING  UV_VERSION_STRING_BASE
-#else
-# define UV_VERSION_STRING  UV_VERSION_STRING_BASE "-" UV_VERSION_SUFFIX
-#endif
-
-
-unsigned int uv_version(void) {
-  return UV_VERSION_HEX;
-}
-
-
-const char* uv_version_string(void) {
-  return UV_VERSION_STRING;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/async.cpp b/wpiutil/src/main/native/libuv/src/win/async.cpp
deleted file mode 100644
index d787f66..0000000
--- a/wpiutil/src/main/native/libuv/src/win/async.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "atomicops-inl.h"
-#include "handle-inl.h"
-#include "req-inl.h"
-
-
-void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) {
-  if (handle->flags & UV_HANDLE_CLOSING &&
-      !handle->async_sent) {
-    assert(!(handle->flags & UV_HANDLE_CLOSED));
-    uv__handle_close(handle);
-  }
-}
-
-
-int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
-  uv_req_t* req;
-
-  uv__handle_init(loop, (uv_handle_t*) handle, UV_ASYNC);
-  handle->async_sent = 0;
-  handle->async_cb = async_cb;
-
-  req = &handle->async_req;
-  UV_REQ_INIT(req, UV_WAKEUP);
-  req->data = handle;
-
-  uv__handle_start(handle);
-
-  return 0;
-}
-
-
-void uv_async_close(uv_loop_t* loop, uv_async_t* handle) {
-  if (!((uv_async_t*)handle)->async_sent) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-  }
-
-  uv__handle_closing(handle);
-}
-
-
-int uv_async_send(uv_async_t* handle) {
-  uv_loop_t* loop = handle->loop;
-
-  if (handle->type != UV_ASYNC) {
-    /* Can't set errno because that's not thread-safe. */
-    return -1;
-  }
-
-  /* The user should make sure never to call uv_async_send to a closing or
-   * closed handle. */
-  assert(!(handle->flags & UV_HANDLE_CLOSING));
-
-  if (!uv__atomic_exchange_set(&handle->async_sent)) {
-    POST_COMPLETION_FOR_REQ(loop, &handle->async_req);
-  }
-
-  return 0;
-}
-
-
-void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
-    uv_req_t* req) {
-  assert(handle->type == UV_ASYNC);
-  assert(req->type == UV_WAKEUP);
-
-  handle->async_sent = 0;
-
-  if (handle->flags & UV_HANDLE_CLOSING) {
-    uv_want_endgame(loop, (uv_handle_t*)handle);
-  } else if (handle->async_cb != NULL) {
-    handle->async_cb(handle);
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/atomicops-inl.h b/wpiutil/src/main/native/libuv/src/win/atomicops-inl.h
deleted file mode 100644
index 52713cf..0000000
--- a/wpiutil/src/main/native/libuv/src/win/atomicops-inl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_WIN_ATOMICOPS_INL_H_
-#define UV_WIN_ATOMICOPS_INL_H_
-
-#include "uv.h"
-#include "internal.h"
-
-
-/* Atomic set operation on char */
-#ifdef _MSC_VER /* MSVC */
-
-/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less
- * efficient than InterlockedExchange, but InterlockedExchange8 does not exist,
- * and interlocked operations on larger targets might require the target to be
- * aligned. */
-#pragma intrinsic(_InterlockedOr8)
-
-static char INLINE uv__atomic_exchange_set(char volatile* target) {
-  return _InterlockedOr8(target, 1);
-}
-
-#else /* GCC */
-
-/* Mingw-32 version, hopefully this works for 64-bit gcc as well. */
-static inline char uv__atomic_exchange_set(char volatile* target) {
-  const char one = 1;
-  char old_value;
-  __asm__ __volatile__ ("lock xchgb %0, %1\n\t"
-                        : "=r"(old_value), "=m"(*target)
-                        : "0"(one), "m"(*target)
-                        : "memory");
-  return old_value;
-}
-
-#endif
-
-#endif /* UV_WIN_ATOMICOPS_INL_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/win/core.cpp b/wpiutil/src/main/native/libuv/src/win/core.cpp
deleted file mode 100644
index 1e162dd..0000000
--- a/wpiutil/src/main/native/libuv/src/win/core.cpp
+++ /dev/null
@@ -1,654 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
-#include <crtdbg.h>
-#endif
-
-#include "uv.h"
-#include "internal.h"
-#include "queue.h"
-#include "handle-inl.h"
-#include "heap-inl.h"
-#include "req-inl.h"
-
-/* uv_once initialization guards */
-static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
-
-
-#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR))
-/* Our crt debug report handler allows us to temporarily disable asserts
- * just for the current thread.
- */
-
-UV_THREAD_LOCAL int uv__crt_assert_enabled = TRUE;
-
-static int uv__crt_dbg_report_handler(int report_type, char *message, int *ret_val) {
-  if (uv__crt_assert_enabled || report_type != _CRT_ASSERT)
-    return FALSE;
-
-  if (ret_val) {
-    /* Set ret_val to 0 to continue with normal execution.
-     * Set ret_val to 1 to trigger a breakpoint.
-    */
-
-    if(IsDebuggerPresent())
-      *ret_val = 1;
-    else
-      *ret_val = 0;
-  }
-
-  /* Don't call _CrtDbgReport. */
-  return TRUE;
-}
-#else
-UV_THREAD_LOCAL int uv__crt_assert_enabled = FALSE;
-#endif
-
-
-#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800
-static void uv__crt_invalid_parameter_handler(const wchar_t* expression,
-    const wchar_t* function, const wchar_t * file, unsigned int line,
-    uintptr_t reserved) {
-  /* No-op. */
-}
-#endif
-
-static uv_loop_t** uv__loops;
-static int uv__loops_size;
-static int uv__loops_capacity;
-#define UV__LOOPS_CHUNK_SIZE 8
-static uv_mutex_t uv__loops_lock;
-
-static void uv__loops_init(void) {
-  uv_mutex_init(&uv__loops_lock);
-}
-
-static int uv__loops_add(uv_loop_t* loop) {
-  uv_loop_t** new_loops;
-  int new_capacity, i;
-
-  uv_mutex_lock(&uv__loops_lock);
-
-  if (uv__loops_size == uv__loops_capacity) {
-    new_capacity = uv__loops_capacity + UV__LOOPS_CHUNK_SIZE;
-    new_loops = (uv_loop_t**)
-        uv__realloc(uv__loops, sizeof(uv_loop_t*) * new_capacity);
-    if (!new_loops)
-      goto failed_loops_realloc;
-    uv__loops = new_loops;
-    for (i = uv__loops_capacity; i < new_capacity; ++i)
-      uv__loops[i] = NULL;
-    uv__loops_capacity = new_capacity;
-  }
-  uv__loops[uv__loops_size] = loop;
-  ++uv__loops_size;
-
-  uv_mutex_unlock(&uv__loops_lock);
-  return 0;
-
-failed_loops_realloc:
-  uv_mutex_unlock(&uv__loops_lock);
-  return ERROR_OUTOFMEMORY;
-}
-
-static void uv__loops_remove(uv_loop_t* loop) {
-  int loop_index;
-  int smaller_capacity;
-  uv_loop_t** new_loops;
-
-  uv_mutex_lock(&uv__loops_lock);
-
-  for (loop_index = 0; loop_index < uv__loops_size; ++loop_index) {
-    if (uv__loops[loop_index] == loop)
-      break;
-  }
-  /* If loop was not found, ignore */
-  if (loop_index == uv__loops_size)
-    goto loop_removed;
-
-  uv__loops[loop_index] = uv__loops[uv__loops_size - 1];
-  uv__loops[uv__loops_size - 1] = NULL;
-  --uv__loops_size;
-
-  if (uv__loops_size == 0) {
-    uv__loops_capacity = 0;
-    uv__free(uv__loops);
-    uv__loops = NULL;
-    goto loop_removed;
-  }
-
-  /* If we didn't grow to big skip downsizing */
-  if (uv__loops_capacity < 4 * UV__LOOPS_CHUNK_SIZE)
-    goto loop_removed;
-
-  /* Downsize only if more than half of buffer is free */
-  smaller_capacity = uv__loops_capacity / 2;
-  if (uv__loops_size >= smaller_capacity)
-    goto loop_removed;
-  new_loops = (uv_loop_t**)
-      uv__realloc(uv__loops, sizeof(uv_loop_t*) * smaller_capacity);
-  if (!new_loops)
-    goto loop_removed;
-  uv__loops = new_loops;
-  uv__loops_capacity = smaller_capacity;
-
-loop_removed:
-  uv_mutex_unlock(&uv__loops_lock);
-}
-
-void uv__wake_all_loops(void) {
-  int i;
-  uv_loop_t* loop;
-
-  uv_mutex_lock(&uv__loops_lock);
-  for (i = 0; i < uv__loops_size; ++i) {
-    loop = uv__loops[i];
-    assert(loop);
-    if (loop->iocp != INVALID_HANDLE_VALUE)
-      PostQueuedCompletionStatus(loop->iocp, 0, 0, NULL);
-  }
-  uv_mutex_unlock(&uv__loops_lock);
-}
-
-static void uv_init(void) {
-  /* Tell Windows that we will handle critical errors. */
-  SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
-               SEM_NOOPENFILEERRORBOX);
-
-  /* Tell the CRT to not exit the application when an invalid parameter is
-   * passed. The main issue is that invalid FDs will trigger this behavior.
-   */
-#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800
-  _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler);
-#endif
-
-  /* We also need to setup our debug report handler because some CRT
-   * functions (eg _get_osfhandle) raise an assert when called with invalid
-   * FDs even though they return the proper error code in the release build.
-   */
-#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR))
-  _CrtSetReportHook(uv__crt_dbg_report_handler);
-#endif
-
-  /* Initialize tracking of all uv loops */
-  uv__loops_init();
-
-  /* Fetch winapi function pointers. This must be done first because other
-   * initialization code might need these function pointers to be loaded.
-   */
-  uv_winapi_init();
-
-  /* Initialize winsock */
-  uv_winsock_init();
-
-  /* Initialize FS */
-  uv_fs_init();
-
-  /* Initialize signal stuff */
-  uv_signals_init();
-
-  /* Initialize console */
-  uv_console_init();
-
-  /* Initialize utilities */
-  uv__util_init();
-
-  /* Initialize system wakeup detection */
-  uv__init_detect_system_wakeup();
-}
-
-
-int uv_loop_init(uv_loop_t* loop) {
-  struct heap* timer_heap;
-  int err;
-
-  /* Initialize libuv itself first */
-  uv__once_init();
-
-  /* Create an I/O completion port */
-  loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
-  if (loop->iocp == NULL)
-    return uv_translate_sys_error(GetLastError());
-
-  /* To prevent uninitialized memory access, loop->time must be initialized
-   * to zero before calling uv_update_time for the first time.
-   */
-  loop->time = 0;
-  uv_update_time(loop);
-
-  QUEUE_INIT(&loop->wq);
-  QUEUE_INIT(&loop->handle_queue);
-  loop->active_reqs.count = 0;
-  loop->active_handles = 0;
-
-  loop->pending_reqs_tail = NULL;
-
-  loop->endgame_handles = NULL;
-
-  loop->timer_heap = timer_heap = (heap*)uv__malloc(sizeof(*timer_heap));
-  if (timer_heap == NULL) {
-    err = UV_ENOMEM;
-    goto fail_timers_alloc;
-  }
-
-  heap_init(timer_heap);
-
-  loop->check_handles = NULL;
-  loop->prepare_handles = NULL;
-  loop->idle_handles = NULL;
-
-  loop->next_prepare_handle = NULL;
-  loop->next_check_handle = NULL;
-  loop->next_idle_handle = NULL;
-
-  memset(&loop->poll_peer_sockets, 0, sizeof loop->poll_peer_sockets);
-
-  loop->active_tcp_streams = 0;
-  loop->active_udp_streams = 0;
-
-  loop->timer_counter = 0;
-  loop->stop_flag = 0;
-
-  err = uv_mutex_init(&loop->wq_mutex);
-  if (err)
-    goto fail_mutex_init;
-
-  err = uv_async_init(loop, &loop->wq_async, uv__work_done);
-  if (err)
-    goto fail_async_init;
-
-  uv__handle_unref(&loop->wq_async);
-  loop->wq_async.flags |= UV_HANDLE_INTERNAL;
-
-  err = uv__loops_add(loop);
-  if (err)
-    goto fail_async_init;
-
-  return 0;
-
-fail_async_init:
-  uv_mutex_destroy(&loop->wq_mutex);
-
-fail_mutex_init:
-  uv__free(timer_heap);
-  loop->timer_heap = NULL;
-
-fail_timers_alloc:
-  CloseHandle(loop->iocp);
-  loop->iocp = INVALID_HANDLE_VALUE;
-
-  return err;
-}
-
-
-void uv_update_time(uv_loop_t* loop) {
-  uint64_t new_time = uv__hrtime(1000);
-  assert(new_time >= loop->time);
-  loop->time = new_time;
-}
-
-
-void uv__once_init(void) {
-  uv_once(&uv_init_guard_, uv_init);
-}
-
-
-void uv__loop_close(uv_loop_t* loop) {
-  size_t i;
-
-  uv__loops_remove(loop);
-
-  /* close the async handle without needing an extra loop iteration */
-  assert(!loop->wq_async.async_sent);
-  loop->wq_async.close_cb = NULL;
-  uv__handle_closing(&loop->wq_async);
-  uv__handle_close(&loop->wq_async);
-
-  for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
-    SOCKET sock = loop->poll_peer_sockets[i];
-    if (sock != 0 && sock != INVALID_SOCKET)
-      closesocket(sock);
-  }
-
-  uv_mutex_lock(&loop->wq_mutex);
-  assert(QUEUE_EMPTY(&loop->wq) && "thread pool work queue not empty!");
-  assert(!uv__has_active_reqs(loop));
-  uv_mutex_unlock(&loop->wq_mutex);
-  uv_mutex_destroy(&loop->wq_mutex);
-
-  uv__free(loop->timer_heap);
-  loop->timer_heap = NULL;
-
-  CloseHandle(loop->iocp);
-}
-
-
-int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
-  return UV_ENOSYS;
-}
-
-
-int uv_backend_fd(const uv_loop_t* loop) {
-  return -1;
-}
-
-
-int uv_loop_fork(uv_loop_t* loop) {
-  return UV_ENOSYS;
-}
-
-
-int uv_backend_timeout(const uv_loop_t* loop) {
-  if (loop->stop_flag != 0)
-    return 0;
-
-  if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
-    return 0;
-
-  if (loop->pending_reqs_tail)
-    return 0;
-
-  if (loop->endgame_handles)
-    return 0;
-
-  if (loop->idle_handles)
-    return 0;
-
-  return uv__next_timeout(loop);
-}
-
-
-static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) {
-  DWORD bytes;
-  ULONG_PTR key;
-  OVERLAPPED* overlapped;
-  uv_req_t* req;
-  int repeat;
-  uint64_t timeout_time;
-
-  timeout_time = loop->time + timeout;
-
-  for (repeat = 0; ; repeat++) {
-    GetQueuedCompletionStatus(loop->iocp,
-                              &bytes,
-                              &key,
-                              &overlapped,
-                              timeout);
-
-    if (overlapped) {
-      /* Package was dequeued */
-      req = uv_overlapped_to_req(overlapped);
-      uv_insert_pending_req(loop, req);
-
-      /* Some time might have passed waiting for I/O,
-       * so update the loop time here.
-       */
-      uv_update_time(loop);
-    } else if (GetLastError() != WAIT_TIMEOUT) {
-      /* Serious error */
-      uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus");
-    } else if (timeout > 0) {
-      /* GetQueuedCompletionStatus can occasionally return a little early.
-       * Make sure that the desired timeout target time is reached.
-       */
-      uv_update_time(loop);
-      if (timeout_time > loop->time) {
-        timeout = (DWORD)(timeout_time - loop->time);
-        /* The first call to GetQueuedCompletionStatus should return very
-         * close to the target time and the second should reach it, but
-         * this is not stated in the documentation. To make sure a busy
-         * loop cannot happen, the timeout is increased exponentially
-         * starting on the third round.
-         */
-        timeout += repeat ? (1 << (repeat - 1)) : 0;
-        continue;
-      }
-    }
-    break;
-  }
-}
-
-
-static void uv__poll(uv_loop_t* loop, DWORD timeout) {
-  BOOL success;
-  uv_req_t* req;
-  OVERLAPPED_ENTRY overlappeds[128];
-  ULONG count;
-  ULONG i;
-  int repeat;
-  uint64_t timeout_time;
-
-  timeout_time = loop->time + timeout;
-
-  for (repeat = 0; ; repeat++) {
-    success = GetQueuedCompletionStatusEx(loop->iocp,
-                                          overlappeds,
-                                          ARRAY_SIZE(overlappeds),
-                                          &count,
-                                          timeout,
-                                          FALSE);
-
-    if (success) {
-      for (i = 0; i < count; i++) {
-        /* Package was dequeued, but see if it is not a empty package
-         * meant only to wake us up.
-         */
-        if (overlappeds[i].lpOverlapped) {
-          req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
-          uv_insert_pending_req(loop, req);
-        }
-      }
-
-      /* Some time might have passed waiting for I/O,
-       * so update the loop time here.
-       */
-      uv_update_time(loop);
-    } else if (GetLastError() != WAIT_TIMEOUT) {
-      /* Serious error */
-      uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
-    } else if (timeout > 0) {
-      /* GetQueuedCompletionStatus can occasionally return a little early.
-       * Make sure that the desired timeout target time is reached.
-       */
-      uv_update_time(loop);
-      if (timeout_time > loop->time) {
-        timeout = (DWORD)(timeout_time - loop->time);
-        /* The first call to GetQueuedCompletionStatus should return very
-         * close to the target time and the second should reach it, but
-         * this is not stated in the documentation. To make sure a busy
-         * loop cannot happen, the timeout is increased exponentially
-         * starting on the third round.
-         */
-        timeout += repeat ? (1 << (repeat - 1)) : 0;
-        continue;
-      }
-    }
-    break;
-  }
-}
-
-
-static int uv__loop_alive(const uv_loop_t* loop) {
-  return uv__has_active_handles(loop) ||
-         uv__has_active_reqs(loop) ||
-         loop->endgame_handles != NULL;
-}
-
-
-int uv_loop_alive(const uv_loop_t* loop) {
-    return uv__loop_alive(loop);
-}
-
-
-int uv_run(uv_loop_t *loop, uv_run_mode mode) {
-  DWORD timeout;
-  int r;
-  int ran_pending;
-
-  r = uv__loop_alive(loop);
-  if (!r)
-    uv_update_time(loop);
-
-  while (r != 0 && loop->stop_flag == 0) {
-    uv_update_time(loop);
-    uv__run_timers(loop);
-
-    ran_pending = uv_process_reqs(loop);
-    uv_idle_invoke(loop);
-    uv_prepare_invoke(loop);
-
-    timeout = 0;
-    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
-      timeout = uv_backend_timeout(loop);
-
-    if (pGetQueuedCompletionStatusEx)
-      uv__poll(loop, timeout);
-    else
-      uv__poll_wine(loop, timeout);
-
-
-    uv_check_invoke(loop);
-    uv_process_endgames(loop);
-
-    if (mode == UV_RUN_ONCE) {
-      /* UV_RUN_ONCE implies forward progress: at least one callback must have
-       * been invoked when it returns. uv__io_poll() can return without doing
-       * I/O (meaning: no callbacks) when its timeout expires - which means we
-       * have pending timers that satisfy the forward progress constraint.
-       *
-       * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
-       * the check.
-       */
-      uv__run_timers(loop);
-    }
-
-    r = uv__loop_alive(loop);
-    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
-      break;
-  }
-
-  /* The if statement lets the compiler compile it to a conditional store.
-   * Avoids dirtying a cache line.
-   */
-  if (loop->stop_flag != 0)
-    loop->stop_flag = 0;
-
-  return r;
-}
-
-
-int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
-  uv_os_fd_t fd_out;
-
-  switch (handle->type) {
-  case UV_TCP:
-    fd_out = (uv_os_fd_t)((uv_tcp_t*) handle)->socket;
-    break;
-
-  case UV_NAMED_PIPE:
-    fd_out = ((uv_pipe_t*) handle)->handle;
-    break;
-
-  case UV_TTY:
-    fd_out = ((uv_tty_t*) handle)->handle;
-    break;
-
-  case UV_UDP:
-    fd_out = (uv_os_fd_t)((uv_udp_t*) handle)->socket;
-    break;
-
-  case UV_POLL:
-    fd_out = (uv_os_fd_t)((uv_poll_t*) handle)->socket;
-    break;
-
-  default:
-    return UV_EINVAL;
-  }
-
-  if (uv_is_closing(handle) || fd_out == INVALID_HANDLE_VALUE)
-    return UV_EBADF;
-
-  *fd = fd_out;
-  return 0;
-}
-
-
-int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
-  int r;
-  int len;
-  SOCKET socket;
-
-  if (handle == NULL || value == NULL)
-    return UV_EINVAL;
-
-  if (handle->type == UV_TCP)
-    socket = ((uv_tcp_t*) handle)->socket;
-  else if (handle->type == UV_UDP)
-    socket = ((uv_udp_t*) handle)->socket;
-  else
-    return UV_ENOTSUP;
-
-  len = sizeof(*value);
-
-  if (*value == 0)
-    r = getsockopt(socket, SOL_SOCKET, optname, (char*) value, &len);
-  else
-    r = setsockopt(socket, SOL_SOCKET, optname, (const char*) value, len);
-
-  if (r == SOCKET_ERROR)
-    return uv_translate_sys_error(WSAGetLastError());
-
-  return 0;
-}
-
-int uv_cpumask_size(void) {
-  return (int)(sizeof(DWORD_PTR) * 8);
-}
-
-int uv__getsockpeername(const uv_handle_t* handle,
-                        uv__peersockfunc func,
-                        struct sockaddr* name,
-                        int* namelen,
-                        int delayed_error) {
-
-  int result;
-  uv_os_fd_t fd;
-
-  result = uv_fileno(handle, &fd);
-  if (result != 0)
-    return result;
-
-  if (delayed_error)
-    return uv_translate_sys_error(delayed_error);
-
-  result = func((SOCKET) fd, name, namelen);
-  if (result != 0)
-    return uv_translate_sys_error(WSAGetLastError());
-
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/detect-wakeup.cpp b/wpiutil/src/main/native/libuv/src/win/detect-wakeup.cpp
deleted file mode 100644
index 72dfb7a..0000000
--- a/wpiutil/src/main/native/libuv/src/win/detect-wakeup.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "uv.h"
-#include "internal.h"
-#include "winapi.h"
-
-static void uv__register_system_resume_callback(void);
-
-void uv__init_detect_system_wakeup(void) {
-  /* Try registering system power event callback. This is the cleanest
-   * method, but it will only work on Win8 and above.
-   */
-  uv__register_system_resume_callback();
-}
-
-static ULONG CALLBACK uv__system_resume_callback(PVOID Context,
-                                                 ULONG Type,
-                                                 PVOID Setting) {
-  if (Type == PBT_APMRESUMESUSPEND || Type == PBT_APMRESUMEAUTOMATIC)
-    uv__wake_all_loops();
-
-  return 0;
-}
-
-static void uv__register_system_resume_callback(void) {
-  _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS recipient;
-  _HPOWERNOTIFY registration_handle;
-
-  if (pPowerRegisterSuspendResumeNotification == NULL)
-    return;
-
-  recipient.Callback = uv__system_resume_callback;
-  recipient.Context = NULL;
-  (*pPowerRegisterSuspendResumeNotification)(DEVICE_NOTIFY_CALLBACK,
-                                             &recipient,
-                                             &registration_handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/dl.cpp b/wpiutil/src/main/native/libuv/src/win/dl.cpp
deleted file mode 100644
index 676be4d..0000000
--- a/wpiutil/src/main/native/libuv/src/win/dl.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "uv.h"
-#include "internal.h"
-
-static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno);
-
-
-int uv_dlopen(const char* filename, uv_lib_t* lib) {
-  WCHAR filename_w[32768];
-
-  lib->handle = NULL;
-  lib->errmsg = NULL;
-
-  if (!MultiByteToWideChar(CP_UTF8,
-                           0,
-                           filename,
-                           -1,
-                           filename_w,
-                           ARRAY_SIZE(filename_w))) {
-    return uv__dlerror(lib, filename, GetLastError());
-  }
-
-  lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
-  if (lib->handle == NULL) {
-    return uv__dlerror(lib, filename, GetLastError());
-  }
-
-  return 0;
-}
-
-
-void uv_dlclose(uv_lib_t* lib) {
-  if (lib->errmsg) {
-    LocalFree((void*)lib->errmsg);
-    lib->errmsg = NULL;
-  }
-
-  if (lib->handle) {
-    /* Ignore errors. No good way to signal them without leaking memory. */
-    FreeLibrary(lib->handle);
-    lib->handle = NULL;
-  }
-}
-
-
-int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
-  /* Cast though integer to suppress pedantic warning about forbidden cast. */
-  *ptr = (void*)(uintptr_t) GetProcAddress(lib->handle, name);
-  return uv__dlerror(lib, "", *ptr ? 0 : GetLastError());
-}
-
-
-const char* uv_dlerror(const uv_lib_t* lib) {
-  return lib->errmsg ? lib->errmsg : "no error";
-}
-
-
-static void uv__format_fallback_error(uv_lib_t* lib, int errorno){
-  static const CHAR fallback_error[] = "error: %1!d!";
-  DWORD_PTR args[1];
-  args[0] = (DWORD_PTR) errorno;
-
-  FormatMessageA(FORMAT_MESSAGE_FROM_STRING |
-                 FORMAT_MESSAGE_ARGUMENT_ARRAY |
-                 FORMAT_MESSAGE_ALLOCATE_BUFFER,
-                 fallback_error, 0, 0,
-                 (LPSTR) &lib->errmsg,
-                 0, (va_list*) args);
-}
-
-
-
-static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) {
-  DWORD_PTR arg;
-  DWORD res;
-  char* msg;
-
-  if (lib->errmsg) {
-    LocalFree(lib->errmsg);
-    lib->errmsg = NULL;
-  }
-
-  if (errorno == 0)
-    return 0;
-
-  res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                       FORMAT_MESSAGE_FROM_SYSTEM |
-                       FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
-                       MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
-                       (LPSTR) &lib->errmsg, 0, NULL);
-
-  if (!res && (GetLastError() == ERROR_MUI_FILE_NOT_FOUND ||
-               GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)) {
-    res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                         FORMAT_MESSAGE_FROM_SYSTEM |
-                         FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
-                         0, (LPSTR) &lib->errmsg, 0, NULL);
-  }
-
-  if (res && errorno == ERROR_BAD_EXE_FORMAT && strstr(lib->errmsg, "%1")) {
-    msg = lib->errmsg;
-    lib->errmsg = NULL;
-    arg = (DWORD_PTR) filename;
-    res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                         FORMAT_MESSAGE_ARGUMENT_ARRAY |
-                         FORMAT_MESSAGE_FROM_STRING,
-                         msg,
-                         0, 0, (LPSTR) &lib->errmsg, 0, (va_list*) &arg);
-    LocalFree(msg);
-  }
-
-  if (!res)
-    uv__format_fallback_error(lib, errorno);
-
-  return -1;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/error.cpp b/wpiutil/src/main/native/libuv/src/win/error.cpp
deleted file mode 100644
index 24924ba..0000000
--- a/wpiutil/src/main/native/libuv/src/win/error.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "uv.h"
-#include "internal.h"
-
-
-/*
- * Display an error message and abort the event loop.
- */
-void uv_fatal_error(const int errorno, const char* syscall) {
-  char* buf = NULL;
-  const char* errmsg;
-
-  FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
-      FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
-      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, NULL);
-
-  if (buf) {
-    errmsg = buf;
-  } else {
-    errmsg = "Unknown error";
-  }
-
-  /* FormatMessage messages include a newline character already, so don't add
-   * another. */
-  if (syscall) {
-    fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg);
-  } else {
-    fprintf(stderr, "(%d) %s", errorno, errmsg);
-  }
-
-  if (buf) {
-    LocalFree(buf);
-  }
-
-  DebugBreak();
-  abort();
-}
-
-
-int uv_translate_sys_error(int sys_errno) {
-  if (sys_errno <= 0) {
-    return sys_errno;  /* If < 0 then it's already a libuv error. */
-  }
-
-  switch (sys_errno) {
-    case ERROR_NOACCESS:                    return UV_EACCES;
-    case WSAEACCES:                         return UV_EACCES;
-    case ERROR_ELEVATION_REQUIRED:          return UV_EACCES;
-    case ERROR_ADDRESS_ALREADY_ASSOCIATED:  return UV_EADDRINUSE;
-    case WSAEADDRINUSE:                     return UV_EADDRINUSE;
-    case WSAEADDRNOTAVAIL:                  return UV_EADDRNOTAVAIL;
-    case WSAEAFNOSUPPORT:                   return UV_EAFNOSUPPORT;
-    case WSAEWOULDBLOCK:                    return UV_EAGAIN;
-    case WSAEALREADY:                       return UV_EALREADY;
-    case ERROR_INVALID_FLAGS:               return UV_EBADF;
-    case ERROR_INVALID_HANDLE:              return UV_EBADF;
-    case ERROR_LOCK_VIOLATION:              return UV_EBUSY;
-    case ERROR_PIPE_BUSY:                   return UV_EBUSY;
-    case ERROR_SHARING_VIOLATION:           return UV_EBUSY;
-    case ERROR_OPERATION_ABORTED:           return UV_ECANCELED;
-    case WSAEINTR:                          return UV_ECANCELED;
-    case ERROR_NO_UNICODE_TRANSLATION:      return UV_ECHARSET;
-    case ERROR_CONNECTION_ABORTED:          return UV_ECONNABORTED;
-    case WSAECONNABORTED:                   return UV_ECONNABORTED;
-    case ERROR_CONNECTION_REFUSED:          return UV_ECONNREFUSED;
-    case WSAECONNREFUSED:                   return UV_ECONNREFUSED;
-    case ERROR_NETNAME_DELETED:             return UV_ECONNRESET;
-    case WSAECONNRESET:                     return UV_ECONNRESET;
-    case ERROR_ALREADY_EXISTS:              return UV_EEXIST;
-    case ERROR_FILE_EXISTS:                 return UV_EEXIST;
-    case ERROR_BUFFER_OVERFLOW:             return UV_EFAULT;
-    case WSAEFAULT:                         return UV_EFAULT;
-    case ERROR_HOST_UNREACHABLE:            return UV_EHOSTUNREACH;
-    case WSAEHOSTUNREACH:                   return UV_EHOSTUNREACH;
-    case ERROR_INSUFFICIENT_BUFFER:         return UV_EINVAL;
-    case ERROR_INVALID_DATA:                return UV_EINVAL;
-    case ERROR_INVALID_PARAMETER:           return UV_EINVAL;
-    case ERROR_SYMLINK_NOT_SUPPORTED:       return UV_EINVAL;
-    case WSAEINVAL:                         return UV_EINVAL;
-    case WSAEPFNOSUPPORT:                   return UV_EINVAL;
-    case WSAESOCKTNOSUPPORT:                return UV_EINVAL;
-    case ERROR_BEGINNING_OF_MEDIA:          return UV_EIO;
-    case ERROR_BUS_RESET:                   return UV_EIO;
-    case ERROR_CRC:                         return UV_EIO;
-    case ERROR_DEVICE_DOOR_OPEN:            return UV_EIO;
-    case ERROR_DEVICE_REQUIRES_CLEANING:    return UV_EIO;
-    case ERROR_DISK_CORRUPT:                return UV_EIO;
-    case ERROR_EOM_OVERFLOW:                return UV_EIO;
-    case ERROR_FILEMARK_DETECTED:           return UV_EIO;
-    case ERROR_GEN_FAILURE:                 return UV_EIO;
-    case ERROR_INVALID_BLOCK_LENGTH:        return UV_EIO;
-    case ERROR_IO_DEVICE:                   return UV_EIO;
-    case ERROR_NO_DATA_DETECTED:            return UV_EIO;
-    case ERROR_NO_SIGNAL_SENT:              return UV_EIO;
-    case ERROR_OPEN_FAILED:                 return UV_EIO;
-    case ERROR_SETMARK_DETECTED:            return UV_EIO;
-    case ERROR_SIGNAL_REFUSED:              return UV_EIO;
-    case WSAEISCONN:                        return UV_EISCONN;
-    case ERROR_CANT_RESOLVE_FILENAME:       return UV_ELOOP;
-    case ERROR_TOO_MANY_OPEN_FILES:         return UV_EMFILE;
-    case WSAEMFILE:                         return UV_EMFILE;
-    case WSAEMSGSIZE:                       return UV_EMSGSIZE;
-    case ERROR_FILENAME_EXCED_RANGE:        return UV_ENAMETOOLONG;
-    case ERROR_NETWORK_UNREACHABLE:         return UV_ENETUNREACH;
-    case WSAENETUNREACH:                    return UV_ENETUNREACH;
-    case WSAENOBUFS:                        return UV_ENOBUFS;
-    case ERROR_BAD_PATHNAME:                return UV_ENOENT;
-    case ERROR_DIRECTORY:                   return UV_ENOENT;
-    case ERROR_FILE_NOT_FOUND:              return UV_ENOENT;
-    case ERROR_INVALID_NAME:                return UV_ENOENT;
-    case ERROR_INVALID_DRIVE:               return UV_ENOENT;
-    case ERROR_INVALID_REPARSE_DATA:        return UV_ENOENT;
-    case ERROR_MOD_NOT_FOUND:               return UV_ENOENT;
-    case ERROR_PATH_NOT_FOUND:              return UV_ENOENT;
-    case WSAHOST_NOT_FOUND:                 return UV_ENOENT;
-    case WSANO_DATA:                        return UV_ENOENT;
-    case ERROR_NOT_ENOUGH_MEMORY:           return UV_ENOMEM;
-    case ERROR_OUTOFMEMORY:                 return UV_ENOMEM;
-    case ERROR_CANNOT_MAKE:                 return UV_ENOSPC;
-    case ERROR_DISK_FULL:                   return UV_ENOSPC;
-    case ERROR_EA_TABLE_FULL:               return UV_ENOSPC;
-    case ERROR_END_OF_MEDIA:                return UV_ENOSPC;
-    case ERROR_HANDLE_DISK_FULL:            return UV_ENOSPC;
-    case ERROR_NOT_CONNECTED:               return UV_ENOTCONN;
-    case WSAENOTCONN:                       return UV_ENOTCONN;
-    case ERROR_DIR_NOT_EMPTY:               return UV_ENOTEMPTY;
-    case WSAENOTSOCK:                       return UV_ENOTSOCK;
-    case ERROR_NOT_SUPPORTED:               return UV_ENOTSUP;
-    case ERROR_BROKEN_PIPE:                 return UV_EOF;
-    case ERROR_ACCESS_DENIED:               return UV_EPERM;
-    case ERROR_PRIVILEGE_NOT_HELD:          return UV_EPERM;
-    case ERROR_BAD_PIPE:                    return UV_EPIPE;
-    case ERROR_NO_DATA:                     return UV_EPIPE;
-    case ERROR_PIPE_NOT_CONNECTED:          return UV_EPIPE;
-    case WSAESHUTDOWN:                      return UV_EPIPE;
-    case WSAEPROTONOSUPPORT:                return UV_EPROTONOSUPPORT;
-    case ERROR_WRITE_PROTECT:               return UV_EROFS;
-    case ERROR_SEM_TIMEOUT:                 return UV_ETIMEDOUT;
-    case WSAETIMEDOUT:                      return UV_ETIMEDOUT;
-    case ERROR_NOT_SAME_DEVICE:             return UV_EXDEV;
-    case ERROR_INVALID_FUNCTION:            return UV_EISDIR;
-    case ERROR_META_EXPANSION_TOO_LONG:     return UV_E2BIG;
-    default:                                return UV_UNKNOWN;
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/fs-event.cpp b/wpiutil/src/main/native/libuv/src/win/fs-event.cpp
deleted file mode 100644
index b9ec025..0000000
--- a/wpiutil/src/main/native/libuv/src/win/fs-event.cpp
+++ /dev/null
@@ -1,591 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#define _CRT_NONSTDC_NO_WARNINGS
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "req-inl.h"
-
-
-const unsigned int uv_directory_watcher_buffer_size = 4096;
-
-
-static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop,
-    uv_fs_event_t* handle) {
-  assert(handle->dir_handle != INVALID_HANDLE_VALUE);
-  assert(!handle->req_pending);
-
-  memset(&(handle->req.u.io.overlapped), 0,
-         sizeof(handle->req.u.io.overlapped));
-  if (!ReadDirectoryChangesW(handle->dir_handle,
-                             handle->buffer,
-                             uv_directory_watcher_buffer_size,
-                             (handle->flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE,
-                             FILE_NOTIFY_CHANGE_FILE_NAME      |
-                               FILE_NOTIFY_CHANGE_DIR_NAME     |
-                               FILE_NOTIFY_CHANGE_ATTRIBUTES   |
-                               FILE_NOTIFY_CHANGE_SIZE         |
-                               FILE_NOTIFY_CHANGE_LAST_WRITE   |
-                               FILE_NOTIFY_CHANGE_LAST_ACCESS  |
-                               FILE_NOTIFY_CHANGE_CREATION     |
-                               FILE_NOTIFY_CHANGE_SECURITY,
-                             NULL,
-                             &handle->req.u.io.overlapped,
-                             NULL)) {
-    /* Make this req pending reporting an error. */
-    SET_REQ_ERROR(&handle->req, GetLastError());
-    uv_insert_pending_req(loop, (uv_req_t*)&handle->req);
-  }
-
-  handle->req_pending = 1;
-}
-
-static void uv_relative_path(const WCHAR* filename,
-                             const WCHAR* dir,
-                             WCHAR** relpath) {
-  size_t relpathlen;
-  size_t filenamelen = wcslen(filename);
-  size_t dirlen = wcslen(dir);
-  assert(!_wcsnicmp(filename, dir, dirlen));
-  if (dirlen > 0 && dir[dirlen - 1] == '\\')
-    dirlen--;
-  relpathlen = filenamelen - dirlen - 1;
-  *relpath = (WCHAR*)uv__malloc((relpathlen + 1) * sizeof(WCHAR));
-  if (!*relpath)
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  wcsncpy(*relpath, filename + dirlen + 1, relpathlen);
-  (*relpath)[relpathlen] = L'\0';
-}
-
-static int uv_split_path(const WCHAR* filename, WCHAR** dir,
-    WCHAR** file) {
-  size_t len, i;
-
-  if (filename == NULL) {
-    if (dir != NULL)
-      *dir = NULL;
-    *file = NULL;
-    return 0;
-  }
-
-  len = wcslen(filename);
-  i = len;
-  while (i > 0 && filename[--i] != '\\' && filename[i] != '/');
-
-  if (i == 0) {
-    if (dir) {
-      *dir = (WCHAR*)uv__malloc((MAX_PATH + 1) * sizeof(WCHAR));
-      if (!*dir) {
-        uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-      }
-
-      if (!GetCurrentDirectoryW(MAX_PATH, *dir)) {
-        uv__free(*dir);
-        *dir = NULL;
-        return -1;
-      }
-    }
-
-    *file = wcsdup(filename);
-  } else {
-    if (dir) {
-      *dir = (WCHAR*)uv__malloc((i + 2) * sizeof(WCHAR));
-      if (!*dir) {
-        uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-      }
-      wcsncpy(*dir, filename, i + 1);
-      (*dir)[i + 1] = L'\0';
-    }
-
-    *file = (WCHAR*)uv__malloc((len - i) * sizeof(WCHAR));
-    if (!*file) {
-      uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-    }
-    wcsncpy(*file, filename + i + 1, len - i - 1);
-    (*file)[len - i - 1] = L'\0';
-  }
-
-  return 0;
-}
-
-
-int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
-  uv__handle_init(loop, (uv_handle_t*) handle, UV_FS_EVENT);
-  handle->dir_handle = INVALID_HANDLE_VALUE;
-  handle->buffer = NULL;
-  handle->req_pending = 0;
-  handle->filew = NULL;
-  handle->short_filew = NULL;
-  handle->dirw = NULL;
-
-  UV_REQ_INIT(&handle->req, UV_FS_EVENT_REQ);
-  handle->req.data = handle;
-
-  return 0;
-}
-
-
-int uv_fs_event_start(uv_fs_event_t* handle,
-                      uv_fs_event_cb cb,
-                      const char* path,
-                      unsigned int flags) {
-  int name_size, is_path_dir, size;
-  DWORD attr, last_error;
-  WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
-  WCHAR short_path_buffer[MAX_PATH];
-  WCHAR* short_path, *long_path;
-
-  if (uv__is_active(handle))
-    return UV_EINVAL;
-
-  handle->cb = cb;
-  handle->path = uv__strdup(path);
-  if (!handle->path) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  uv__handle_start(handle);
-
-  /* Convert name to UTF16. */
-
-  name_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) *
-              sizeof(WCHAR);
-  pathw = (WCHAR*)uv__malloc(name_size);
-  if (!pathw) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  if (!MultiByteToWideChar(CP_UTF8,
-                           0,
-                           path,
-                           -1,
-                           pathw,
-                           name_size / sizeof(WCHAR))) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  /* Determine whether path is a file or a directory. */
-  attr = GetFileAttributesW(pathw);
-  if (attr == INVALID_FILE_ATTRIBUTES) {
-    last_error = GetLastError();
-    goto error;
-  }
-
-  is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
-
-  if (is_path_dir) {
-     /* path is a directory, so that's the directory that we will watch. */
-
-    /* Convert to long path. */
-    size = GetLongPathNameW(pathw, NULL, 0);
-
-    if (size) {
-      long_path = (WCHAR*)uv__malloc(size * sizeof(WCHAR));
-      if (!long_path) {
-        uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-      }
-
-      size = GetLongPathNameW(pathw, long_path, size);
-      if (size) {
-        long_path[size] = '\0';
-      } else {
-        uv__free(long_path);
-        long_path = NULL;
-      }
-
-      if (long_path) {
-        uv__free(pathw);
-        pathw = long_path;
-      }
-    }
-
-    dir_to_watch = pathw;
-  } else {
-    /*
-     * path is a file.  So we split path into dir & file parts, and
-     * watch the dir directory.
-     */
-
-    /* Convert to short path. */
-    if (GetShortPathNameW(pathw,
-                          short_path_buffer,
-                          ARRAY_SIZE(short_path_buffer))) {
-      short_path = short_path_buffer;
-    } else {
-      short_path = NULL;
-    }
-
-    if (uv_split_path(pathw, &dir, &handle->filew) != 0) {
-      last_error = GetLastError();
-      goto error;
-    }
-
-    if (uv_split_path(short_path, NULL, &handle->short_filew) != 0) {
-      last_error = GetLastError();
-      goto error;
-    }
-
-    dir_to_watch = dir;
-    uv__free(pathw);
-    pathw = NULL;
-  }
-
-  handle->dir_handle = CreateFileW(dir_to_watch,
-                                   FILE_LIST_DIRECTORY,
-                                   FILE_SHARE_READ | FILE_SHARE_DELETE |
-                                     FILE_SHARE_WRITE,
-                                   NULL,
-                                   OPEN_EXISTING,
-                                   FILE_FLAG_BACKUP_SEMANTICS |
-                                     FILE_FLAG_OVERLAPPED,
-                                   NULL);
-
-  if (dir) {
-    uv__free(dir);
-    dir = NULL;
-  }
-
-  if (handle->dir_handle == INVALID_HANDLE_VALUE) {
-    last_error = GetLastError();
-    goto error;
-  }
-
-  if (CreateIoCompletionPort(handle->dir_handle,
-                             handle->loop->iocp,
-                             (ULONG_PTR)handle,
-                             0) == NULL) {
-    last_error = GetLastError();
-    goto error;
-  }
-
-  if (!handle->buffer) {
-    handle->buffer = (char*)uv__malloc(uv_directory_watcher_buffer_size);
-  }
-  if (!handle->buffer) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  memset(&(handle->req.u.io.overlapped), 0,
-         sizeof(handle->req.u.io.overlapped));
-
-  if (!ReadDirectoryChangesW(handle->dir_handle,
-                             handle->buffer,
-                             uv_directory_watcher_buffer_size,
-                             (flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE,
-                             FILE_NOTIFY_CHANGE_FILE_NAME      |
-                               FILE_NOTIFY_CHANGE_DIR_NAME     |
-                               FILE_NOTIFY_CHANGE_ATTRIBUTES   |
-                               FILE_NOTIFY_CHANGE_SIZE         |
-                               FILE_NOTIFY_CHANGE_LAST_WRITE   |
-                               FILE_NOTIFY_CHANGE_LAST_ACCESS  |
-                               FILE_NOTIFY_CHANGE_CREATION     |
-                               FILE_NOTIFY_CHANGE_SECURITY,
-                             NULL,
-                             &handle->req.u.io.overlapped,
-                             NULL)) {
-    last_error = GetLastError();
-    goto error;
-  }
-
-  assert(is_path_dir ? pathw != NULL : pathw == NULL);
-  handle->dirw = pathw;
-  handle->req_pending = 1;
-  return 0;
-
-error:
-  if (handle->path) {
-    uv__free(handle->path);
-    handle->path = NULL;
-  }
-
-  if (handle->filew) {
-    uv__free(handle->filew);
-    handle->filew = NULL;
-  }
-
-  if (handle->short_filew) {
-    uv__free(handle->short_filew);
-    handle->short_filew = NULL;
-  }
-
-  uv__free(pathw);
-
-  if (handle->dir_handle != INVALID_HANDLE_VALUE) {
-    CloseHandle(handle->dir_handle);
-    handle->dir_handle = INVALID_HANDLE_VALUE;
-  }
-
-  if (handle->buffer) {
-    uv__free(handle->buffer);
-    handle->buffer = NULL;
-  }
-
-  if (uv__is_active(handle))
-    uv__handle_stop(handle);
-
-  return uv_translate_sys_error(last_error);
-}
-
-
-int uv_fs_event_stop(uv_fs_event_t* handle) {
-  if (!uv__is_active(handle))
-    return 0;
-
-  if (handle->dir_handle != INVALID_HANDLE_VALUE) {
-    CloseHandle(handle->dir_handle);
-    handle->dir_handle = INVALID_HANDLE_VALUE;
-  }
-
-  uv__handle_stop(handle);
-
-  if (handle->filew) {
-    uv__free(handle->filew);
-    handle->filew = NULL;
-  }
-
-  if (handle->short_filew) {
-    uv__free(handle->short_filew);
-    handle->short_filew = NULL;
-  }
-
-  if (handle->path) {
-    uv__free(handle->path);
-    handle->path = NULL;
-  }
-
-  if (handle->dirw) {
-    uv__free(handle->dirw);
-    handle->dirw = NULL;
-  }
-
-  return 0;
-}
-
-
-static int file_info_cmp(WCHAR* str, WCHAR* file_name, size_t file_name_len) {
-  size_t str_len;
-
-  if (str == NULL)
-    return -1;
-
-  str_len = wcslen(str);
-
-  /*
-    Since we only care about equality, return early if the strings
-    aren't the same length
-  */
-  if (str_len != (file_name_len / sizeof(WCHAR)))
-    return -1;
-
-  return _wcsnicmp(str, file_name, str_len);
-}
-
-
-void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
-    uv_fs_event_t* handle) {
-  FILE_NOTIFY_INFORMATION* file_info;
-  int err, sizew, size;
-  char* filename = NULL;
-  WCHAR* filenamew = NULL;
-  WCHAR* long_filenamew = NULL;
-  DWORD offset = 0;
-
-  assert(req->type == UV_FS_EVENT_REQ);
-  assert(handle->req_pending);
-  handle->req_pending = 0;
-
-  /* Don't report any callbacks if:
-   * - We're closing, just push the handle onto the endgame queue
-   * - We are not active, just ignore the callback
-   */
-  if (!uv__is_active(handle)) {
-    if (handle->flags & UV_HANDLE_CLOSING) {
-      uv_want_endgame(loop, (uv_handle_t*) handle);
-    }
-    return;
-  }
-
-  file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset);
-
-  if (REQ_SUCCESS(req)) {
-    if (req->u.io.overlapped.InternalHigh > 0) {
-      do {
-        file_info = (FILE_NOTIFY_INFORMATION*)((char*)file_info + offset);
-        assert(!filename);
-        assert(!filenamew);
-        assert(!long_filenamew);
-
-        /*
-         * Fire the event only if we were asked to watch a directory,
-         * or if the filename filter matches.
-         */
-        if (handle->dirw ||
-            file_info_cmp(handle->filew,
-                          file_info->FileName,
-                          file_info->FileNameLength) == 0 ||
-            file_info_cmp(handle->short_filew,
-                          file_info->FileName,
-                          file_info->FileNameLength) == 0) {
-
-          if (handle->dirw) {
-            /*
-             * We attempt to resolve the long form of the file name explicitly.
-             * We only do this for file names that might still exist on disk.
-             * If this fails, we use the name given by ReadDirectoryChangesW.
-             * This may be the long form or the 8.3 short name in some cases.
-             */
-            if (file_info->Action != FILE_ACTION_REMOVED &&
-              file_info->Action != FILE_ACTION_RENAMED_OLD_NAME) {
-              /* Construct a full path to the file. */
-              size = wcslen(handle->dirw) +
-                file_info->FileNameLength / sizeof(WCHAR) + 2;
-
-              filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR));
-              if (!filenamew) {
-                uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-              }
-
-              _snwprintf(filenamew, size, L"%s\\%.*s", handle->dirw,
-                file_info->FileNameLength / (DWORD)sizeof(WCHAR),
-                file_info->FileName);
-
-              filenamew[size - 1] = L'\0';
-
-              /* Convert to long name. */
-              size = GetLongPathNameW(filenamew, NULL, 0);
-
-              if (size) {
-                long_filenamew = (WCHAR*)uv__malloc(size * sizeof(WCHAR));
-                if (!long_filenamew) {
-                  uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-                }
-
-                size = GetLongPathNameW(filenamew, long_filenamew, size);
-                if (size) {
-                  long_filenamew[size] = '\0';
-                } else {
-                  uv__free(long_filenamew);
-                  long_filenamew = NULL;
-                }
-              }
-
-              uv__free(filenamew);
-
-              if (long_filenamew) {
-                /* Get the file name out of the long path. */
-                uv_relative_path(long_filenamew,
-                                 handle->dirw,
-                                 &filenamew);
-                uv__free(long_filenamew);
-                long_filenamew = filenamew;
-                sizew = -1;
-              } else {
-                /* We couldn't get the long filename, use the one reported. */
-                filenamew = file_info->FileName;
-                sizew = file_info->FileNameLength / sizeof(WCHAR);
-              }
-            } else {
-              /*
-               * Removed or renamed events cannot be resolved to the long form.
-               * We therefore use the name given by ReadDirectoryChangesW.
-               * This may be the long form or the 8.3 short name in some cases.
-               */
-              filenamew = file_info->FileName;
-              sizew = file_info->FileNameLength / sizeof(WCHAR);
-            }
-          } else {
-            /* We already have the long name of the file, so just use it. */
-            filenamew = handle->filew;
-            sizew = -1;
-          }
-
-          /* Convert the filename to utf8. */
-          uv__convert_utf16_to_utf8(filenamew, sizew, &filename);
-
-          switch (file_info->Action) {
-            case FILE_ACTION_ADDED:
-            case FILE_ACTION_REMOVED:
-            case FILE_ACTION_RENAMED_OLD_NAME:
-            case FILE_ACTION_RENAMED_NEW_NAME:
-              handle->cb(handle, filename, UV_RENAME, 0);
-              break;
-
-            case FILE_ACTION_MODIFIED:
-              handle->cb(handle, filename, UV_CHANGE, 0);
-              break;
-          }
-
-          uv__free(filename);
-          filename = NULL;
-          uv__free(long_filenamew);
-          long_filenamew = NULL;
-          filenamew = NULL;
-        }
-
-        offset = file_info->NextEntryOffset;
-      } while (offset && !(handle->flags & UV_HANDLE_CLOSING));
-    } else {
-      handle->cb(handle, NULL, UV_CHANGE, 0);
-    }
-  } else {
-    err = GET_REQ_ERROR(req);
-    handle->cb(handle, NULL, 0, uv_translate_sys_error(err));
-  }
-
-  if (!(handle->flags & UV_HANDLE_CLOSING)) {
-    uv_fs_event_queue_readdirchanges(loop, handle);
-  } else {
-    uv_want_endgame(loop, (uv_handle_t*)handle);
-  }
-}
-
-
-void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) {
-  uv_fs_event_stop(handle);
-
-  uv__handle_closing(handle);
-
-  if (!handle->req_pending) {
-    uv_want_endgame(loop, (uv_handle_t*)handle);
-  }
-
-}
-
-
-void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) {
-  if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) {
-    assert(!(handle->flags & UV_HANDLE_CLOSED));
-
-    if (handle->buffer) {
-      uv__free(handle->buffer);
-      handle->buffer = NULL;
-    }
-
-    uv__handle_close(handle);
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/fs.cpp b/wpiutil/src/main/native/libuv/src/win/fs.cpp
deleted file mode 100644
index 6b9e37b..0000000
--- a/wpiutil/src/main/native/libuv/src/win/fs.cpp
+++ /dev/null
@@ -1,2721 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#define _CRT_NONSTDC_NO_WARNINGS
-
-#include <assert.h>
-#include <stdlib.h>
-#include <direct.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <io.h>
-#include <limits.h>
-#include <sys/stat.h>
-#include <sys/utime.h>
-#include <stdio.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "req-inl.h"
-#include "handle-inl.h"
-
-#include <wincrypt.h>
-
-#pragma comment(lib, "Advapi32.lib")
-
-#define UV_FS_FREE_PATHS         0x0002
-#define UV_FS_FREE_PTR           0x0008
-#define UV_FS_CLEANEDUP          0x0010
-
-
-#define INIT(subtype)                                                         \
-  do {                                                                        \
-    if (req == NULL)                                                          \
-      return UV_EINVAL;                                                       \
-    uv_fs_req_init(loop, req, subtype, cb);                                   \
-  }                                                                           \
-  while (0)
-
-#define POST                                                                  \
-  do {                                                                        \
-    if (cb != NULL) {                                                         \
-      uv__req_register(loop, req);                                            \
-      uv__work_submit(loop,                                                   \
-                      &req->work_req,                                         \
-                      UV__WORK_FAST_IO,                                       \
-                      uv__fs_work,                                            \
-                      uv__fs_done);                                           \
-      return 0;                                                               \
-    } else {                                                                  \
-      uv__fs_work(&req->work_req);                                            \
-      return req->result;                                                     \
-    }                                                                         \
-  }                                                                           \
-  while (0)
-
-#define SET_REQ_RESULT(req, result_value)                                   \
-  do {                                                                      \
-    req->result = (result_value);                                           \
-    if (req->result == -1) {                                                \
-      req->sys_errno_ = _doserrno;                                          \
-      req->result = uv_translate_sys_error(req->sys_errno_);                \
-    }                                                                       \
-  } while (0)
-
-#define SET_REQ_WIN32_ERROR(req, sys_errno)                                 \
-  do {                                                                      \
-    req->sys_errno_ = (sys_errno);                                          \
-    req->result = uv_translate_sys_error(req->sys_errno_);                  \
-  } while (0)
-
-#define SET_REQ_UV_ERROR(req, uv_errno, sys_errno)                          \
-  do {                                                                      \
-    req->result = (uv_errno);                                               \
-    req->sys_errno_ = (sys_errno);                                          \
-  } while (0)
-
-#define VERIFY_FD(fd, req)                                                  \
-  if (fd == -1) {                                                           \
-    req->result = UV_EBADF;                                                 \
-    req->sys_errno_ = ERROR_INVALID_HANDLE;                                 \
-    return;                                                                 \
-  }
-
-#define MILLIONu (1000U * 1000U)
-#define BILLIONu (1000U * 1000U * 1000U)
-
-#define FILETIME_TO_UINT(filetime)                                          \
-   (*((uint64_t*) &(filetime)) - (uint64_t) 116444736 * BILLIONu)
-
-#define FILETIME_TO_TIME_T(filetime)                                        \
-   (FILETIME_TO_UINT(filetime) / (10u * MILLIONu))
-
-#define FILETIME_TO_TIME_NS(filetime, secs)                                 \
-   ((FILETIME_TO_UINT(filetime) - (secs * (uint64_t) 10 * MILLIONu)) * 100U)
-
-#define FILETIME_TO_TIMESPEC(ts, filetime)                                  \
-   do {                                                                     \
-     (ts).tv_sec = (long) FILETIME_TO_TIME_T(filetime);                     \
-     (ts).tv_nsec = (long) FILETIME_TO_TIME_NS(filetime, (ts).tv_sec);      \
-   } while(0)
-
-#define TIME_T_TO_FILETIME(time, filetime_ptr)                              \
-  do {                                                                      \
-    uint64_t bigtime = ((uint64_t) ((time) * (uint64_t) 10 * MILLIONu)) +   \
-                       (uint64_t) 116444736 * BILLIONu;                     \
-    (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF;                   \
-    (filetime_ptr)->dwHighDateTime = bigtime >> 32;                         \
-  } while(0)
-
-#define IS_SLASH(c) ((c) == L'\\' || (c) == L'/')
-#define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \
-  ((c) >= L'A' && (c) <= L'Z'))
-
-const WCHAR JUNCTION_PREFIX[] = L"\\??\\";
-const WCHAR JUNCTION_PREFIX_LEN = 4;
-
-const WCHAR LONG_PATH_PREFIX[] = L"\\\\?\\";
-const WCHAR LONG_PATH_PREFIX_LEN = 4;
-
-const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
-const WCHAR UNC_PATH_PREFIX_LEN = 8;
-
-static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
-
-void uv_fs_init(void) {
-  _fmode = _O_BINARY;
-}
-
-
-INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
-    const char* new_path, const int copy_path) {
-  char* buf;
-  char* pos;
-  ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0;
-
-  /* new_path can only be set if path is also set. */
-  assert(new_path == NULL || path != NULL);
-
-  if (path != NULL) {
-    pathw_len = MultiByteToWideChar(CP_UTF8,
-                                    0,
-                                    path,
-                                    -1,
-                                    NULL,
-                                    0);
-    if (pathw_len == 0) {
-      return GetLastError();
-    }
-
-    buf_sz += pathw_len * sizeof(WCHAR);
-  }
-
-  if (path != NULL && copy_path) {
-    path_len = 1 + strlen(path);
-    buf_sz += path_len;
-  }
-
-  if (new_path != NULL) {
-    new_pathw_len = MultiByteToWideChar(CP_UTF8,
-                                        0,
-                                        new_path,
-                                        -1,
-                                        NULL,
-                                        0);
-    if (new_pathw_len == 0) {
-      return GetLastError();
-    }
-
-    buf_sz += new_pathw_len * sizeof(WCHAR);
-  }
-
-
-  if (buf_sz == 0) {
-    req->file.pathw = NULL;
-    req->fs.info.new_pathw = NULL;
-    req->path = NULL;
-    return 0;
-  }
-
-  buf = (char*) uv__malloc(buf_sz);
-  if (buf == NULL) {
-    return ERROR_OUTOFMEMORY;
-  }
-
-  pos = buf;
-
-  if (path != NULL) {
-    DWORD r = MultiByteToWideChar(CP_UTF8,
-                                  0,
-                                  path,
-                                  -1,
-                                  (WCHAR*) pos,
-                                  pathw_len);
-    assert(r == (DWORD) pathw_len);
-    req->file.pathw = (WCHAR*) pos;
-    pos += r * sizeof(WCHAR);
-  } else {
-    req->file.pathw = NULL;
-  }
-
-  if (new_path != NULL) {
-    DWORD r = MultiByteToWideChar(CP_UTF8,
-                                  0,
-                                  new_path,
-                                  -1,
-                                  (WCHAR*) pos,
-                                  new_pathw_len);
-    assert(r == (DWORD) new_pathw_len);
-    req->fs.info.new_pathw = (WCHAR*) pos;
-    pos += r * sizeof(WCHAR);
-  } else {
-    req->fs.info.new_pathw = NULL;
-  }
-
-  req->path = path;
-  if (path != NULL && copy_path) {
-    memcpy(pos, path, path_len);
-    assert(path_len == buf_sz - (pos - buf));
-    req->path = pos;
-  }
-
-  req->flags |= UV_FS_FREE_PATHS;
-
-  return 0;
-}
-
-
-
-INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
-    uv_fs_type fs_type, const uv_fs_cb cb) {
-  uv__once_init();
-  UV_REQ_INIT(req, UV_FS);
-  req->loop = loop;
-  req->flags = 0;
-  req->fs_type = fs_type;
-  req->result = 0;
-  req->ptr = NULL;
-  req->path = NULL;
-  req->cb = cb;
-  memset(&req->fs, 0, sizeof(req->fs));
-}
-
-
-static int fs__wide_to_utf8(WCHAR* w_source_ptr,
-                               DWORD w_source_len,
-                               char** target_ptr,
-                               uint64_t* target_len_ptr) {
-  int r;
-  int target_len;
-  char* target;
-  target_len = WideCharToMultiByte(CP_UTF8,
-                                   0,
-                                   w_source_ptr,
-                                   w_source_len,
-                                   NULL,
-                                   0,
-                                   NULL,
-                                   NULL);
-
-  if (target_len == 0) {
-    return -1;
-  }
-
-  if (target_len_ptr != NULL) {
-    *target_len_ptr = target_len;
-  }
-
-  if (target_ptr == NULL) {
-    return 0;
-  }
-
-  target = (char*)uv__malloc(target_len + 1);
-  if (target == NULL) {
-    SetLastError(ERROR_OUTOFMEMORY);
-    return -1;
-  }
-
-  r = WideCharToMultiByte(CP_UTF8,
-                          0,
-                          w_source_ptr,
-                          w_source_len,
-                          target,
-                          target_len,
-                          NULL,
-                          NULL);
-  assert(r == target_len);
-  target[target_len] = '\0';
-  *target_ptr = target;
-  return 0;
-}
-
-
-INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
-    uint64_t* target_len_ptr) {
-  char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
-  REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
-  WCHAR* w_target;
-  DWORD w_target_len;
-  DWORD bytes;
-
-  if (!DeviceIoControl(handle,
-                       FSCTL_GET_REPARSE_POINT,
-                       NULL,
-                       0,
-                       buffer,
-                       sizeof buffer,
-                       &bytes,
-                       NULL)) {
-    return -1;
-  }
-
-  if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
-    /* Real symlink */
-    w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
-        (reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
-        sizeof(WCHAR));
-    w_target_len =
-        reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
-        sizeof(WCHAR);
-
-    /* Real symlinks can contain pretty much everything, but the only thing we
-     * really care about is undoing the implicit conversion to an NT namespaced
-     * path that CreateSymbolicLink will perform on absolute paths. If the path
-     * is win32-namespaced then the user must have explicitly made it so, and
-     * we better just return the unmodified reparse data. */
-    if (w_target_len >= 4 &&
-        w_target[0] == L'\\' &&
-        w_target[1] == L'?' &&
-        w_target[2] == L'?' &&
-        w_target[3] == L'\\') {
-      /* Starts with \??\ */
-      if (w_target_len >= 6 &&
-          ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
-           (w_target[4] >= L'a' && w_target[4] <= L'z')) &&
-          w_target[5] == L':' &&
-          (w_target_len == 6 || w_target[6] == L'\\')) {
-        /* \??\<drive>:\ */
-        w_target += 4;
-        w_target_len -= 4;
-
-      } else if (w_target_len >= 8 &&
-                 (w_target[4] == L'U' || w_target[4] == L'u') &&
-                 (w_target[5] == L'N' || w_target[5] == L'n') &&
-                 (w_target[6] == L'C' || w_target[6] == L'c') &&
-                 w_target[7] == L'\\') {
-        /* \??\UNC\<server>\<share>\ - make sure the final path looks like
-         * \\<server>\<share>\ */
-        w_target += 6;
-        w_target[0] = L'\\';
-        w_target_len -= 6;
-      }
-    }
-
-  } else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
-    /* Junction. */
-    w_target = reparse_data->MountPointReparseBuffer.PathBuffer +
-        (reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
-        sizeof(WCHAR));
-    w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
-        sizeof(WCHAR);
-
-    /* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions
-     * can also be used as mount points, like \??\Volume{<guid>}, but that's
-     * confusing for programs since they wouldn't be able to actually
-     * understand such a path when returned by uv_readlink(). UNC paths are
-     * never valid for junctions so we don't care about them. */
-    if (!(w_target_len >= 6 &&
-          w_target[0] == L'\\' &&
-          w_target[1] == L'?' &&
-          w_target[2] == L'?' &&
-          w_target[3] == L'\\' &&
-          ((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
-           (w_target[4] >= L'a' && w_target[4] <= L'z')) &&
-          w_target[5] == L':' &&
-          (w_target_len == 6 || w_target[6] == L'\\'))) {
-      SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
-      return -1;
-    }
-
-    /* Remove leading \??\ */
-    w_target += 4;
-    w_target_len -= 4;
-
-  } else {
-    /* Reparse tag does not indicate a symlink. */
-    SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
-    return -1;
-  }
-
-  return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);
-}
-
-
-void fs__open(uv_fs_t* req) {
-  DWORD access;
-  DWORD share;
-  DWORD disposition;
-  DWORD attributes = 0;
-  HANDLE file;
-  int fd, current_umask;
-  int flags = req->fs.info.file_flags;
-
-  /* Obtain the active umask. umask() never fails and returns the previous
-   * umask. */
-  current_umask = umask(0);
-  umask(current_umask);
-
-  /* convert flags and mode to CreateFile parameters */
-  switch (flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) {
-  case UV_FS_O_RDONLY:
-    access = FILE_GENERIC_READ;
-    break;
-  case UV_FS_O_WRONLY:
-    access = FILE_GENERIC_WRITE;
-    break;
-  case UV_FS_O_RDWR:
-    access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
-    break;
-  default:
-    goto einval;
-  }
-
-  if (flags & UV_FS_O_APPEND) {
-    access &= ~FILE_WRITE_DATA;
-    access |= FILE_APPEND_DATA;
-  }
-
-  /*
-   * Here is where we deviate significantly from what CRT's _open()
-   * does. We indiscriminately use all the sharing modes, to match
-   * UNIX semantics. In particular, this ensures that the file can
-   * be deleted even whilst it's open, fixing issue #1449.
-   * We still support exclusive sharing mode, since it is necessary
-   * for opening raw block devices, otherwise Windows will prevent
-   * any attempt to write past the master boot record.
-   */
-  if (flags & UV_FS_O_EXLOCK) {
-    share = 0;
-  } else {
-    share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
-  }
-
-  switch (flags & (UV_FS_O_CREAT | UV_FS_O_EXCL | UV_FS_O_TRUNC)) {
-  case 0:
-  case UV_FS_O_EXCL:
-    disposition = OPEN_EXISTING;
-    break;
-  case UV_FS_O_CREAT:
-    disposition = OPEN_ALWAYS;
-    break;
-  case UV_FS_O_CREAT | UV_FS_O_EXCL:
-  case UV_FS_O_CREAT | UV_FS_O_TRUNC | UV_FS_O_EXCL:
-    disposition = CREATE_NEW;
-    break;
-  case UV_FS_O_TRUNC:
-  case UV_FS_O_TRUNC | UV_FS_O_EXCL:
-    disposition = TRUNCATE_EXISTING;
-    break;
-  case UV_FS_O_CREAT | UV_FS_O_TRUNC:
-    disposition = CREATE_ALWAYS;
-    break;
-  default:
-    goto einval;
-  }
-
-  attributes |= FILE_ATTRIBUTE_NORMAL;
-  if (flags & UV_FS_O_CREAT) {
-    if (!((req->fs.info.mode & ~current_umask) & _S_IWRITE)) {
-      attributes |= FILE_ATTRIBUTE_READONLY;
-    }
-  }
-
-  if (flags & UV_FS_O_TEMPORARY ) {
-    attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
-    access |= DELETE;
-  }
-
-  if (flags & UV_FS_O_SHORT_LIVED) {
-    attributes |= FILE_ATTRIBUTE_TEMPORARY;
-  }
-
-  switch (flags & (UV_FS_O_SEQUENTIAL | UV_FS_O_RANDOM)) {
-  case 0:
-    break;
-  case UV_FS_O_SEQUENTIAL:
-    attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
-    break;
-  case UV_FS_O_RANDOM:
-    attributes |= FILE_FLAG_RANDOM_ACCESS;
-    break;
-  default:
-    goto einval;
-  }
-
-  if (flags & UV_FS_O_DIRECT) {
-    /*
-     * FILE_APPEND_DATA and FILE_FLAG_NO_BUFFERING are mutually exclusive.
-     * Windows returns 87, ERROR_INVALID_PARAMETER if these are combined.
-     *
-     * FILE_APPEND_DATA is included in FILE_GENERIC_WRITE:
-     *
-     * FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE |
-     *                      FILE_WRITE_DATA |
-     *                      FILE_WRITE_ATTRIBUTES |
-     *                      FILE_WRITE_EA |
-     *                      FILE_APPEND_DATA |
-     *                      SYNCHRONIZE
-     *
-     * Note: Appends are also permitted by FILE_WRITE_DATA.
-     *
-     * In order for direct writes and direct appends to succeed, we therefore
-     * exclude FILE_APPEND_DATA if FILE_WRITE_DATA is specified, and otherwise
-     * fail if the user's sole permission is a direct append, since this
-     * particular combination is invalid.
-     */
-    if (access & FILE_APPEND_DATA) {
-      if (access & FILE_WRITE_DATA) {
-        access &= ~FILE_APPEND_DATA;
-      } else {
-        goto einval;
-      }
-    }
-    attributes |= FILE_FLAG_NO_BUFFERING;
-  }
-
-  switch (flags & (UV_FS_O_DSYNC | UV_FS_O_SYNC)) {
-  case 0:
-    break;
-  case UV_FS_O_DSYNC:
-  case UV_FS_O_SYNC:
-    attributes |= FILE_FLAG_WRITE_THROUGH;
-    break;
-  default:
-    goto einval;
-  }
-
-  /* Setting this flag makes it possible to open a directory. */
-  attributes |= FILE_FLAG_BACKUP_SEMANTICS;
-
-  file = CreateFileW(req->file.pathw,
-                     access,
-                     share,
-                     NULL,
-                     disposition,
-                     attributes,
-                     NULL);
-  if (file == INVALID_HANDLE_VALUE) {
-    DWORD error = GetLastError();
-    if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
-        !(flags & UV_FS_O_EXCL)) {
-      /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was
-       * specified, it means the path referred to a directory. */
-      SET_REQ_UV_ERROR(req, UV_EISDIR, error);
-    } else {
-      SET_REQ_WIN32_ERROR(req, GetLastError());
-    }
-    return;
-  }
-
-  fd = _open_osfhandle((intptr_t) file, flags);
-  if (fd < 0) {
-    /* The only known failure mode for _open_osfhandle() is EMFILE, in which
-     * case GetLastError() will return zero. However we'll try to handle other
-     * errors as well, should they ever occur.
-     */
-    if (errno == EMFILE)
-      SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES);
-    else if (GetLastError() != ERROR_SUCCESS)
-      SET_REQ_WIN32_ERROR(req, GetLastError());
-    else
-      SET_REQ_WIN32_ERROR(req, UV_UNKNOWN);
-    CloseHandle(file);
-    return;
-  }
-
-  SET_REQ_RESULT(req, fd);
-  return;
-
- einval:
-  SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
-}
-
-void fs__close(uv_fs_t* req) {
-  int fd = req->file.fd;
-  int result;
-
-  VERIFY_FD(fd, req);
-
-  if (fd > 2)
-    result = _close(fd);
-  else
-    result = 0;
-
-  /* _close doesn't set _doserrno on failure, but it does always set errno
-   * to EBADF on failure.
-   */
-  if (result == -1) {
-    assert(errno == EBADF);
-    SET_REQ_UV_ERROR(req, UV_EBADF, ERROR_INVALID_HANDLE);
-  } else {
-    req->result = 0;
-  }
-}
-
-
-void fs__read(uv_fs_t* req) {
-  int fd = req->file.fd;
-  int64_t offset = req->fs.info.offset;
-  HANDLE handle;
-  OVERLAPPED overlapped, *overlapped_ptr;
-  LARGE_INTEGER offset_;
-  DWORD bytes;
-  DWORD error;
-  int result;
-  unsigned int index;
-  LARGE_INTEGER original_position;
-  LARGE_INTEGER zero_offset;
-  int restore_position;
-
-  VERIFY_FD(fd, req);
-
-  zero_offset.QuadPart = 0;
-  restore_position = 0;
-  handle = uv__get_osfhandle(fd);
-
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
-    return;
-  }
-
-  if (offset != -1) {
-    memset(&overlapped, 0, sizeof overlapped);
-    overlapped_ptr = &overlapped;
-    if (SetFilePointerEx(handle, zero_offset, &original_position,
-                         FILE_CURRENT)) {
-      restore_position = 1;
-    }
-  } else {
-    overlapped_ptr = NULL;
-  }
-
-  index = 0;
-  bytes = 0;
-  do {
-    DWORD incremental_bytes;
-
-    if (offset != -1) {
-      offset_.QuadPart = offset + bytes;
-      overlapped.Offset = offset_.LowPart;
-      overlapped.OffsetHigh = offset_.HighPart;
-    }
-
-    result = ReadFile(handle,
-                      req->fs.info.bufs[index].base,
-                      req->fs.info.bufs[index].len,
-                      &incremental_bytes,
-                      overlapped_ptr);
-    bytes += incremental_bytes;
-    ++index;
-  } while (result && index < req->fs.info.nbufs);
-
-  if (restore_position)
-    SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
-
-  if (result || bytes > 0) {
-    SET_REQ_RESULT(req, bytes);
-  } else {
-    error = GetLastError();
-    if (error == ERROR_HANDLE_EOF) {
-      SET_REQ_RESULT(req, bytes);
-    } else {
-      SET_REQ_WIN32_ERROR(req, error);
-    }
-  }
-}
-
-
-void fs__write(uv_fs_t* req) {
-  int fd = req->file.fd;
-  int64_t offset = req->fs.info.offset;
-  HANDLE handle;
-  OVERLAPPED overlapped, *overlapped_ptr;
-  LARGE_INTEGER offset_;
-  DWORD bytes;
-  int result;
-  unsigned int index;
-  LARGE_INTEGER original_position;
-  LARGE_INTEGER zero_offset;
-  int restore_position;
-
-  VERIFY_FD(fd, req);
-
-  zero_offset.QuadPart = 0;
-  restore_position = 0;
-  handle = uv__get_osfhandle(fd);
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
-    return;
-  }
-
-  if (offset != -1) {
-    memset(&overlapped, 0, sizeof overlapped);
-    overlapped_ptr = &overlapped;
-    if (SetFilePointerEx(handle, zero_offset, &original_position,
-                         FILE_CURRENT)) {
-      restore_position = 1;
-    }
-  } else {
-    overlapped_ptr = NULL;
-  }
-
-  index = 0;
-  bytes = 0;
-  do {
-    DWORD incremental_bytes;
-
-    if (offset != -1) {
-      offset_.QuadPart = offset + bytes;
-      overlapped.Offset = offset_.LowPart;
-      overlapped.OffsetHigh = offset_.HighPart;
-    }
-
-    result = WriteFile(handle,
-                       req->fs.info.bufs[index].base,
-                       req->fs.info.bufs[index].len,
-                       &incremental_bytes,
-                       overlapped_ptr);
-    bytes += incremental_bytes;
-    ++index;
-  } while (result && index < req->fs.info.nbufs);
-
-  if (restore_position)
-    SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
-
-  if (result || bytes > 0) {
-    SET_REQ_RESULT(req, bytes);
-  } else {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-  }
-}
-
-
-void fs__rmdir(uv_fs_t* req) {
-  int result = _wrmdir(req->file.pathw);
-  SET_REQ_RESULT(req, result);
-}
-
-
-void fs__unlink(uv_fs_t* req) {
-  const WCHAR* pathw = req->file.pathw;
-  HANDLE handle;
-  BY_HANDLE_FILE_INFORMATION info;
-  FILE_DISPOSITION_INFORMATION disposition;
-  IO_STATUS_BLOCK iosb;
-  NTSTATUS status;
-
-  handle = CreateFileW(pathw,
-                       FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE,
-                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                       NULL,
-                       OPEN_EXISTING,
-                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
-                       NULL);
-
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  if (!GetFileInformationByHandle(handle, &info)) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    CloseHandle(handle);
-    return;
-  }
-
-  if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-    /* Do not allow deletion of directories, unless it is a symlink. When the
-     * path refers to a non-symlink directory, report EPERM as mandated by
-     * POSIX.1. */
-
-    /* Check if it is a reparse point. If it's not, it's a normal directory. */
-    if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
-      SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
-      CloseHandle(handle);
-      return;
-    }
-
-    /* Read the reparse point and check if it is a valid symlink. If not, don't
-     * unlink. */
-    if (fs__readlink_handle(handle, NULL, NULL) < 0) {
-      DWORD error = GetLastError();
-      if (error == ERROR_SYMLINK_NOT_SUPPORTED)
-        error = ERROR_ACCESS_DENIED;
-      SET_REQ_WIN32_ERROR(req, error);
-      CloseHandle(handle);
-      return;
-    }
-  }
-
-  if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
-    /* Remove read-only attribute */
-    FILE_BASIC_INFORMATION basic = { 0 };
-
-    basic.FileAttributes = (info.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY) |
-                           FILE_ATTRIBUTE_ARCHIVE;
-
-    status = pNtSetInformationFile(handle,
-                                   &iosb,
-                                   &basic,
-                                   sizeof basic,
-                                   FileBasicInformation);
-    if (!NT_SUCCESS(status)) {
-      SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
-      CloseHandle(handle);
-      return;
-    }
-  }
-
-  /* Try to set the delete flag. */
-  disposition.DeleteFile = TRUE;
-  status = pNtSetInformationFile(handle,
-                                 &iosb,
-                                 &disposition,
-                                 sizeof disposition,
-                                 FileDispositionInformation);
-  if (NT_SUCCESS(status)) {
-    SET_REQ_SUCCESS(req);
-  } else {
-    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
-  }
-
-  CloseHandle(handle);
-}
-
-
-void fs__mkdir(uv_fs_t* req) {
-  /* TODO: use req->mode. */
-  int result = _wmkdir(req->file.pathw);
-  SET_REQ_RESULT(req, result);
-}
-
-
-/* OpenBSD original: lib/libc/stdio/mktemp.c */
-void fs__mkdtemp(uv_fs_t* req) {
-  static const WCHAR *tempchars =
-    L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-  static const size_t num_chars = 62;
-  static const size_t num_x = 6;
-  WCHAR *cp, *ep;
-  unsigned int tries, i;
-  size_t len;
-  HCRYPTPROV h_crypt_prov;
-  uint64_t v;
-  BOOL released;
-
-  len = wcslen(req->file.pathw);
-  ep = req->file.pathw + len;
-  if (len < num_x || wcsncmp(ep - num_x, L"XXXXXX", num_x)) {
-    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER);
-    return;
-  }
-
-  if (!CryptAcquireContext(&h_crypt_prov, NULL, NULL, PROV_RSA_FULL,
-                           CRYPT_VERIFYCONTEXT)) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  tries = TMP_MAX;
-  do {
-    if (!CryptGenRandom(h_crypt_prov, sizeof(v), (BYTE*) &v)) {
-      SET_REQ_WIN32_ERROR(req, GetLastError());
-      break;
-    }
-
-    cp = ep - num_x;
-    for (i = 0; i < num_x; i++) {
-      *cp++ = tempchars[v % num_chars];
-      v /= num_chars;
-    }
-
-    if (_wmkdir(req->file.pathw) == 0) {
-      len = strlen(req->path);
-      wcstombs((char*) req->path + len - num_x, ep - num_x, num_x);
-      SET_REQ_RESULT(req, 0);
-      break;
-    } else if (errno != EEXIST) {
-      SET_REQ_RESULT(req, -1);
-      break;
-    }
-  } while (--tries);
-
-  released = CryptReleaseContext(h_crypt_prov, 0);
-  assert(released);
-  if (tries == 0) {
-    SET_REQ_RESULT(req, -1);
-  }
-}
-
-
-void fs__scandir(uv_fs_t* req) {
-  static const size_t dirents_initial_size = 32;
-
-  HANDLE dir_handle = INVALID_HANDLE_VALUE;
-
-  uv__dirent_t** dirents = NULL;
-  size_t dirents_size = 0;
-  size_t dirents_used = 0;
-
-  IO_STATUS_BLOCK iosb;
-  NTSTATUS status;
-
-  /* Buffer to hold directory entries returned by NtQueryDirectoryFile.
-   * It's important that this buffer can hold at least one entry, regardless
-   * of the length of the file names present in the enumerated directory.
-   * A file name is at most 256 WCHARs long.
-   * According to MSDN, the buffer must be aligned at an 8-byte boundary.
-   */
-#if _MSC_VER
-  __declspec(align(8)) char buffer[8192];
-#else
-  __attribute__ ((aligned (8))) char buffer[8192];
-#endif
-
-  STATIC_ASSERT(sizeof buffer >=
-                sizeof(FILE_DIRECTORY_INFORMATION) + 256 * sizeof(WCHAR));
-
-  /* Open the directory. */
-  dir_handle =
-      CreateFileW(req->file.pathw,
-                  FILE_LIST_DIRECTORY | SYNCHRONIZE,
-                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                  NULL,
-                  OPEN_EXISTING,
-                  FILE_FLAG_BACKUP_SEMANTICS,
-                  NULL);
-  if (dir_handle == INVALID_HANDLE_VALUE)
-    goto win32_error;
-
-  /* Read the first chunk. */
-  status = pNtQueryDirectoryFile(dir_handle,
-                                 NULL,
-                                 NULL,
-                                 NULL,
-                                 &iosb,
-                                 &buffer,
-                                 sizeof buffer,
-                                 FileDirectoryInformation,
-                                 FALSE,
-                                 NULL,
-                                 TRUE);
-
-  /* If the handle is not a directory, we'll get STATUS_INVALID_PARAMETER.
-   * This should be reported back as UV_ENOTDIR.
-   */
-  if (status == STATUS_INVALID_PARAMETER)
-    goto not_a_directory_error;
-
-  while (NT_SUCCESS(status)) {
-    char* position = buffer;
-    size_t next_entry_offset = 0;
-
-    do {
-      FILE_DIRECTORY_INFORMATION* info;
-      uv__dirent_t* dirent;
-
-      size_t wchar_len;
-      size_t utf8_len;
-
-      /* Obtain a pointer to the current directory entry. */
-      position += next_entry_offset;
-      info = (FILE_DIRECTORY_INFORMATION*) position;
-
-      /* Fetch the offset to the next directory entry. */
-      next_entry_offset = info->NextEntryOffset;
-
-      /* Compute the length of the filename in WCHARs. */
-      wchar_len = info->FileNameLength / sizeof info->FileName[0];
-
-      /* Skip over '.' and '..' entries.  It has been reported that
-       * the SharePoint driver includes the terminating zero byte in
-       * the filename length.  Strip those first.
-       */
-      while (wchar_len > 0 && info->FileName[wchar_len - 1] == L'\0')
-        wchar_len -= 1;
-
-      if (wchar_len == 0)
-        continue;
-      if (wchar_len == 1 && info->FileName[0] == L'.')
-        continue;
-      if (wchar_len == 2 && info->FileName[0] == L'.' &&
-          info->FileName[1] == L'.')
-        continue;
-
-      /* Compute the space required to store the filename as UTF-8. */
-      utf8_len = WideCharToMultiByte(
-          CP_UTF8, 0, &info->FileName[0], wchar_len, NULL, 0, NULL, NULL);
-      if (utf8_len == 0)
-        goto win32_error;
-
-      /* Resize the dirent array if needed. */
-      if (dirents_used >= dirents_size) {
-        size_t new_dirents_size =
-            dirents_size == 0 ? dirents_initial_size : dirents_size << 1;
-        uv__dirent_t** new_dirents = (uv__dirent_t**)
-            uv__realloc(dirents, new_dirents_size * sizeof *dirents);
-
-        if (new_dirents == NULL)
-          goto out_of_memory_error;
-
-        dirents_size = new_dirents_size;
-        dirents = new_dirents;
-      }
-
-      /* Allocate space for the uv dirent structure. The dirent structure
-       * includes room for the first character of the filename, but `utf8_len`
-       * doesn't count the NULL terminator at this point.
-       */
-      dirent = (uv__dirent_t*)uv__malloc(sizeof *dirent + utf8_len);
-      if (dirent == NULL)
-        goto out_of_memory_error;
-
-      dirents[dirents_used++] = dirent;
-
-      /* Convert file name to UTF-8. */
-      if (WideCharToMultiByte(CP_UTF8,
-                              0,
-                              &info->FileName[0],
-                              wchar_len,
-                              &dirent->d_name[0],
-                              utf8_len,
-                              NULL,
-                              NULL) == 0)
-        goto win32_error;
-
-      /* Add a null terminator to the filename. */
-      dirent->d_name[utf8_len] = '\0';
-
-      /* Fill out the type field. */
-      if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE)
-        dirent->d_type = UV__DT_CHAR;
-      else if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
-        dirent->d_type = UV__DT_LINK;
-      else if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-        dirent->d_type = UV__DT_DIR;
-      else
-        dirent->d_type = UV__DT_FILE;
-    } while (next_entry_offset != 0);
-
-    /* Read the next chunk. */
-    status = pNtQueryDirectoryFile(dir_handle,
-                                   NULL,
-                                   NULL,
-                                   NULL,
-                                   &iosb,
-                                   &buffer,
-                                   sizeof buffer,
-                                   FileDirectoryInformation,
-                                   FALSE,
-                                   NULL,
-                                   FALSE);
-
-    /* After the first pNtQueryDirectoryFile call, the function may return
-     * STATUS_SUCCESS even if the buffer was too small to hold at least one
-     * directory entry.
-     */
-    if (status == STATUS_SUCCESS && iosb.Information == 0)
-      status = STATUS_BUFFER_OVERFLOW;
-  }
-
-  if (status != STATUS_NO_MORE_FILES)
-    goto nt_error;
-
-  CloseHandle(dir_handle);
-
-  /* Store the result in the request object. */
-  req->ptr = dirents;
-  if (dirents != NULL)
-    req->flags |= UV_FS_FREE_PTR;
-
-  SET_REQ_RESULT(req, dirents_used);
-
-  /* `nbufs` will be used as index by uv_fs_scandir_next. */
-  req->fs.info.nbufs = 0;
-
-  return;
-
-nt_error:
-  SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
-  goto cleanup;
-
-win32_error:
-  SET_REQ_WIN32_ERROR(req, GetLastError());
-  goto cleanup;
-
-not_a_directory_error:
-  SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
-  goto cleanup;
-
-out_of_memory_error:
-  SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
-  goto cleanup;
-
-cleanup:
-  if (dir_handle != INVALID_HANDLE_VALUE)
-    CloseHandle(dir_handle);
-  while (dirents_used > 0)
-    uv__free(dirents[--dirents_used]);
-  if (dirents != NULL)
-    uv__free(dirents);
-}
-
-void fs__opendir(uv_fs_t* req) {
-  WCHAR* pathw;
-  size_t len;
-  const WCHAR* fmt;
-  WCHAR* find_path;
-  uv_dir_t* dir;
-
-  pathw = req->file.pathw;
-  dir = NULL;
-  find_path = NULL;
-
-  /* Figure out whether path is a file or a directory. */
-  if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) {
-    SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY);
-    goto error;
-  }
-
-  dir = (uv_dir_t*)uv__malloc(sizeof(*dir));
-  if (dir == NULL) {
-    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
-    goto error;
-  }
-
-  len = wcslen(pathw);
-
-  if (len == 0)
-    fmt = L"./*";
-  else if (IS_SLASH(pathw[len - 1]))
-    fmt = L"%s*";
-  else
-    fmt = L"%s\\*";
-
-  find_path = (WCHAR*)uv__malloc(sizeof(WCHAR) * (len + 4));
-  if (find_path == NULL) {
-    SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
-    goto error;
-  }
-
-  _snwprintf(find_path, len + 3, fmt, pathw);
-  dir->dir_handle = FindFirstFileW(find_path, &dir->find_data);
-  uv__free(find_path);
-  find_path = NULL;
-  if (dir->dir_handle == INVALID_HANDLE_VALUE &&
-      GetLastError() != ERROR_FILE_NOT_FOUND) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    goto error;
-  }
-
-  dir->need_find_call = FALSE;
-  req->ptr = dir;
-  SET_REQ_RESULT(req, 0);
-  return;
-
-error:
-  uv__free(dir);
-  uv__free(find_path);
-  req->ptr = NULL;
-}
-
-void fs__readdir(uv_fs_t* req) {
-  uv_dir_t* dir;
-  uv_dirent_t* dirents;
-  uv__dirent_t dent;
-  unsigned int dirent_idx;
-  PWIN32_FIND_DATAW find_data;
-  unsigned int i;
-  int r;
-
-  req->flags |= UV_FS_FREE_PTR;
-  dir = (uv_dir_t*)req->ptr;
-  dirents = dir->dirents;
-  memset(dirents, 0, dir->nentries * sizeof(*dir->dirents));
-  find_data = &dir->find_data;
-  dirent_idx = 0;
-
-  while (dirent_idx < dir->nentries) {
-    if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) {
-      if (GetLastError() == ERROR_NO_MORE_FILES)
-        break;
-      goto error;
-    }
-
-    /* Skip "." and ".." entries. */
-    if (find_data->cFileName[0] == L'.' &&
-        (find_data->cFileName[1] == L'\0' ||
-        (find_data->cFileName[1] == L'.' &&
-        find_data->cFileName[2] == L'\0'))) {
-      dir->need_find_call = TRUE;
-      continue;
-    }
-
-    r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName,
-                                  -1,
-                                  (char**) &dirents[dirent_idx].name);
-    if (r != 0)
-      goto error;
-
-    /* Copy file type. */
-    if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
-      dent.d_type = UV__DT_DIR;
-    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0)
-      dent.d_type = UV__DT_LINK;
-    else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0)
-      dent.d_type = UV__DT_CHAR;
-    else
-      dent.d_type = UV__DT_FILE;
-
-    dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent);
-    dir->need_find_call = TRUE;
-    ++dirent_idx;
-  }
-
-  SET_REQ_RESULT(req, dirent_idx);
-  return;
-
-error:
-  SET_REQ_WIN32_ERROR(req, GetLastError());
-  for (i = 0; i < dirent_idx; ++i) {
-    uv__free((char*) dirents[i].name);
-    dirents[i].name = NULL;
-  }
-}
-
-void fs__closedir(uv_fs_t* req) {
-  uv_dir_t* dir;
-
-  dir = (uv_dir_t*)req->ptr;
-  FindClose(dir->dir_handle);
-  uv__free(req->ptr);
-  SET_REQ_RESULT(req, 0);
-}
-
-INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
-    int do_lstat) {
-  FILE_ALL_INFORMATION file_info;
-  FILE_FS_VOLUME_INFORMATION volume_info;
-  NTSTATUS nt_status;
-  IO_STATUS_BLOCK io_status;
-
-  nt_status = pNtQueryInformationFile(handle,
-                                      &io_status,
-                                      &file_info,
-                                      sizeof file_info,
-                                      FileAllInformation);
-
-  /* Buffer overflow (a warning status code) is expected here. */
-  if (NT_ERROR(nt_status)) {
-    SetLastError(pRtlNtStatusToDosError(nt_status));
-    return -1;
-  }
-
-  nt_status = pNtQueryVolumeInformationFile(handle,
-                                            &io_status,
-                                            &volume_info,
-                                            sizeof volume_info,
-                                            FileFsVolumeInformation);
-
-  /* Buffer overflow (a warning status code) is expected here. */
-  if (io_status.Status == STATUS_NOT_IMPLEMENTED) {
-    statbuf->st_dev = 0;
-  } else if (NT_ERROR(nt_status)) {
-    SetLastError(pRtlNtStatusToDosError(nt_status));
-    return -1;
-  } else {
-    statbuf->st_dev = volume_info.VolumeSerialNumber;
-  }
-
-  /* Todo: st_mode should probably always be 0666 for everyone. We might also
-   * want to report 0777 if the file is a .exe or a directory.
-   *
-   * Currently it's based on whether the 'readonly' attribute is set, which
-   * makes little sense because the semantics are so different: the 'read-only'
-   * flag is just a way for a user to protect against accidental deletion, and
-   * serves no security purpose. Windows uses ACLs for that.
-   *
-   * Also people now use uv_fs_chmod() to take away the writable bit for good
-   * reasons. Windows however just makes the file read-only, which makes it
-   * impossible to delete the file afterwards, since read-only files can't be
-   * deleted.
-   *
-   * IOW it's all just a clusterfuck and we should think of something that
-   * makes slightly more sense.
-   *
-   * And uv_fs_chmod should probably just fail on windows or be a total no-op.
-   * There's nothing sensible it can do anyway.
-   */
-  statbuf->st_mode = 0;
-
-  /*
-  * On Windows, FILE_ATTRIBUTE_REPARSE_POINT is a general purpose mechanism
-  * by which filesystem drivers can intercept and alter file system requests.
-  *
-  * The only reparse points we care about are symlinks and mount points, both
-  * of which are treated as POSIX symlinks. Further, we only care when
-  * invoked via lstat, which seeks information about the link instead of its
-  * target. Otherwise, reparse points must be treated as regular files.
-  */
-  if (do_lstat &&
-      (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
-    /*
-     * If reading the link fails, the reparse point is not a symlink and needs
-     * to be treated as a regular file. The higher level lstat function will
-     * detect this failure and retry without do_lstat if appropriate.
-     */
-    if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0)
-      return -1;
-    statbuf->st_mode |= S_IFLNK;
-  }
-
-  if (statbuf->st_mode == 0) {
-    if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-      statbuf->st_mode |= _S_IFDIR;
-      statbuf->st_size = 0;
-    } else {
-      statbuf->st_mode |= _S_IFREG;
-      statbuf->st_size = file_info.StandardInformation.EndOfFile.QuadPart;
-    }
-  }
-
-  if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_READONLY)
-    statbuf->st_mode |= _S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6);
-  else
-    statbuf->st_mode |= (_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) |
-                        ((_S_IREAD | _S_IWRITE) >> 6);
-
-  FILETIME_TO_TIMESPEC(statbuf->st_atim, file_info.BasicInformation.LastAccessTime);
-  FILETIME_TO_TIMESPEC(statbuf->st_ctim, file_info.BasicInformation.ChangeTime);
-  FILETIME_TO_TIMESPEC(statbuf->st_mtim, file_info.BasicInformation.LastWriteTime);
-  FILETIME_TO_TIMESPEC(statbuf->st_birthtim, file_info.BasicInformation.CreationTime);
-
-  statbuf->st_ino = file_info.InternalInformation.IndexNumber.QuadPart;
-
-  /* st_blocks contains the on-disk allocation size in 512-byte units. */
-  statbuf->st_blocks =
-      (uint64_t) file_info.StandardInformation.AllocationSize.QuadPart >> 9;
-
-  statbuf->st_nlink = file_info.StandardInformation.NumberOfLinks;
-
-  /* The st_blksize is supposed to be the 'optimal' number of bytes for reading
-   * and writing to the disk. That is, for any definition of 'optimal' - it's
-   * supposed to at least avoid read-update-write behavior when writing to the
-   * disk.
-   *
-   * However nobody knows this and even fewer people actually use this value,
-   * and in order to fill it out we'd have to make another syscall to query the
-   * volume for FILE_FS_SECTOR_SIZE_INFORMATION.
-   *
-   * Therefore we'll just report a sensible value that's quite commonly okay
-   * on modern hardware.
-   *
-   * 4096 is the minimum required to be compatible with newer Advanced Format
-   * drives (which have 4096 bytes per physical sector), and to be backwards
-   * compatible with older drives (which have 512 bytes per physical sector).
-   */
-  statbuf->st_blksize = 4096;
-
-  /* Todo: set st_flags to something meaningful. Also provide a wrapper for
-   * chattr(2).
-   */
-  statbuf->st_flags = 0;
-
-  /* Windows has nothing sensible to say about these values, so they'll just
-   * remain empty.
-   */
-  statbuf->st_gid = 0;
-  statbuf->st_uid = 0;
-  statbuf->st_rdev = 0;
-  statbuf->st_gen = 0;
-
-  return 0;
-}
-
-
-INLINE static void fs__stat_prepare_path(WCHAR* pathw) {
-  size_t len = wcslen(pathw);
-
-  /* TODO: ignore namespaced paths. */
-  if (len > 1 && pathw[len - 2] != L':' &&
-      (pathw[len - 1] == L'\\' || pathw[len - 1] == L'/')) {
-    pathw[len - 1] = '\0';
-  }
-}
-
-
-INLINE static DWORD fs__stat_impl_from_path(WCHAR* path,
-                                            int do_lstat,
-                                            uv_stat_t* statbuf) {
-  HANDLE handle;
-  DWORD flags;
-  DWORD ret;
-
-  flags = FILE_FLAG_BACKUP_SEMANTICS;
-  if (do_lstat)
-    flags |= FILE_FLAG_OPEN_REPARSE_POINT;
-
-  handle = CreateFileW(path,
-                       FILE_READ_ATTRIBUTES,
-                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                       NULL,
-                       OPEN_EXISTING,
-                       flags,
-                       NULL);
-
-  if (handle == INVALID_HANDLE_VALUE)
-    ret = GetLastError();
-  else if (fs__stat_handle(handle, statbuf, do_lstat) != 0)
-    ret = GetLastError();
-  else
-    ret = 0;
-
-  CloseHandle(handle);
-  return ret;
-}
-
-
-INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
-  DWORD error;
-
-  error = fs__stat_impl_from_path(req->file.pathw, do_lstat, &req->statbuf);
-  if (error != 0) {
-    if (do_lstat &&
-        (error == ERROR_SYMLINK_NOT_SUPPORTED ||
-         error == ERROR_NOT_A_REPARSE_POINT)) {
-      /* We opened a reparse point but it was not a symlink. Try again. */
-      fs__stat_impl(req, 0);
-    } else {
-      /* Stat failed. */
-      SET_REQ_WIN32_ERROR(req, error);
-    }
-
-    return;
-  }
-
-  req->ptr = &req->statbuf;
-  req->result = 0;
-}
-
-
-static void fs__stat(uv_fs_t* req) {
-  fs__stat_prepare_path(req->file.pathw);
-  fs__stat_impl(req, 0);
-}
-
-
-static void fs__lstat(uv_fs_t* req) {
-  fs__stat_prepare_path(req->file.pathw);
-  fs__stat_impl(req, 1);
-}
-
-
-static void fs__fstat(uv_fs_t* req) {
-  int fd = req->file.fd;
-  HANDLE handle;
-
-  VERIFY_FD(fd, req);
-
-  handle = uv__get_osfhandle(fd);
-
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
-    return;
-  }
-
-  if (fs__stat_handle(handle, &req->statbuf, 0) != 0) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  req->ptr = &req->statbuf;
-  req->result = 0;
-}
-
-
-static void fs__rename(uv_fs_t* req) {
-  if (!MoveFileExW(req->file.pathw, req->fs.info.new_pathw, MOVEFILE_REPLACE_EXISTING)) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  SET_REQ_RESULT(req, 0);
-}
-
-
-INLINE static void fs__sync_impl(uv_fs_t* req) {
-  int fd = req->file.fd;
-  int result;
-
-  VERIFY_FD(fd, req);
-
-  result = FlushFileBuffers(uv__get_osfhandle(fd)) ? 0 : -1;
-  if (result == -1) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-  } else {
-    SET_REQ_RESULT(req, result);
-  }
-}
-
-
-static void fs__fsync(uv_fs_t* req) {
-  fs__sync_impl(req);
-}
-
-
-static void fs__fdatasync(uv_fs_t* req) {
-  fs__sync_impl(req);
-}
-
-
-static void fs__ftruncate(uv_fs_t* req) {
-  int fd = req->file.fd;
-  HANDLE handle;
-  NTSTATUS status;
-  IO_STATUS_BLOCK io_status;
-  FILE_END_OF_FILE_INFORMATION eof_info;
-
-  VERIFY_FD(fd, req);
-
-  handle = uv__get_osfhandle(fd);
-
-  eof_info.EndOfFile.QuadPart = req->fs.info.offset;
-
-  status = pNtSetInformationFile(handle,
-                                 &io_status,
-                                 &eof_info,
-                                 sizeof eof_info,
-                                 FileEndOfFileInformation);
-
-  if (NT_SUCCESS(status)) {
-    SET_REQ_RESULT(req, 0);
-  } else {
-    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
-  }
-}
-
-
-static void fs__copyfile(uv_fs_t* req) {
-  int flags;
-  int overwrite;
-  uv_stat_t statbuf;
-  uv_stat_t new_statbuf;
-
-  flags = req->fs.info.file_flags;
-
-  if (flags & UV_FS_COPYFILE_FICLONE_FORCE) {
-    SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
-    return;
-  }
-
-  overwrite = flags & UV_FS_COPYFILE_EXCL;
-
-  if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) != 0) {
-    SET_REQ_RESULT(req, 0);
-    return;
-  }
-
-  SET_REQ_WIN32_ERROR(req, GetLastError());
-  if (req->result != UV_EBUSY)
-    return;
-
-  /* if error UV_EBUSY check if src and dst file are the same */
-  if (fs__stat_impl_from_path(req->file.pathw, 0, &statbuf) != 0 ||
-      fs__stat_impl_from_path(req->fs.info.new_pathw, 0, &new_statbuf) != 0) {
-    return;
-  }
-
-  if (statbuf.st_dev == new_statbuf.st_dev &&
-      statbuf.st_ino == new_statbuf.st_ino) {
-    SET_REQ_RESULT(req, 0);
-  }
-}
-
-
-static void fs__sendfile(uv_fs_t* req) {
-  int fd_in = req->file.fd, fd_out = req->fs.info.fd_out;
-  size_t length = req->fs.info.bufsml[0].len;
-  int64_t offset = req->fs.info.offset;
-  const size_t max_buf_size = 65536;
-  size_t buf_size = length < max_buf_size ? length : max_buf_size;
-  int n, result = 0;
-  int64_t result_offset = 0;
-  char* buf = (char*) uv__malloc(buf_size);
-  if (!buf) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  if (offset != -1) {
-    result_offset = _lseeki64(fd_in, offset, SEEK_SET);
-  }
-
-  if (result_offset == -1) {
-    result = -1;
-  } else {
-    while (length > 0) {
-      n = _read(fd_in, buf, length < buf_size ? length : buf_size);
-      if (n == 0) {
-        break;
-      } else if (n == -1) {
-        result = -1;
-        break;
-      }
-
-      length -= n;
-
-      n = _write(fd_out, buf, n);
-      if (n == -1) {
-        result = -1;
-        break;
-      }
-
-      result += n;
-    }
-  }
-
-  uv__free(buf);
-
-  SET_REQ_RESULT(req, result);
-}
-
-
-static void fs__access(uv_fs_t* req) {
-  DWORD attr = GetFileAttributesW(req->file.pathw);
-
-  if (attr == INVALID_FILE_ATTRIBUTES) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  /*
-   * Access is possible if
-   * - write access wasn't requested,
-   * - or the file isn't read-only,
-   * - or it's a directory.
-   * (Directories cannot be read-only on Windows.)
-   */
-  if (!(req->fs.info.mode & W_OK) ||
-      !(attr & FILE_ATTRIBUTE_READONLY) ||
-      (attr & FILE_ATTRIBUTE_DIRECTORY)) {
-    SET_REQ_RESULT(req, 0);
-  } else {
-    SET_REQ_WIN32_ERROR(req, UV_EPERM);
-  }
-
-}
-
-
-static void fs__chmod(uv_fs_t* req) {
-  int result = _wchmod(req->file.pathw, req->fs.info.mode);
-  SET_REQ_RESULT(req, result);
-}
-
-
-static void fs__fchmod(uv_fs_t* req) {
-  int fd = req->file.fd;
-  int clear_archive_flag;
-  HANDLE handle;
-  NTSTATUS nt_status;
-  IO_STATUS_BLOCK io_status;
-  FILE_BASIC_INFORMATION file_info;
-
-  VERIFY_FD(fd, req);
-
-  handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0);
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  nt_status = pNtQueryInformationFile(handle,
-                                      &io_status,
-                                      &file_info,
-                                      sizeof file_info,
-                                      FileBasicInformation);
-
-  if (!NT_SUCCESS(nt_status)) {
-    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
-    goto fchmod_cleanup;
-  }
-
-  /* Test if the Archive attribute is cleared */
-  if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) {
-      /* Set Archive flag, otherwise setting or clearing the read-only
-         flag will not work */
-      file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
-      nt_status = pNtSetInformationFile(handle,
-                                        &io_status,
-                                        &file_info,
-                                        sizeof file_info,
-                                        FileBasicInformation);
-      if (!NT_SUCCESS(nt_status)) {
-        SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
-        goto fchmod_cleanup;
-      }
-      /* Remeber to clear the flag later on */
-      clear_archive_flag = 1;
-  } else {
-      clear_archive_flag = 0;
-  }
-
-  if (req->fs.info.mode & _S_IWRITE) {
-    file_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
-  } else {
-    file_info.FileAttributes |= FILE_ATTRIBUTE_READONLY;
-  }
-
-  nt_status = pNtSetInformationFile(handle,
-                                    &io_status,
-                                    &file_info,
-                                    sizeof file_info,
-                                    FileBasicInformation);
-
-  if (!NT_SUCCESS(nt_status)) {
-    SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
-    goto fchmod_cleanup;
-  }
-
-  if (clear_archive_flag) {
-      file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
-      if (file_info.FileAttributes == 0) {
-          file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL;
-      }
-      nt_status = pNtSetInformationFile(handle,
-                                        &io_status,
-                                        &file_info,
-                                        sizeof file_info,
-                                        FileBasicInformation);
-      if (!NT_SUCCESS(nt_status)) {
-        SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status));
-        goto fchmod_cleanup;
-      }
-  }
-
-  SET_REQ_SUCCESS(req);
-fchmod_cleanup:
-  CloseHandle(handle);
-}
-
-
-INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
-  FILETIME filetime_a, filetime_m;
-
-  TIME_T_TO_FILETIME(atime, &filetime_a);
-  TIME_T_TO_FILETIME(mtime, &filetime_m);
-
-  if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {
-    return -1;
-  }
-
-  return 0;
-}
-
-
-static void fs__utime(uv_fs_t* req) {
-  HANDLE handle;
-
-  handle = CreateFileW(req->file.pathw,
-                       FILE_WRITE_ATTRIBUTES,
-                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                       NULL,
-                       OPEN_EXISTING,
-                       FILE_FLAG_BACKUP_SEMANTICS,
-                       NULL);
-
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    CloseHandle(handle);
-    return;
-  }
-
-  CloseHandle(handle);
-
-  req->result = 0;
-}
-
-
-static void fs__futime(uv_fs_t* req) {
-  int fd = req->file.fd;
-  HANDLE handle;
-  VERIFY_FD(fd, req);
-
-  handle = uv__get_osfhandle(fd);
-
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
-    return;
-  }
-
-  if (fs__utime_handle(handle, req->fs.time.atime, req->fs.time.mtime) != 0) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  req->result = 0;
-}
-
-
-static void fs__link(uv_fs_t* req) {
-  DWORD r = CreateHardLinkW(req->fs.info.new_pathw, req->file.pathw, NULL);
-  if (r == 0) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-  } else {
-    req->result = 0;
-  }
-}
-
-
-static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
-    const WCHAR* new_path) {
-  HANDLE handle = INVALID_HANDLE_VALUE;
-  REPARSE_DATA_BUFFER *buffer = NULL;
-  int created = 0;
-  int target_len;
-  int is_absolute, is_long_path;
-  int needed_buf_size, used_buf_size, used_data_size, path_buf_len;
-  int start, len, i;
-  int add_slash;
-  DWORD bytes;
-  WCHAR* path_buf;
-
-  target_len = wcslen(path);
-  is_long_path = wcsncmp(path, LONG_PATH_PREFIX, LONG_PATH_PREFIX_LEN) == 0;
-
-  if (is_long_path) {
-    is_absolute = 1;
-  } else {
-    is_absolute = target_len >= 3 && IS_LETTER(path[0]) &&
-      path[1] == L':' && IS_SLASH(path[2]);
-  }
-
-  if (!is_absolute) {
-    /* Not supporting relative paths */
-    SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_NOT_SUPPORTED);
-    return;
-  }
-
-  /* Do a pessimistic calculation of the required buffer size */
-  needed_buf_size =
-      FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
-      JUNCTION_PREFIX_LEN * sizeof(WCHAR) +
-      2 * (target_len + 2) * sizeof(WCHAR);
-
-  /* Allocate the buffer */
-  buffer = (REPARSE_DATA_BUFFER*)uv__malloc(needed_buf_size);
-  if (!buffer) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  /* Grab a pointer to the part of the buffer where filenames go */
-  path_buf = (WCHAR*)&(buffer->MountPointReparseBuffer.PathBuffer);
-  path_buf_len = 0;
-
-  /* Copy the substitute (internal) target path */
-  start = path_buf_len;
-
-  wcsncpy((WCHAR*)&path_buf[path_buf_len], JUNCTION_PREFIX,
-    JUNCTION_PREFIX_LEN);
-  path_buf_len += JUNCTION_PREFIX_LEN;
-
-  add_slash = 0;
-  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
-    if (IS_SLASH(path[i])) {
-      add_slash = 1;
-      continue;
-    }
-
-    if (add_slash) {
-      path_buf[path_buf_len++] = L'\\';
-      add_slash = 0;
-    }
-
-    path_buf[path_buf_len++] = path[i];
-  }
-  path_buf[path_buf_len++] = L'\\';
-  len = path_buf_len - start;
-
-  /* Set the info about the substitute name */
-  buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(WCHAR);
-  buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(WCHAR);
-
-  /* Insert null terminator */
-  path_buf[path_buf_len++] = L'\0';
-
-  /* Copy the print name of the target path */
-  start = path_buf_len;
-  add_slash = 0;
-  for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
-    if (IS_SLASH(path[i])) {
-      add_slash = 1;
-      continue;
-    }
-
-    if (add_slash) {
-      path_buf[path_buf_len++] = L'\\';
-      add_slash = 0;
-    }
-
-    path_buf[path_buf_len++] = path[i];
-  }
-  len = path_buf_len - start;
-  if (len == 2) {
-    path_buf[path_buf_len++] = L'\\';
-    len++;
-  }
-
-  /* Set the info about the print name */
-  buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(WCHAR);
-  buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(WCHAR);
-
-  /* Insert another null terminator */
-  path_buf[path_buf_len++] = L'\0';
-
-  /* Calculate how much buffer space was actually used */
-  used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
-    path_buf_len * sizeof(WCHAR);
-  used_data_size = used_buf_size -
-    FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer);
-
-  /* Put general info in the data buffer */
-  buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
-  buffer->ReparseDataLength = used_data_size;
-  buffer->Reserved = 0;
-
-  /* Create a new directory */
-  if (!CreateDirectoryW(new_path, NULL)) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    goto error;
-  }
-  created = 1;
-
-  /* Open the directory */
-  handle = CreateFileW(new_path,
-                       GENERIC_WRITE,
-                       0,
-                       NULL,
-                       OPEN_EXISTING,
-                       FILE_FLAG_BACKUP_SEMANTICS |
-                         FILE_FLAG_OPEN_REPARSE_POINT,
-                       NULL);
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    goto error;
-  }
-
-  /* Create the actual reparse point */
-  if (!DeviceIoControl(handle,
-                       FSCTL_SET_REPARSE_POINT,
-                       buffer,
-                       used_buf_size,
-                       NULL,
-                       0,
-                       &bytes,
-                       NULL)) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    goto error;
-  }
-
-  /* Clean up */
-  CloseHandle(handle);
-  uv__free(buffer);
-
-  SET_REQ_RESULT(req, 0);
-  return;
-
-error:
-  uv__free(buffer);
-
-  if (handle != INVALID_HANDLE_VALUE) {
-    CloseHandle(handle);
-  }
-
-  if (created) {
-    RemoveDirectoryW(new_path);
-  }
-}
-
-
-static void fs__symlink(uv_fs_t* req) {
-  WCHAR* pathw;
-  WCHAR* new_pathw;
-  int flags;
-  int err;
-
-  pathw = req->file.pathw;
-  new_pathw = req->fs.info.new_pathw;
-
-  if (req->fs.info.file_flags & UV_FS_SYMLINK_JUNCTION) {
-    fs__create_junction(req, pathw, new_pathw);
-    return;
-  }
-
-  if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
-    flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
-  else
-    flags = uv__file_symlink_usermode_flag;
-
-  if (CreateSymbolicLinkW(new_pathw, pathw, flags)) {
-    SET_REQ_RESULT(req, 0);
-    return;
-  }
-
-  /* Something went wrong. We will test if it is because of user-mode
-   * symlinks.
-   */
-  err = GetLastError();
-  if (err == ERROR_INVALID_PARAMETER &&
-      flags & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) {
-    /* This system does not support user-mode symlinks. We will clear the
-     * unsupported flag and retry.
-     */
-    uv__file_symlink_usermode_flag = 0;
-    fs__symlink(req);
-  } else {
-    SET_REQ_WIN32_ERROR(req, err);
-  }
-}
-
-
-static void fs__readlink(uv_fs_t* req) {
-  HANDLE handle;
-
-  handle = CreateFileW(req->file.pathw,
-                       0,
-                       0,
-                       NULL,
-                       OPEN_EXISTING,
-                       FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
-                       NULL);
-
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  if (fs__readlink_handle(handle, (char**) &req->ptr, NULL) != 0) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    CloseHandle(handle);
-    return;
-  }
-
-  req->flags |= UV_FS_FREE_PTR;
-  SET_REQ_RESULT(req, 0);
-
-  CloseHandle(handle);
-}
-
-
-static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
-  int r;
-  DWORD w_realpath_len;
-  WCHAR* w_realpath_ptr = NULL;
-  WCHAR* w_realpath_buf;
-
-  w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS);
-  if (w_realpath_len == 0) {
-    return -1;
-  }
-
-  w_realpath_buf = (WCHAR*)uv__malloc((w_realpath_len + 1) * sizeof(WCHAR));
-  if (w_realpath_buf == NULL) {
-    SetLastError(ERROR_OUTOFMEMORY);
-    return -1;
-  }
-  w_realpath_ptr = w_realpath_buf;
-
-  if (GetFinalPathNameByHandleW(
-          handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) {
-    uv__free(w_realpath_buf);
-    SetLastError(ERROR_INVALID_HANDLE);
-    return -1;
-  }
-
-  /* convert UNC path to long path */
-  if (wcsncmp(w_realpath_ptr,
-              UNC_PATH_PREFIX,
-              UNC_PATH_PREFIX_LEN) == 0) {
-    w_realpath_ptr += 6;
-    *w_realpath_ptr = L'\\';
-    w_realpath_len -= 6;
-  } else if (wcsncmp(w_realpath_ptr,
-                      LONG_PATH_PREFIX,
-                      LONG_PATH_PREFIX_LEN) == 0) {
-    w_realpath_ptr += 4;
-    w_realpath_len -= 4;
-  } else {
-    uv__free(w_realpath_buf);
-    SetLastError(ERROR_INVALID_HANDLE);
-    return -1;
-  }
-
-  r = fs__wide_to_utf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
-  uv__free(w_realpath_buf);
-  return r;
-}
-
-static void fs__realpath(uv_fs_t* req) {
-  HANDLE handle;
-
-  handle = CreateFileW(req->file.pathw,
-                       0,
-                       0,
-                       NULL,
-                       OPEN_EXISTING,
-                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
-                       NULL);
-  if (handle == INVALID_HANDLE_VALUE) {
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  if (fs__realpath_handle(handle, (char**) &req->ptr) == -1) {
-    CloseHandle(handle);
-    SET_REQ_WIN32_ERROR(req, GetLastError());
-    return;
-  }
-
-  CloseHandle(handle);
-  req->flags |= UV_FS_FREE_PTR;
-  SET_REQ_RESULT(req, 0);
-}
-
-
-static void fs__chown(uv_fs_t* req) {
-  req->result = 0;
-}
-
-
-static void fs__fchown(uv_fs_t* req) {
-  req->result = 0;
-}
-
-
-static void fs__lchown(uv_fs_t* req) {
-  req->result = 0;
-}
-
-static void uv__fs_work(struct uv__work* w) {
-  uv_fs_t* req;
-
-  req = container_of(w, uv_fs_t, work_req);
-  assert(req->type == UV_FS);
-
-#define XX(uc, lc)  case UV_FS_##uc: fs__##lc(req); break;
-  switch (req->fs_type) {
-    XX(OPEN, open)
-    XX(CLOSE, close)
-    XX(READ, read)
-    XX(WRITE, write)
-    XX(COPYFILE, copyfile)
-    XX(SENDFILE, sendfile)
-    XX(STAT, stat)
-    XX(LSTAT, lstat)
-    XX(FSTAT, fstat)
-    XX(FTRUNCATE, ftruncate)
-    XX(UTIME, utime)
-    XX(FUTIME, futime)
-    XX(ACCESS, access)
-    XX(CHMOD, chmod)
-    XX(FCHMOD, fchmod)
-    XX(FSYNC, fsync)
-    XX(FDATASYNC, fdatasync)
-    XX(UNLINK, unlink)
-    XX(RMDIR, rmdir)
-    XX(MKDIR, mkdir)
-    XX(MKDTEMP, mkdtemp)
-    XX(RENAME, rename)
-    XX(SCANDIR, scandir)
-    XX(READDIR, readdir)
-    XX(OPENDIR, opendir)
-    XX(CLOSEDIR, closedir)
-    XX(LINK, link)
-    XX(SYMLINK, symlink)
-    XX(READLINK, readlink)
-    XX(REALPATH, realpath)
-    XX(CHOWN, chown)
-    XX(FCHOWN, fchown);
-    XX(LCHOWN, lchown);
-    default:
-      assert(!"bad uv_fs_type");
-  }
-}
-
-
-static void uv__fs_done(struct uv__work* w, int status) {
-  uv_fs_t* req;
-
-  req = container_of(w, uv_fs_t, work_req);
-  uv__req_unregister(req->loop, req);
-
-  if (status == UV_ECANCELED) {
-    assert(req->result == 0);
-    req->result = UV_ECANCELED;
-  }
-
-  req->cb(req);
-}
-
-
-void uv_fs_req_cleanup(uv_fs_t* req) {
-  if (req == NULL)
-    return;
-
-  if (req->flags & UV_FS_CLEANEDUP)
-    return;
-
-  if (req->flags & UV_FS_FREE_PATHS)
-    uv__free(req->file.pathw);
-
-  if (req->flags & UV_FS_FREE_PTR) {
-    if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
-      uv__fs_scandir_cleanup(req);
-    else if (req->fs_type == UV_FS_READDIR)
-      uv__fs_readdir_cleanup(req);
-    else
-      uv__free(req->ptr);
-  }
-
-  if (req->fs.info.bufs != req->fs.info.bufsml)
-    uv__free(req->fs.info.bufs);
-
-  req->path = NULL;
-  req->file.pathw = NULL;
-  req->fs.info.new_pathw = NULL;
-  req->fs.info.bufs = NULL;
-  req->ptr = NULL;
-
-  req->flags |= UV_FS_CLEANEDUP;
-}
-
-
-int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
-    int mode, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_OPEN);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  req->fs.info.file_flags = flags;
-  req->fs.info.mode = mode;
-  POST;
-}
-
-
-int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
-  INIT(UV_FS_CLOSE);
-  req->file.fd = fd;
-  POST;
-}
-
-
-int uv_fs_read(uv_loop_t* loop,
-               uv_fs_t* req,
-               uv_file fd,
-               const uv_buf_t bufs[],
-               unsigned int nbufs,
-               int64_t offset,
-               uv_fs_cb cb) {
-  INIT(UV_FS_READ);
-
-  if (bufs == NULL || nbufs == 0)
-    return UV_EINVAL;
-
-  req->file.fd = fd;
-
-  req->fs.info.nbufs = nbufs;
-  req->fs.info.bufs = req->fs.info.bufsml;
-  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
-    req->fs.info.bufs = (uv_buf_t*)uv__malloc(nbufs * sizeof(*bufs));
-
-  if (req->fs.info.bufs == NULL)
-    return UV_ENOMEM;
-
-  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
-
-  req->fs.info.offset = offset;
-  POST;
-}
-
-
-int uv_fs_write(uv_loop_t* loop,
-                uv_fs_t* req,
-                uv_file fd,
-                const uv_buf_t bufs[],
-                unsigned int nbufs,
-                int64_t offset,
-                uv_fs_cb cb) {
-  INIT(UV_FS_WRITE);
-
-  if (bufs == NULL || nbufs == 0)
-    return UV_EINVAL;
-
-  req->file.fd = fd;
-
-  req->fs.info.nbufs = nbufs;
-  req->fs.info.bufs = req->fs.info.bufsml;
-  if (nbufs > ARRAY_SIZE(req->fs.info.bufsml))
-    req->fs.info.bufs = (uv_buf_t*)uv__malloc(nbufs * sizeof(*bufs));
-
-  if (req->fs.info.bufs == NULL)
-    return UV_ENOMEM;
-
-  memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
-
-  req->fs.info.offset = offset;
-  POST;
-}
-
-
-int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
-    uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_UNLINK);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
-    uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_MKDIR);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  req->fs.info.mode = mode;
-  POST;
-}
-
-
-int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl,
-    uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_MKDTEMP);
-  err = fs__capture_path(req, tpl, NULL, TRUE);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  POST;
-}
-
-
-int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_RMDIR);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
-    uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_SCANDIR);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  req->fs.info.file_flags = flags;
-  POST;
-}
-
-int uv_fs_opendir(uv_loop_t* loop,
-                  uv_fs_t* req,
-                  const char* path,
-                  uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_OPENDIR);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err)
-    return uv_translate_sys_error(err);
-  POST;
-}
-
-int uv_fs_readdir(uv_loop_t* loop,
-                  uv_fs_t* req,
-                  uv_dir_t* dir,
-                  uv_fs_cb cb) {
-  INIT(UV_FS_READDIR);
-
-  if (dir == NULL ||
-      dir->dirents == NULL ||
-      dir->dir_handle == INVALID_HANDLE_VALUE) {
-    return UV_EINVAL;
-  }
-
-  req->ptr = dir;
-  POST;
-}
-
-int uv_fs_closedir(uv_loop_t* loop,
-                   uv_fs_t* req,
-                   uv_dir_t* dir,
-                   uv_fs_cb cb) {
-  INIT(UV_FS_CLOSEDIR);
-  if (dir == NULL)
-    return UV_EINVAL;
-  req->ptr = dir;
-  POST;
-}
-
-int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
-    const char* new_path, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_LINK);
-  err = fs__capture_path(req, path, new_path, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
-    const char* new_path, int flags, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_SYMLINK);
-  err = fs__capture_path(req, path, new_path, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  req->fs.info.file_flags = flags;
-  POST;
-}
-
-
-int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
-    uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_READLINK);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
-    uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_REALPATH);
-
-  if (!path) {
-    return UV_EINVAL;
-  }
-
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
-    uv_gid_t gid, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_CHOWN);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
-    uv_gid_t gid, uv_fs_cb cb) {
-  INIT(UV_FS_FCHOWN);
-  POST;
-}
-
-
-int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
-    uv_gid_t gid, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_LCHOWN);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-  POST;
-}
-
-
-int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_STAT);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_LSTAT);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
-  INIT(UV_FS_FSTAT);
-  req->file.fd = fd;
-  POST;
-}
-
-
-int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
-    const char* new_path, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_RENAME);
-  err = fs__capture_path(req, path, new_path, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  POST;
-}
-
-
-int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
-  INIT(UV_FS_FSYNC);
-  req->file.fd = fd;
-  POST;
-}
-
-
-int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
-  INIT(UV_FS_FDATASYNC);
-  req->file.fd = fd;
-  POST;
-}
-
-
-int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd,
-    int64_t offset, uv_fs_cb cb) {
-  INIT(UV_FS_FTRUNCATE);
-  req->file.fd = fd;
-  req->fs.info.offset = offset;
-  POST;
-}
-
-
-int uv_fs_copyfile(uv_loop_t* loop,
-                   uv_fs_t* req,
-                   const char* path,
-                   const char* new_path,
-                   int flags,
-                   uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_COPYFILE);
-
-  if (flags & ~(UV_FS_COPYFILE_EXCL |
-                UV_FS_COPYFILE_FICLONE |
-                UV_FS_COPYFILE_FICLONE_FORCE)) {
-    return UV_EINVAL;
-  }
-
-  err = fs__capture_path(req, path, new_path, cb != NULL);
-
-  if (err)
-    return uv_translate_sys_error(err);
-
-  req->fs.info.file_flags = flags;
-  POST;
-}
-
-
-int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,
-    uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) {
-  INIT(UV_FS_SENDFILE);
-  req->file.fd = fd_in;
-  req->fs.info.fd_out = fd_out;
-  req->fs.info.offset = in_offset;
-  req->fs.info.bufsml[0].len = length;
-  POST;
-}
-
-
-int uv_fs_access(uv_loop_t* loop,
-                 uv_fs_t* req,
-                 const char* path,
-                 int flags,
-                 uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_ACCESS);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  req->fs.info.mode = flags;
-  POST;
-}
-
-
-int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
-    uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_CHMOD);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  req->fs.info.mode = mode;
-  POST;
-}
-
-
-int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode,
-    uv_fs_cb cb) {
-  INIT(UV_FS_FCHMOD);
-  req->file.fd = fd;
-  req->fs.info.mode = mode;
-  POST;
-}
-
-
-int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
-    double mtime, uv_fs_cb cb) {
-  int err;
-
-  INIT(UV_FS_UTIME);
-  err = fs__capture_path(req, path, NULL, cb != NULL);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  req->fs.time.atime = atime;
-  req->fs.time.mtime = mtime;
-  POST;
-}
-
-
-int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
-    double mtime, uv_fs_cb cb) {
-  INIT(UV_FS_FUTIME);
-  req->file.fd = fd;
-  req->fs.time.atime = atime;
-  req->fs.time.mtime = mtime;
-  POST;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/getaddrinfo.cpp b/wpiutil/src/main/native/libuv/src/win/getaddrinfo.cpp
deleted file mode 100644
index dfab860..0000000
--- a/wpiutil/src/main/native/libuv/src/win/getaddrinfo.cpp
+++ /dev/null
@@ -1,463 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "req-inl.h"
-#include "idna.h"
-
-/* EAI_* constants. */
-#include <winsock2.h>
-
-/* Needed for ConvertInterfaceIndexToLuid and ConvertInterfaceLuidToNameA */
-#include <iphlpapi.h>
-
-int uv__getaddrinfo_translate_error(int sys_err) {
-  switch (sys_err) {
-    case 0:                       return 0;
-    case WSATRY_AGAIN:            return UV_EAI_AGAIN;
-    case WSAEINVAL:               return UV_EAI_BADFLAGS;
-    case WSANO_RECOVERY:          return UV_EAI_FAIL;
-    case WSAEAFNOSUPPORT:         return UV_EAI_FAMILY;
-    case WSA_NOT_ENOUGH_MEMORY:   return UV_EAI_MEMORY;
-    case WSAHOST_NOT_FOUND:       return UV_EAI_NONAME;
-    case WSATYPE_NOT_FOUND:       return UV_EAI_SERVICE;
-    case WSAESOCKTNOSUPPORT:      return UV_EAI_SOCKTYPE;
-    default:                      return uv_translate_sys_error(sys_err);
-  }
-}
-
-
-/*
- * MinGW is missing this
- */
-#if !defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR)
-  typedef struct addrinfoW {
-    int ai_flags;
-    int ai_family;
-    int ai_socktype;
-    int ai_protocol;
-    size_t ai_addrlen;
-    WCHAR* ai_canonname;
-    struct sockaddr* ai_addr;
-    struct addrinfoW* ai_next;
-  } ADDRINFOW, *PADDRINFOW;
-
-  DECLSPEC_IMPORT int WSAAPI GetAddrInfoW(const WCHAR* node,
-                                          const WCHAR* service,
-                                          const ADDRINFOW* hints,
-                                          PADDRINFOW* result);
-
-  DECLSPEC_IMPORT void WSAAPI FreeAddrInfoW(PADDRINFOW pAddrInfo);
-#endif
-
-
-/* Adjust size value to be multiple of 4. Use to keep pointer aligned.
- * Do we need different versions of this for different architectures? */
-#define ALIGNED_SIZE(X)     ((((X) + 3) >> 2) << 2)
-
-#ifndef NDIS_IF_MAX_STRING_SIZE
-#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE
-#endif
-
-static void uv__getaddrinfo_work(struct uv__work* w) {
-  uv_getaddrinfo_t* req;
-  struct addrinfoW* hints;
-  int err;
-
-  req = container_of(w, uv_getaddrinfo_t, work_req);
-  hints = req->addrinfow;
-  req->addrinfow = NULL;
-  err = GetAddrInfoW(req->node, req->service, hints, &req->addrinfow);
-  req->retcode = uv__getaddrinfo_translate_error(err);
-}
-
-
-/*
- * Called from uv_run when complete. Call user specified callback
- * then free returned addrinfo
- * Returned addrinfo strings are converted from UTF-16 to UTF-8.
- *
- * To minimize allocation we calculate total size required,
- * and copy all structs and referenced strings into the one block.
- * Each size calculation is adjusted to avoid unaligned pointers.
- */
-static void uv__getaddrinfo_done(struct uv__work* w, int status) {
-  uv_getaddrinfo_t* req;
-  int addrinfo_len = 0;
-  int name_len = 0;
-  size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
-  struct addrinfoW* addrinfow_ptr;
-  struct addrinfo* addrinfo_ptr;
-  char* alloc_ptr = NULL;
-  char* cur_ptr = NULL;
-
-  req = container_of(w, uv_getaddrinfo_t, work_req);
-
-  /* release input parameter memory */
-  uv__free(req->alloc);
-  req->alloc = NULL;
-
-  if (status == UV_ECANCELED) {
-    assert(req->retcode == 0);
-    req->retcode = UV_EAI_CANCELED;
-    goto complete;
-  }
-
-  if (req->retcode == 0) {
-    /* Convert addrinfoW to addrinfo. First calculate required length. */
-    addrinfow_ptr = req->addrinfow;
-    while (addrinfow_ptr != NULL) {
-      addrinfo_len += addrinfo_struct_len +
-          ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
-      if (addrinfow_ptr->ai_canonname != NULL) {
-        name_len = WideCharToMultiByte(CP_UTF8,
-                                       0,
-                                       addrinfow_ptr->ai_canonname,
-                                       -1,
-                                       NULL,
-                                       0,
-                                       NULL,
-                                       NULL);
-        if (name_len == 0) {
-          req->retcode = uv_translate_sys_error(GetLastError());
-          goto complete;
-        }
-        addrinfo_len += ALIGNED_SIZE(name_len);
-      }
-      addrinfow_ptr = addrinfow_ptr->ai_next;
-    }
-
-    /* allocate memory for addrinfo results */
-    alloc_ptr = (char*)uv__malloc(addrinfo_len);
-
-    /* do conversions */
-    if (alloc_ptr != NULL) {
-      cur_ptr = alloc_ptr;
-      addrinfow_ptr = req->addrinfow;
-
-      while (addrinfow_ptr != NULL) {
-        /* copy addrinfo struct data */
-        assert(cur_ptr + addrinfo_struct_len <= alloc_ptr + addrinfo_len);
-        addrinfo_ptr = (struct addrinfo*)cur_ptr;
-        addrinfo_ptr->ai_family = addrinfow_ptr->ai_family;
-        addrinfo_ptr->ai_socktype = addrinfow_ptr->ai_socktype;
-        addrinfo_ptr->ai_protocol = addrinfow_ptr->ai_protocol;
-        addrinfo_ptr->ai_flags = addrinfow_ptr->ai_flags;
-        addrinfo_ptr->ai_addrlen = addrinfow_ptr->ai_addrlen;
-        addrinfo_ptr->ai_canonname = NULL;
-        addrinfo_ptr->ai_addr = NULL;
-        addrinfo_ptr->ai_next = NULL;
-
-        cur_ptr += addrinfo_struct_len;
-
-        /* copy sockaddr */
-        if (addrinfo_ptr->ai_addrlen > 0) {
-          assert(cur_ptr + addrinfo_ptr->ai_addrlen <=
-                 alloc_ptr + addrinfo_len);
-          memcpy(cur_ptr, addrinfow_ptr->ai_addr, addrinfo_ptr->ai_addrlen);
-          addrinfo_ptr->ai_addr = (struct sockaddr*)cur_ptr;
-          cur_ptr += ALIGNED_SIZE(addrinfo_ptr->ai_addrlen);
-        }
-
-        /* convert canonical name to UTF-8 */
-        if (addrinfow_ptr->ai_canonname != NULL) {
-          name_len = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         addrinfow_ptr->ai_canonname,
-                                         -1,
-                                         NULL,
-                                         0,
-                                         NULL,
-                                         NULL);
-          assert(name_len > 0);
-          assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);
-          name_len = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         addrinfow_ptr->ai_canonname,
-                                         -1,
-                                         cur_ptr,
-                                         name_len,
-                                         NULL,
-                                         NULL);
-          assert(name_len > 0);
-          addrinfo_ptr->ai_canonname = cur_ptr;
-          cur_ptr += ALIGNED_SIZE(name_len);
-        }
-        assert(cur_ptr <= alloc_ptr + addrinfo_len);
-
-        /* set next ptr */
-        addrinfow_ptr = addrinfow_ptr->ai_next;
-        if (addrinfow_ptr != NULL) {
-          addrinfo_ptr->ai_next = (struct addrinfo*)cur_ptr;
-        }
-      }
-      req->addrinfo = (struct addrinfo*)alloc_ptr;
-    } else {
-      req->retcode = UV_EAI_MEMORY;
-    }
-  }
-
-  /* return memory to system */
-  if (req->addrinfow != NULL) {
-    FreeAddrInfoW(req->addrinfow);
-    req->addrinfow = NULL;
-  }
-
-complete:
-  uv__req_unregister(req->loop, req);
-
-  /* finally do callback with converted result */
-  if (req->getaddrinfo_cb)
-    req->getaddrinfo_cb(req, req->retcode, req->addrinfo);
-}
-
-
-void uv_freeaddrinfo(struct addrinfo* ai) {
-  char* alloc_ptr = (char*)ai;
-
-  /* release copied result memory */
-  uv__free(alloc_ptr);
-}
-
-
-/*
- * Entry point for getaddrinfo
- * we convert the UTF-8 strings to UNICODE
- * and save the UNICODE string pointers in the req
- * We also copy hints so that caller does not need to keep memory until the
- * callback.
- * return 0 if a callback will be made
- * return error code if validation fails
- *
- * To minimize allocation we calculate total size required,
- * and copy all structs and referenced strings into the one block.
- * Each size calculation is adjusted to avoid unaligned pointers.
- */
-int uv_getaddrinfo(uv_loop_t* loop,
-                   uv_getaddrinfo_t* req,
-                   uv_getaddrinfo_cb getaddrinfo_cb,
-                   const char* node,
-                   const char* service,
-                   const struct addrinfo* hints) {
-  char hostname_ascii[256];
-  int nodesize = 0;
-  int servicesize = 0;
-  int hintssize = 0;
-  char* alloc_ptr = NULL;
-  int err;
-  long rc;
-
-  if (req == NULL || (node == NULL && service == NULL)) {
-    return UV_EINVAL;
-  }
-
-  UV_REQ_INIT(req, UV_GETADDRINFO);
-  req->getaddrinfo_cb = getaddrinfo_cb;
-  req->addrinfo = NULL;
-  req->loop = loop;
-  req->retcode = 0;
-
-  /* calculate required memory size for all input values */
-  if (node != NULL) {
-    rc = uv__idna_toascii(node,
-                          node + strlen(node),
-                          hostname_ascii,
-                          hostname_ascii + sizeof(hostname_ascii));
-    if (rc < 0)
-      return rc;
-    nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,
-                                                -1, NULL, 0) * sizeof(WCHAR));
-    if (nodesize == 0) {
-      err = GetLastError();
-      goto error;
-    }
-    node = hostname_ascii;
-  }
-
-  if (service != NULL) {
-    servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8,
-                                                   0,
-                                                   service,
-                                                   -1,
-                                                   NULL,
-                                                   0) *
-                               sizeof(WCHAR));
-    if (servicesize == 0) {
-      err = GetLastError();
-      goto error;
-    }
-  }
-  if (hints != NULL) {
-    hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
-  }
-
-  /* allocate memory for inputs, and partition it as needed */
-  alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);
-  if (!alloc_ptr) {
-    err = WSAENOBUFS;
-    goto error;
-  }
-
-  /* save alloc_ptr now so we can free if error */
-  req->alloc = (void*)alloc_ptr;
-
-  /* Convert node string to UTF16 into allocated memory and save pointer in the
-   * request. */
-  if (node != NULL) {
-    req->node = (WCHAR*)alloc_ptr;
-    if (MultiByteToWideChar(CP_UTF8,
-                            0,
-                            node,
-                            -1,
-                            (WCHAR*) alloc_ptr,
-                            nodesize / sizeof(WCHAR)) == 0) {
-      err = GetLastError();
-      goto error;
-    }
-    alloc_ptr += nodesize;
-  } else {
-    req->node = NULL;
-  }
-
-  /* Convert service string to UTF16 into allocated memory and save pointer in
-   * the req. */
-  if (service != NULL) {
-    req->service = (WCHAR*)alloc_ptr;
-    if (MultiByteToWideChar(CP_UTF8,
-                            0,
-                            service,
-                            -1,
-                            (WCHAR*) alloc_ptr,
-                            servicesize / sizeof(WCHAR)) == 0) {
-      err = GetLastError();
-      goto error;
-    }
-    alloc_ptr += servicesize;
-  } else {
-    req->service = NULL;
-  }
-
-  /* copy hints to allocated memory and save pointer in req */
-  if (hints != NULL) {
-    req->addrinfow = (struct addrinfoW*)alloc_ptr;
-    req->addrinfow->ai_family = hints->ai_family;
-    req->addrinfow->ai_socktype = hints->ai_socktype;
-    req->addrinfow->ai_protocol = hints->ai_protocol;
-    req->addrinfow->ai_flags = hints->ai_flags;
-    req->addrinfow->ai_addrlen = 0;
-    req->addrinfow->ai_canonname = NULL;
-    req->addrinfow->ai_addr = NULL;
-    req->addrinfow->ai_next = NULL;
-  } else {
-    req->addrinfow = NULL;
-  }
-
-  uv__req_register(loop, req);
-
-  if (getaddrinfo_cb) {
-    uv__work_submit(loop,
-                    &req->work_req,
-                    UV__WORK_SLOW_IO,
-                    uv__getaddrinfo_work,
-                    uv__getaddrinfo_done);
-    return 0;
-  } else {
-    uv__getaddrinfo_work(&req->work_req);
-    uv__getaddrinfo_done(&req->work_req, 0);
-    return req->retcode;
-  }
-
-error:
-  if (req != NULL) {
-    uv__free(req->alloc);
-    req->alloc = NULL;
-  }
-  return uv_translate_sys_error(err);
-}
-
-int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
-  NET_LUID luid;
-  wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
-  DWORD bufsize;
-  int r;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  r = ConvertInterfaceIndexToLuid(ifindex, &luid);
-
-  if (r != 0)
-    return uv_translate_sys_error(r);
-
-  r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
-
-  if (r != 0)
-    return uv_translate_sys_error(r);
-
-  /* Check how much space we need */
-  bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
-
-  if (bufsize == 0) {
-    return uv_translate_sys_error(GetLastError());
-  } else if (bufsize > *size) {
-    *size = bufsize;
-    return UV_ENOBUFS;
-  }
-
-  /* Convert to UTF-8 */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                wname,
-                                -1,
-                                buffer,
-                                *size,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  *size = bufsize - 1;
-  return 0;
-}
-
-int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
-  int r;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  r = snprintf(buffer, *size, "%d", ifindex);
-
-  if (r < 0)
-    return uv_translate_sys_error(r);
-
-  if (r >= (int) *size) {
-    *size = r + 1;
-    return UV_ENOBUFS;
-  }
-
-  *size = r;
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/getnameinfo.cpp b/wpiutil/src/main/native/libuv/src/win/getnameinfo.cpp
deleted file mode 100644
index b377338..0000000
--- a/wpiutil/src/main/native/libuv/src/win/getnameinfo.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to
-* deal in the Software without restriction, including without limitation the
-* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-* sell copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in
-* all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-* IN THE SOFTWARE.
-*/
-
-#include <assert.h>
-#include <stdio.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "req-inl.h"
-
-#ifndef GetNameInfo
-int WSAAPI GetNameInfoW(
-  const SOCKADDR *pSockaddr,
-  socklen_t SockaddrLength,
-  PWCHAR pNodeBuffer,
-  DWORD NodeBufferSize,
-  PWCHAR pServiceBuffer,
-  DWORD ServiceBufferSize,
-  INT Flags
-);
-#endif
-
-static void uv__getnameinfo_work(struct uv__work* w) {
-  uv_getnameinfo_t* req;
-  WCHAR host[NI_MAXHOST];
-  WCHAR service[NI_MAXSERV];
-  int ret;
-
-  req = container_of(w, uv_getnameinfo_t, work_req);
-  if (GetNameInfoW((struct sockaddr*)&req->storage,
-                   sizeof(req->storage),
-                   host,
-                   ARRAY_SIZE(host),
-                   service,
-                   ARRAY_SIZE(service),
-                   req->flags)) {
-    ret = WSAGetLastError();
-    req->retcode = uv__getaddrinfo_translate_error(ret);
-    return;
-  }
-
-  ret = WideCharToMultiByte(CP_UTF8,
-                            0,
-                            host,
-                            -1,
-                            req->host,
-                            sizeof(req->host),
-                            NULL,
-                            NULL);
-  if (ret == 0) {
-    req->retcode = uv_translate_sys_error(GetLastError());
-    return;
-  }
-
-  ret = WideCharToMultiByte(CP_UTF8,
-                            0,
-                            service,
-                            -1,
-                            req->service,
-                            sizeof(req->service),
-                            NULL,
-                            NULL);
-  if (ret == 0) {
-    req->retcode = uv_translate_sys_error(GetLastError());
-  }
-}
-
-
-/*
-* Called from uv_run when complete.
-*/
-static void uv__getnameinfo_done(struct uv__work* w, int status) {
-  uv_getnameinfo_t* req;
-  char* host;
-  char* service;
-
-  req = container_of(w, uv_getnameinfo_t, work_req);
-  uv__req_unregister(req->loop, req);
-  host = service = NULL;
-
-  if (status == UV_ECANCELED) {
-    assert(req->retcode == 0);
-    req->retcode = UV_EAI_CANCELED;
-  } else if (req->retcode == 0) {
-    host = req->host;
-    service = req->service;
-  }
-
-  if (req->getnameinfo_cb)
-    req->getnameinfo_cb(req, req->retcode, host, service);
-}
-
-
-/*
-* Entry point for getnameinfo
-* return 0 if a callback will be made
-* return error code if validation fails
-*/
-int uv_getnameinfo(uv_loop_t* loop,
-                   uv_getnameinfo_t* req,
-                   uv_getnameinfo_cb getnameinfo_cb,
-                   const struct sockaddr* addr,
-                   int flags) {
-  if (req == NULL || addr == NULL)
-    return UV_EINVAL;
-
-  if (addr->sa_family == AF_INET) {
-    memcpy(&req->storage,
-           addr,
-           sizeof(struct sockaddr_in));
-  } else if (addr->sa_family == AF_INET6) {
-    memcpy(&req->storage,
-           addr,
-           sizeof(struct sockaddr_in6));
-  } else {
-    return UV_EINVAL;
-  }
-
-  UV_REQ_INIT(req, UV_GETNAMEINFO);
-  uv__req_register(loop, req);
-
-  req->getnameinfo_cb = getnameinfo_cb;
-  req->flags = flags;
-  req->loop = loop;
-  req->retcode = 0;
-
-  if (getnameinfo_cb) {
-    uv__work_submit(loop,
-                    &req->work_req,
-                    UV__WORK_SLOW_IO,
-                    uv__getnameinfo_work,
-                    uv__getnameinfo_done);
-    return 0;
-  } else {
-    uv__getnameinfo_work(&req->work_req);
-    uv__getnameinfo_done(&req->work_req, 0);
-    return req->retcode;
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/handle-inl.h b/wpiutil/src/main/native/libuv/src/win/handle-inl.h
deleted file mode 100644
index 82c657d..0000000
--- a/wpiutil/src/main/native/libuv/src/win/handle-inl.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_WIN_HANDLE_INL_H_
-#define UV_WIN_HANDLE_INL_H_
-
-#include <assert.h>
-#include <io.h>
-
-#include "uv.h"
-#include "internal.h"
-
-
-#define DECREASE_ACTIVE_COUNT(loop, handle)                             \
-  do {                                                                  \
-    if (--(handle)->activecnt == 0 &&                                   \
-        !((handle)->flags & UV_HANDLE_CLOSING)) {                       \
-      uv__handle_stop((handle));                                        \
-    }                                                                   \
-    assert((handle)->activecnt >= 0);                                   \
-  } while (0)
-
-
-#define INCREASE_ACTIVE_COUNT(loop, handle)                             \
-  do {                                                                  \
-    if ((handle)->activecnt++ == 0) {                                   \
-      uv__handle_start((handle));                                       \
-    }                                                                   \
-    assert((handle)->activecnt > 0);                                    \
-  } while (0)
-
-
-#define DECREASE_PENDING_REQ_COUNT(handle)                              \
-  do {                                                                  \
-    assert(handle->reqs_pending > 0);                                   \
-    handle->reqs_pending--;                                             \
-                                                                        \
-    if (handle->flags & UV_HANDLE_CLOSING &&                            \
-        handle->reqs_pending == 0) {                                    \
-      uv_want_endgame(loop, (uv_handle_t*)handle);                      \
-    }                                                                   \
-  } while (0)
-
-
-#define uv__handle_closing(handle)                                      \
-  do {                                                                  \
-    assert(!((handle)->flags & UV_HANDLE_CLOSING));                     \
-                                                                        \
-    if (!(((handle)->flags & UV_HANDLE_ACTIVE) &&                       \
-          ((handle)->flags & UV_HANDLE_REF)))                           \
-      uv__active_handle_add((uv_handle_t*) (handle));                   \
-                                                                        \
-    (handle)->flags |= UV_HANDLE_CLOSING;                               \
-    (handle)->flags &= ~UV_HANDLE_ACTIVE;                               \
-  } while (0)
-
-
-#define uv__handle_close(handle)                                        \
-  do {                                                                  \
-    QUEUE_REMOVE(&(handle)->handle_queue);                              \
-    uv__active_handle_rm((uv_handle_t*) (handle));                      \
-                                                                        \
-    (handle)->flags |= UV_HANDLE_CLOSED;                                \
-                                                                        \
-    if ((handle)->close_cb)                                             \
-      (handle)->close_cb((uv_handle_t*) (handle));                      \
-  } while (0)
-
-
-INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) {
-  if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) {
-    handle->flags |= UV_HANDLE_ENDGAME_QUEUED;
-
-    handle->endgame_next = loop->endgame_handles;
-    loop->endgame_handles = handle;
-  }
-}
-
-
-INLINE static void uv_process_endgames(uv_loop_t* loop) {
-  uv_handle_t* handle;
-
-  while (loop->endgame_handles) {
-    handle = loop->endgame_handles;
-    loop->endgame_handles = handle->endgame_next;
-
-    handle->flags &= ~UV_HANDLE_ENDGAME_QUEUED;
-
-    switch (handle->type) {
-      case UV_TCP:
-        uv_tcp_endgame(loop, (uv_tcp_t*) handle);
-        break;
-
-      case UV_NAMED_PIPE:
-        uv_pipe_endgame(loop, (uv_pipe_t*) handle);
-        break;
-
-      case UV_TTY:
-        uv_tty_endgame(loop, (uv_tty_t*) handle);
-        break;
-
-      case UV_UDP:
-        uv_udp_endgame(loop, (uv_udp_t*) handle);
-        break;
-
-      case UV_POLL:
-        uv_poll_endgame(loop, (uv_poll_t*) handle);
-        break;
-
-      case UV_TIMER:
-        uv__timer_close((uv_timer_t*) handle);
-        uv__handle_close(handle);
-        break;
-
-      case UV_PREPARE:
-      case UV_CHECK:
-      case UV_IDLE:
-        uv_loop_watcher_endgame(loop, handle);
-        break;
-
-      case UV_ASYNC:
-        uv_async_endgame(loop, (uv_async_t*) handle);
-        break;
-
-      case UV_SIGNAL:
-        uv_signal_endgame(loop, (uv_signal_t*) handle);
-        break;
-
-      case UV_PROCESS:
-        uv_process_endgame(loop, (uv_process_t*) handle);
-        break;
-
-      case UV_FS_EVENT:
-        uv_fs_event_endgame(loop, (uv_fs_event_t*) handle);
-        break;
-
-      case UV_FS_POLL:
-        uv__fs_poll_endgame(loop, (uv_fs_poll_t*) handle);
-        break;
-
-      default:
-        assert(0);
-        break;
-    }
-  }
-}
-
-INLINE static HANDLE uv__get_osfhandle(int fd)
-{
-  /* _get_osfhandle() raises an assert in debug builds if the FD is invalid.
-   * But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for
-   * invalid FDs in release builds (or if you let the assert continue). So this
-   * wrapper function disables asserts when calling _get_osfhandle. */
-
-  HANDLE handle;
-  UV_BEGIN_DISABLE_CRT_ASSERT();
-  handle = (HANDLE) _get_osfhandle(fd);
-  UV_END_DISABLE_CRT_ASSERT();
-  return handle;
-}
-
-#endif /* UV_WIN_HANDLE_INL_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/win/handle.cpp b/wpiutil/src/main/native/libuv/src/win/handle.cpp
deleted file mode 100644
index 61e4df6..0000000
--- a/wpiutil/src/main/native/libuv/src/win/handle.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <io.h>
-#include <stdlib.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-
-
-uv_handle_type uv_guess_handle(uv_file file) {
-  HANDLE handle;
-  DWORD mode;
-
-  if (file < 0) {
-    return UV_UNKNOWN_HANDLE;
-  }
-
-  handle = uv__get_osfhandle(file);
-
-  switch (GetFileType(handle)) {
-    case FILE_TYPE_CHAR:
-      if (GetConsoleMode(handle, &mode)) {
-        return UV_TTY;
-      } else {
-        return UV_FILE;
-      }
-
-    case FILE_TYPE_PIPE:
-      return UV_NAMED_PIPE;
-
-    case FILE_TYPE_DISK:
-      return UV_FILE;
-
-    default:
-      return UV_UNKNOWN_HANDLE;
-  }
-}
-
-
-int uv_is_active(const uv_handle_t* handle) {
-  return (handle->flags & UV_HANDLE_ACTIVE) &&
-        !(handle->flags & UV_HANDLE_CLOSING);
-}
-
-
-void uv_close(uv_handle_t* handle, uv_close_cb cb) {
-  uv_loop_t* loop = handle->loop;
-
-  if (handle->flags & UV_HANDLE_CLOSING) {
-    assert(0);
-    return;
-  }
-
-  handle->close_cb = cb;
-
-  /* Handle-specific close actions */
-  switch (handle->type) {
-    case UV_TCP:
-      uv_tcp_close(loop, (uv_tcp_t*)handle);
-      return;
-
-    case UV_NAMED_PIPE:
-      uv_pipe_close(loop, (uv_pipe_t*) handle);
-      return;
-
-    case UV_TTY:
-      uv_tty_close((uv_tty_t*) handle);
-      return;
-
-    case UV_UDP:
-      uv_udp_close(loop, (uv_udp_t*) handle);
-      return;
-
-    case UV_POLL:
-      uv_poll_close(loop, (uv_poll_t*) handle);
-      return;
-
-    case UV_TIMER:
-      uv_timer_stop((uv_timer_t*)handle);
-      uv__handle_closing(handle);
-      uv_want_endgame(loop, handle);
-      return;
-
-    case UV_PREPARE:
-      uv_prepare_stop((uv_prepare_t*)handle);
-      uv__handle_closing(handle);
-      uv_want_endgame(loop, handle);
-      return;
-
-    case UV_CHECK:
-      uv_check_stop((uv_check_t*)handle);
-      uv__handle_closing(handle);
-      uv_want_endgame(loop, handle);
-      return;
-
-    case UV_IDLE:
-      uv_idle_stop((uv_idle_t*)handle);
-      uv__handle_closing(handle);
-      uv_want_endgame(loop, handle);
-      return;
-
-    case UV_ASYNC:
-      uv_async_close(loop, (uv_async_t*) handle);
-      return;
-
-    case UV_SIGNAL:
-      uv_signal_close(loop, (uv_signal_t*) handle);
-      return;
-
-    case UV_PROCESS:
-      uv_process_close(loop, (uv_process_t*) handle);
-      return;
-
-    case UV_FS_EVENT:
-      uv_fs_event_close(loop, (uv_fs_event_t*) handle);
-      return;
-
-    case UV_FS_POLL:
-      uv__fs_poll_close((uv_fs_poll_t*) handle);
-      uv__handle_closing(handle);
-      return;
-
-    default:
-      /* Not supported */
-      abort();
-  }
-}
-
-
-int uv_is_closing(const uv_handle_t* handle) {
-  return !!(handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED));
-}
-
-
-uv_os_fd_t uv_get_osfhandle(int fd) {
-  return uv__get_osfhandle(fd);
-}
-
-int uv_open_osfhandle(uv_os_fd_t os_fd) {
-  return _open_osfhandle((intptr_t) os_fd, 0);
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/internal.h b/wpiutil/src/main/native/libuv/src/win/internal.h
deleted file mode 100644
index 70ddaa5..0000000
--- a/wpiutil/src/main/native/libuv/src/win/internal.h
+++ /dev/null
@@ -1,342 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_WIN_INTERNAL_H_
-#define UV_WIN_INTERNAL_H_
-
-#include "uv.h"
-#include "../uv-common.h"
-
-#include "uv/tree.h"
-#include "winapi.h"
-#include "winsock.h"
-
-#ifdef _MSC_VER
-# define INLINE __inline
-# define UV_THREAD_LOCAL __declspec( thread )
-#else
-# define INLINE inline
-# define UV_THREAD_LOCAL __thread
-#endif
-
-
-#ifdef _DEBUG
-
-extern UV_THREAD_LOCAL int uv__crt_assert_enabled;
-
-#define UV_BEGIN_DISABLE_CRT_ASSERT()                           \
-  {                                                             \
-    int uv__saved_crt_assert_enabled = uv__crt_assert_enabled;  \
-    uv__crt_assert_enabled = FALSE;
-
-
-#define UV_END_DISABLE_CRT_ASSERT()                             \
-    uv__crt_assert_enabled = uv__saved_crt_assert_enabled;      \
-  }
-
-#else
-#define UV_BEGIN_DISABLE_CRT_ASSERT()
-#define UV_END_DISABLE_CRT_ASSERT()
-#endif
-
-/*
- * TCP
- */
-
-typedef enum {
-  UV__IPC_SOCKET_XFER_NONE = 0,
-  UV__IPC_SOCKET_XFER_TCP_CONNECTION,
-  UV__IPC_SOCKET_XFER_TCP_SERVER
-} uv__ipc_socket_xfer_type_t;
-
-typedef struct {
-  WSAPROTOCOL_INFOW socket_info;
-  uint32_t delayed_error;
-} uv__ipc_socket_xfer_info_t;
-
-int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);
-int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client);
-int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
-    uv_read_cb read_cb);
-int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
-    const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
-int uv__tcp_try_write(uv_tcp_t* handle, const uv_buf_t bufs[],
-    unsigned int nbufs);
-
-void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req);
-void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
-    uv_write_t* req);
-void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
-    uv_req_t* req);
-void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
-    uv_connect_t* req);
-
-void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp);
-void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle);
-
-int uv__tcp_xfer_export(uv_tcp_t* handle,
-                        int pid,
-                        uv__ipc_socket_xfer_type_t* xfer_type,
-                        uv__ipc_socket_xfer_info_t* xfer_info);
-int uv__tcp_xfer_import(uv_tcp_t* tcp,
-                        uv__ipc_socket_xfer_type_t xfer_type,
-                        uv__ipc_socket_xfer_info_t* xfer_info);
-
-
-/*
- * UDP
- */
-void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req);
-void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
-    uv_udp_send_t* req);
-
-void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle);
-void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle);
-
-
-/*
- * Pipes
- */
-int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
-    char* name, size_t nameSize);
-
-int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
-int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client);
-int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb,
-    uv_read_cb read_cb);
-void uv__pipe_read_stop(uv_pipe_t* handle);
-int uv__pipe_write(uv_loop_t* loop,
-                   uv_write_t* req,
-                   uv_pipe_t* handle,
-                   const uv_buf_t bufs[],
-                   size_t nbufs,
-                   uv_stream_t* send_handle,
-                   uv_write_cb cb);
-
-void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_req_t* req);
-void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_write_t* req);
-void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_req_t* raw_req);
-void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_connect_t* req);
-void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_shutdown_t* req);
-
-void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle);
-void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle);
-void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle);
-
-
-/*
- * TTY
- */
-void uv_console_init(void);
-
-int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
-    uv_read_cb read_cb);
-int uv_tty_read_stop(uv_tty_t* handle);
-int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle,
-    const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb);
-int uv__tty_try_write(uv_tty_t* handle, const uv_buf_t bufs[],
-    unsigned int nbufs);
-void uv_tty_close(uv_tty_t* handle);
-
-void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_req_t* req);
-void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_write_t* req);
-/*
- * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
- * TODO: find a way to remove it
- */
-void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_req_t* raw_req);
-/*
- * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
- * TODO: find a way to remove it
- */
-void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_connect_t* req);
-
-void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle);
-
-
-/*
- * Poll watchers
- */
-void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
-    uv_req_t* req);
-
-int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle);
-void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle);
-
-
-/*
- * Loop watchers
- */
-void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle);
-
-void uv_prepare_invoke(uv_loop_t* loop);
-void uv_check_invoke(uv_loop_t* loop);
-void uv_idle_invoke(uv_loop_t* loop);
-
-void uv__once_init(void);
-
-
-/*
- * Async watcher
- */
-void uv_async_close(uv_loop_t* loop, uv_async_t* handle);
-void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle);
-
-void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle,
-    uv_req_t* req);
-
-
-/*
- * Signal watcher
- */
-void uv_signals_init(void);
-int uv__signal_dispatch(int signum);
-
-void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle);
-void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle);
-
-void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
-    uv_req_t* req);
-
-
-/*
- * Spawn
- */
-void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle);
-void uv_process_close(uv_loop_t* loop, uv_process_t* handle);
-void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle);
-
-
-/*
- * Error
- */
-int uv_translate_sys_error(int sys_errno);
-
-
-/*
- * FS
- */
-void uv_fs_init(void);
-
-
-/*
- * FS Event
- */
-void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
-    uv_fs_event_t* handle);
-void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle);
-void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle);
-
-
-/*
- * Stat poller.
- */
-void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
-
-
-/*
- * Utilities.
- */
-void uv__util_init(void);
-
-uint64_t uv__hrtime(double scale);
-__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
-int uv__getpwuid_r(uv_passwd_t* pwd);
-int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
-int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
-
-typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);
-
-int uv__getsockpeername(const uv_handle_t* handle,
-                        uv__peersockfunc func,
-                        struct sockaddr* name,
-                        int* namelen,
-                        int delayed_error);
-
-
-/*
- * Process stdio handles.
- */
-int uv__stdio_create(uv_loop_t* loop,
-                     const uv_process_options_t* options,
-                     BYTE** buffer_ptr);
-void uv__stdio_destroy(BYTE* buffer);
-void uv__stdio_noinherit(BYTE* buffer);
-int uv__stdio_verify(BYTE* buffer, WORD size);
-WORD uv__stdio_size(BYTE* buffer);
-HANDLE uv__stdio_handle(BYTE* buffer, int fd);
-
-
-/*
- * Winapi and ntapi utility functions
- */
-void uv_winapi_init(void);
-
-
-/*
- * Winsock utility functions
- */
-void uv_winsock_init(void);
-
-int uv_ntstatus_to_winsock_error(NTSTATUS status);
-
-BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target);
-BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target);
-
-int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,
-    DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped,
-    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
-int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
-    DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr,
-    int* addr_len, WSAOVERLAPPED *overlapped,
-    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine);
-
-int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
-    AFD_POLL_INFO* info_out, OVERLAPPED* overlapped);
-
-/* Whether there are any non-IFS LSPs stacked on TCP */
-extern int uv_tcp_non_ifs_lsp_ipv4;
-extern int uv_tcp_non_ifs_lsp_ipv6;
-
-/* Ip address used to bind to any port at any interface */
-extern struct sockaddr_in uv_addr_ip4_any_;
-extern struct sockaddr_in6 uv_addr_ip6_any_;
-
-/*
- * Wake all loops with fake message
- */
-void uv__wake_all_loops(void);
-
-/*
- * Init system wake-up detection
- */
-void uv__init_detect_system_wakeup(void);
-
-#endif /* UV_WIN_INTERNAL_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/win/loop-watcher.cpp b/wpiutil/src/main/native/libuv/src/win/loop-watcher.cpp
deleted file mode 100644
index ad7fbea..0000000
--- a/wpiutil/src/main/native/libuv/src/win/loop-watcher.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-
-
-void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) {
-  if (handle->flags & UV_HANDLE_CLOSING) {
-    assert(!(handle->flags & UV_HANDLE_CLOSED));
-    handle->flags |= UV_HANDLE_CLOSED;
-    uv__handle_close(handle);
-  }
-}
-
-
-#define UV_LOOP_WATCHER_DEFINE(name, NAME)                                    \
-  int uv_##name##_init(uv_loop_t* loop, uv_##name##_t* handle) {              \
-    uv__handle_init(loop, (uv_handle_t*) handle, UV_##NAME);                  \
-                                                                              \
-    return 0;                                                                 \
-  }                                                                           \
-                                                                              \
-                                                                              \
-  int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) {           \
-    uv_loop_t* loop = handle->loop;                                           \
-    uv_##name##_t* old_head;                                                  \
-                                                                              \
-    assert(handle->type == UV_##NAME);                                        \
-                                                                              \
-    if (uv__is_active(handle))                                                \
-      return 0;                                                               \
-                                                                              \
-    if (cb == NULL)                                                           \
-      return UV_EINVAL;                                                       \
-                                                                              \
-    old_head = loop->name##_handles;                                          \
-                                                                              \
-    handle->name##_next = old_head;                                           \
-    handle->name##_prev = NULL;                                               \
-                                                                              \
-    if (old_head) {                                                           \
-      old_head->name##_prev = handle;                                         \
-    }                                                                         \
-                                                                              \
-    loop->name##_handles = handle;                                            \
-                                                                              \
-    handle->name##_cb = cb;                                                   \
-    uv__handle_start(handle);                                                 \
-                                                                              \
-    return 0;                                                                 \
-  }                                                                           \
-                                                                              \
-                                                                              \
-  int uv_##name##_stop(uv_##name##_t* handle) {                               \
-    uv_loop_t* loop = handle->loop;                                           \
-                                                                              \
-    assert(handle->type == UV_##NAME);                                        \
-                                                                              \
-    if (!uv__is_active(handle))                                               \
-      return 0;                                                               \
-                                                                              \
-    /* Update loop head if needed */                                          \
-    if (loop->name##_handles == handle) {                                     \
-      loop->name##_handles = handle->name##_next;                             \
-    }                                                                         \
-                                                                              \
-    /* Update the iterator-next pointer of needed */                          \
-    if (loop->next_##name##_handle == handle) {                               \
-      loop->next_##name##_handle = handle->name##_next;                       \
-    }                                                                         \
-                                                                              \
-    if (handle->name##_prev) {                                                \
-      handle->name##_prev->name##_next = handle->name##_next;                 \
-    }                                                                         \
-    if (handle->name##_next) {                                                \
-      handle->name##_next->name##_prev = handle->name##_prev;                 \
-    }                                                                         \
-                                                                              \
-    uv__handle_stop(handle);                                                  \
-                                                                              \
-    return 0;                                                                 \
-  }                                                                           \
-                                                                              \
-                                                                              \
-  void uv_##name##_invoke(uv_loop_t* loop) {                                  \
-    uv_##name##_t* handle;                                                    \
-                                                                              \
-    (loop)->next_##name##_handle = (loop)->name##_handles;                    \
-                                                                              \
-    while ((loop)->next_##name##_handle != NULL) {                            \
-      handle = (loop)->next_##name##_handle;                                  \
-      (loop)->next_##name##_handle = handle->name##_next;                     \
-                                                                              \
-      handle->name##_cb(handle);                                              \
-    }                                                                         \
-  }
-
-UV_LOOP_WATCHER_DEFINE(prepare, PREPARE)
-UV_LOOP_WATCHER_DEFINE(check, CHECK)
-UV_LOOP_WATCHER_DEFINE(idle, IDLE)
diff --git a/wpiutil/src/main/native/libuv/src/win/pipe.cpp b/wpiutil/src/main/native/libuv/src/win/pipe.cpp
deleted file mode 100644
index 0c03a06..0000000
--- a/wpiutil/src/main/native/libuv/src/win/pipe.cpp
+++ /dev/null
@@ -1,2388 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#define _CRT_NONSTDC_NO_WARNINGS
-
-#include <assert.h>
-#include <io.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "handle-inl.h"
-#include "internal.h"
-#include "req-inl.h"
-#include "stream-inl.h"
-#include "uv-common.h"
-#include "uv.h"
-
-#include <aclapi.h>
-#include <accctrl.h>
-
-/* A zero-size buffer for use by uv_pipe_read */
-static char uv_zero_[] = "";
-
-/* Null uv_buf_t */
-static const uv_buf_t uv_null_buf_ = { 0, NULL };
-
-/* The timeout that the pipe will wait for the remote end to write data when
- * the local ends wants to shut it down. */
-static const int64_t eof_timeout = 50; /* ms */
-
-static const int default_pending_pipe_instances = 4;
-
-/* Pipe prefix */
-static char pipe_prefix[] = "\\\\?\\pipe";
-static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
-
-/* IPC incoming xfer queue item. */
-typedef struct {
-  uv__ipc_socket_xfer_type_t xfer_type;
-  uv__ipc_socket_xfer_info_t xfer_info;
-  QUEUE member;
-} uv__ipc_xfer_queue_item_t;
-
-/* IPC frame header flags. */
-/* clang-format off */
-enum {
-  UV__IPC_FRAME_HAS_DATA                = 0x01,
-  UV__IPC_FRAME_HAS_SOCKET_XFER         = 0x02,
-  UV__IPC_FRAME_XFER_IS_TCP_CONNECTION  = 0x04,
-  /* These are combinations of the flags above. */
-  UV__IPC_FRAME_XFER_FLAGS              = 0x06,
-  UV__IPC_FRAME_VALID_FLAGS             = 0x07
-};
-/* clang-format on */
-
-/* IPC frame header. */
-typedef struct {
-  uint32_t flags;
-  uint32_t reserved1;   /* Ignored. */
-  uint32_t data_length; /* Must be zero if there is no data. */
-  uint32_t reserved2;   /* Must be zero. */
-} uv__ipc_frame_header_t;
-
-/* To implement the IPC protocol correctly, these structures must have exactly
- * the right size. */
-STATIC_ASSERT(sizeof(uv__ipc_frame_header_t) == 16);
-STATIC_ASSERT(sizeof(uv__ipc_socket_xfer_info_t) == 632);
-
-/* Coalesced write request. */
-typedef struct {
-  uv_write_t req;       /* Internal heap-allocated write request. */
-  uv_write_t* user_req; /* Pointer to user-specified uv_write_t. */
-} uv__coalesced_write_t;
-
-
-static void eof_timer_init(uv_pipe_t* pipe);
-static void eof_timer_start(uv_pipe_t* pipe);
-static void eof_timer_stop(uv_pipe_t* pipe);
-static void eof_timer_cb(uv_timer_t* timer);
-static void eof_timer_destroy(uv_pipe_t* pipe);
-static void eof_timer_close_cb(uv_handle_t* handle);
-
-
-static void uv_unique_pipe_name(char* ptr, char* name, size_t size) {
-  snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId());
-}
-
-
-int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
-  uv_stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
-
-  handle->reqs_pending = 0;
-  handle->handle = INVALID_HANDLE_VALUE;
-  handle->name = NULL;
-  handle->pipe.conn.ipc_remote_pid = 0;
-  handle->pipe.conn.ipc_data_frame.payload_remaining = 0;
-  QUEUE_INIT(&handle->pipe.conn.ipc_xfer_queue);
-  handle->pipe.conn.ipc_xfer_queue_length = 0;
-  handle->ipc = ipc;
-  handle->pipe.conn.non_overlapped_writes_tail = NULL;
-
-  return 0;
-}
-
-
-static void uv_pipe_connection_init(uv_pipe_t* handle) {
-  uv_connection_init((uv_stream_t*) handle);
-  handle->read_req.data = handle;
-  handle->pipe.conn.eof_timer = NULL;
-  assert(!(handle->flags & UV_HANDLE_PIPESERVER));
-  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
-    handle->pipe.conn.readfile_thread_handle = NULL;
-    InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock);
-  }
-}
-
-
-static HANDLE open_named_pipe(const WCHAR* name, DWORD* duplex_flags) {
-  HANDLE pipeHandle;
-
-  /*
-   * Assume that we have a duplex pipe first, so attempt to
-   * connect with GENERIC_READ | GENERIC_WRITE.
-   */
-  pipeHandle = CreateFileW(name,
-                           GENERIC_READ | GENERIC_WRITE,
-                           0,
-                           NULL,
-                           OPEN_EXISTING,
-                           FILE_FLAG_OVERLAPPED,
-                           NULL);
-  if (pipeHandle != INVALID_HANDLE_VALUE) {
-    *duplex_flags = UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
-    return pipeHandle;
-  }
-
-  /*
-   * If the pipe is not duplex CreateFileW fails with
-   * ERROR_ACCESS_DENIED.  In that case try to connect
-   * as a read-only or write-only.
-   */
-  if (GetLastError() == ERROR_ACCESS_DENIED) {
-    pipeHandle = CreateFileW(name,
-                             GENERIC_READ | FILE_WRITE_ATTRIBUTES,
-                             0,
-                             NULL,
-                             OPEN_EXISTING,
-                             FILE_FLAG_OVERLAPPED,
-                             NULL);
-
-    if (pipeHandle != INVALID_HANDLE_VALUE) {
-      *duplex_flags = UV_HANDLE_READABLE;
-      return pipeHandle;
-    }
-  }
-
-  if (GetLastError() == ERROR_ACCESS_DENIED) {
-    pipeHandle = CreateFileW(name,
-                             GENERIC_WRITE | FILE_READ_ATTRIBUTES,
-                             0,
-                             NULL,
-                             OPEN_EXISTING,
-                             FILE_FLAG_OVERLAPPED,
-                             NULL);
-
-    if (pipeHandle != INVALID_HANDLE_VALUE) {
-      *duplex_flags = UV_HANDLE_WRITABLE;
-      return pipeHandle;
-    }
-  }
-
-  return INVALID_HANDLE_VALUE;
-}
-
-
-static void close_pipe(uv_pipe_t* pipe) {
-  assert(pipe->u.fd == -1 || pipe->u.fd > 2);
-  if (pipe->u.fd == -1)
-    CloseHandle(pipe->handle);
-  else
-    close(pipe->u.fd);
-
-  pipe->u.fd = -1;
-  pipe->handle = INVALID_HANDLE_VALUE;
-}
-
-
-int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
-    char* name, size_t nameSize) {
-  HANDLE pipeHandle;
-  int err;
-  char* ptr = (char*)handle;
-
-  for (;;) {
-    uv_unique_pipe_name(ptr, name, nameSize);
-
-    pipeHandle = CreateNamedPipeA(name,
-      access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
-      PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0,
-      NULL);
-
-    if (pipeHandle != INVALID_HANDLE_VALUE) {
-      /* No name collisions.  We're done. */
-      break;
-    }
-
-    err = GetLastError();
-    if (err != ERROR_PIPE_BUSY && err != ERROR_ACCESS_DENIED) {
-      goto error;
-    }
-
-    /* Pipe name collision.  Increment the pointer and try again. */
-    ptr++;
-  }
-
-  if (CreateIoCompletionPort(pipeHandle,
-                             loop->iocp,
-                             (ULONG_PTR)handle,
-                             0) == NULL) {
-    err = GetLastError();
-    goto error;
-  }
-
-  uv_pipe_connection_init(handle);
-  handle->handle = pipeHandle;
-
-  return 0;
-
- error:
-  if (pipeHandle != INVALID_HANDLE_VALUE) {
-    CloseHandle(pipeHandle);
-  }
-
-  return err;
-}
-
-
-static int uv_set_pipe_handle(uv_loop_t* loop,
-                              uv_pipe_t* handle,
-                              HANDLE pipeHandle,
-                              int fd,
-                              DWORD duplex_flags) {
-  NTSTATUS nt_status;
-  IO_STATUS_BLOCK io_status;
-  FILE_MODE_INFORMATION mode_info;
-  DWORD mode = PIPE_READMODE_BYTE | PIPE_WAIT;
-  DWORD current_mode = 0;
-  DWORD err = 0;
-
-  if (!(handle->flags & UV_HANDLE_PIPESERVER) &&
-      handle->handle != INVALID_HANDLE_VALUE)
-    return UV_EBUSY;
-
-  if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
-    err = GetLastError();
-    if (err == ERROR_ACCESS_DENIED) {
-      /*
-       * SetNamedPipeHandleState can fail if the handle doesn't have either
-       * GENERIC_WRITE  or FILE_WRITE_ATTRIBUTES.
-       * But if the handle already has the desired wait and blocking modes
-       * we can continue.
-       */
-      if (!GetNamedPipeHandleState(pipeHandle, &current_mode, NULL, NULL,
-                                   NULL, NULL, 0)) {
-        return -1;
-      } else if (current_mode & PIPE_NOWAIT) {
-        SetLastError(ERROR_ACCESS_DENIED);
-        return -1;
-      }
-    } else {
-      /* If this returns ERROR_INVALID_PARAMETER we probably opened
-       * something that is not a pipe. */
-      if (err == ERROR_INVALID_PARAMETER) {
-        SetLastError(WSAENOTSOCK);
-      }
-      return -1;
-    }
-  }
-
-  /* Check if the pipe was created with FILE_FLAG_OVERLAPPED. */
-  nt_status = pNtQueryInformationFile(pipeHandle,
-                                      &io_status,
-                                      &mode_info,
-                                      sizeof(mode_info),
-                                      FileModeInformation);
-  if (nt_status != STATUS_SUCCESS) {
-    return -1;
-  }
-
-  if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT ||
-      mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) {
-    /* Non-overlapped pipe. */
-    handle->flags |= UV_HANDLE_NON_OVERLAPPED_PIPE;
-  } else {
-    /* Overlapped pipe.  Try to associate with IOCP. */
-    if (CreateIoCompletionPort(pipeHandle,
-                               loop->iocp,
-                               (ULONG_PTR)handle,
-                               0) == NULL) {
-      handle->flags |= UV_HANDLE_EMULATE_IOCP;
-    }
-  }
-
-  handle->handle = pipeHandle;
-  handle->u.fd = fd;
-  handle->flags |= duplex_flags;
-
-  return 0;
-}
-
-
-static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) {
-  uv_loop_t* loop;
-  uv_pipe_t* handle;
-  uv_shutdown_t* req;
-
-  req = (uv_shutdown_t*) parameter;
-  assert(req);
-  handle = (uv_pipe_t*) req->handle;
-  assert(handle);
-  loop = handle->loop;
-  assert(loop);
-
-  FlushFileBuffers(handle->handle);
-
-  /* Post completed */
-  POST_COMPLETION_FOR_REQ(loop, req);
-
-  return 0;
-}
-
-
-void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) {
-  int err;
-  DWORD result;
-  uv_shutdown_t* req;
-  NTSTATUS nt_status;
-  IO_STATUS_BLOCK io_status;
-  FILE_PIPE_LOCAL_INFORMATION pipe_info;
-  uv__ipc_xfer_queue_item_t* xfer_queue_item;
-
-  if ((handle->flags & UV_HANDLE_CONNECTION) &&
-      handle->stream.conn.shutdown_req != NULL &&
-      handle->stream.conn.write_reqs_pending == 0) {
-    req = handle->stream.conn.shutdown_req;
-
-    /* Clear the shutdown_req field so we don't go here again. */
-    handle->stream.conn.shutdown_req = NULL;
-
-    if (handle->flags & UV_HANDLE_CLOSING) {
-      UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-      /* Already closing. Cancel the shutdown. */
-      if (req->cb) {
-        req->cb(req, UV_ECANCELED);
-      }
-
-      DECREASE_PENDING_REQ_COUNT(handle);
-      return;
-    }
-
-    /* Try to avoid flushing the pipe buffer in the thread pool. */
-    nt_status = pNtQueryInformationFile(handle->handle,
-                                        &io_status,
-                                        &pipe_info,
-                                        sizeof pipe_info,
-                                        FilePipeLocalInformation);
-
-    if (nt_status != STATUS_SUCCESS) {
-      /* Failure */
-      UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-      handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */
-      if (req->cb) {
-        err = pRtlNtStatusToDosError(nt_status);
-        req->cb(req, uv_translate_sys_error(err));
-      }
-
-      DECREASE_PENDING_REQ_COUNT(handle);
-      return;
-    }
-
-    if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) {
-      /* Short-circuit, no need to call FlushFileBuffers. */
-      uv_insert_pending_req(loop, (uv_req_t*) req);
-      return;
-    }
-
-    /* Run FlushFileBuffers in the thread pool. */
-    result = QueueUserWorkItem(pipe_shutdown_thread_proc,
-                               req,
-                               WT_EXECUTELONGFUNCTION);
-    if (result) {
-      return;
-
-    } else {
-      /* Failure. */
-      UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-      handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */
-      if (req->cb) {
-        err = GetLastError();
-        req->cb(req, uv_translate_sys_error(err));
-      }
-
-      DECREASE_PENDING_REQ_COUNT(handle);
-      return;
-    }
-  }
-
-  if (handle->flags & UV_HANDLE_CLOSING &&
-      handle->reqs_pending == 0) {
-    assert(!(handle->flags & UV_HANDLE_CLOSED));
-
-    if (handle->flags & UV_HANDLE_CONNECTION) {
-      /* Free pending sockets */
-      while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) {
-        QUEUE* q;
-        SOCKET socket;
-
-        q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue);
-        QUEUE_REMOVE(q);
-        xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
-
-        /* Materialize socket and close it */
-        socket = WSASocketW(FROM_PROTOCOL_INFO,
-                            FROM_PROTOCOL_INFO,
-                            FROM_PROTOCOL_INFO,
-                            &xfer_queue_item->xfer_info.socket_info,
-                            0,
-                            WSA_FLAG_OVERLAPPED);
-        uv__free(xfer_queue_item);
-
-        if (socket != INVALID_SOCKET)
-          closesocket(socket);
-      }
-      handle->pipe.conn.ipc_xfer_queue_length = 0;
-
-      if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-        if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
-          UnregisterWait(handle->read_req.wait_handle);
-          handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
-        }
-        if (handle->read_req.event_handle) {
-          CloseHandle(handle->read_req.event_handle);
-          handle->read_req.event_handle = NULL;
-        }
-      }
-
-      if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)
-        DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock);
-    }
-
-    if (handle->flags & UV_HANDLE_PIPESERVER) {
-      assert(handle->pipe.serv.accept_reqs);
-      uv__free(handle->pipe.serv.accept_reqs);
-      handle->pipe.serv.accept_reqs = NULL;
-    }
-
-    uv__handle_close(handle);
-  }
-}
-
-
-void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
-  if (handle->flags & UV_HANDLE_BOUND)
-    return;
-  handle->pipe.serv.pending_instances = count;
-  handle->flags |= UV_HANDLE_PIPESERVER;
-}
-
-
-/* Creates a pipe server. */
-int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
-  uv_loop_t* loop = handle->loop;
-  int i, err, nameSize;
-  uv_pipe_accept_t* req;
-
-  if (handle->flags & UV_HANDLE_BOUND) {
-    return UV_EINVAL;
-  }
-
-  if (!name) {
-    return UV_EINVAL;
-  }
-
-  if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
-    handle->pipe.serv.pending_instances = default_pending_pipe_instances;
-  }
-
-  handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*)
-    uv__malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances);
-  if (!handle->pipe.serv.accept_reqs) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
-    req = &handle->pipe.serv.accept_reqs[i];
-    UV_REQ_INIT(req, UV_ACCEPT);
-    req->data = handle;
-    req->pipeHandle = INVALID_HANDLE_VALUE;
-    req->next_pending = NULL;
-  }
-
-  /* Convert name to UTF16. */
-  nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
-  handle->name = (WCHAR*)uv__malloc(nameSize);
-  if (!handle->name) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  if (!MultiByteToWideChar(CP_UTF8,
-                           0,
-                           name,
-                           -1,
-                           handle->name,
-                           nameSize / sizeof(WCHAR))) {
-    err = GetLastError();
-    goto error;
-  }
-
-  /*
-   * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
-   * If this fails then there's already a pipe server for the given pipe name.
-   */
-  handle->pipe.serv.accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
-      PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
-      FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
-      PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
-      PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
-
-  if (handle->pipe.serv.accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) {
-    err = GetLastError();
-    if (err == ERROR_ACCESS_DENIED) {
-      err = WSAEADDRINUSE;  /* Translates to UV_EADDRINUSE. */
-    } else if (err == ERROR_PATH_NOT_FOUND || err == ERROR_INVALID_NAME) {
-      err = WSAEACCES;  /* Translates to UV_EACCES. */
-    }
-    goto error;
-  }
-
-  if (uv_set_pipe_handle(loop,
-                         handle,
-                         handle->pipe.serv.accept_reqs[0].pipeHandle,
-                         -1,
-                         0)) {
-    err = GetLastError();
-    goto error;
-  }
-
-  handle->pipe.serv.pending_accepts = NULL;
-  handle->flags |= UV_HANDLE_PIPESERVER;
-  handle->flags |= UV_HANDLE_BOUND;
-
-  return 0;
-
-error:
-  if (handle->name) {
-    uv__free(handle->name);
-    handle->name = NULL;
-  }
-
-  if (handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) {
-    CloseHandle(handle->pipe.serv.accept_reqs[0].pipeHandle);
-    handle->pipe.serv.accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE;
-  }
-
-  return uv_translate_sys_error(err);
-}
-
-
-static DWORD WINAPI pipe_connect_thread_proc(void* parameter) {
-  uv_loop_t* loop;
-  uv_pipe_t* handle;
-  uv_connect_t* req;
-  HANDLE pipeHandle = INVALID_HANDLE_VALUE;
-  DWORD duplex_flags;
-
-  req = (uv_connect_t*) parameter;
-  assert(req);
-  handle = (uv_pipe_t*) req->handle;
-  assert(handle);
-  loop = handle->loop;
-  assert(loop);
-
-  /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait
-   * for the pipe to become available with WaitNamedPipe. */
-  while (WaitNamedPipeW(handle->name, 30000)) {
-    /* The pipe is now available, try to connect. */
-    pipeHandle = open_named_pipe(handle->name, &duplex_flags);
-    if (pipeHandle != INVALID_HANDLE_VALUE) {
-      break;
-    }
-
-    SwitchToThread();
-  }
-
-  if (pipeHandle != INVALID_HANDLE_VALUE &&
-      !uv_set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) {
-    SET_REQ_SUCCESS(req);
-  } else {
-    SET_REQ_ERROR(req, GetLastError());
-  }
-
-  /* Post completed */
-  POST_COMPLETION_FOR_REQ(loop, req);
-
-  return 0;
-}
-
-
-void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
-    const char* name, uv_connect_cb cb) {
-  uv_loop_t* loop = handle->loop;
-  int err, nameSize;
-  HANDLE pipeHandle = INVALID_HANDLE_VALUE;
-  DWORD duplex_flags;
-
-  UV_REQ_INIT(req, UV_CONNECT);
-  req->handle = (uv_stream_t*) handle;
-  req->cb = cb;
-
-  /* Convert name to UTF16. */
-  nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
-  handle->name = (WCHAR*)uv__malloc(nameSize);
-  if (!handle->name) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  if (!MultiByteToWideChar(CP_UTF8,
-                           0,
-                           name,
-                           -1,
-                           handle->name,
-                           nameSize / sizeof(WCHAR))) {
-    err = GetLastError();
-    goto error;
-  }
-
-  pipeHandle = open_named_pipe(handle->name, &duplex_flags);
-  if (pipeHandle == INVALID_HANDLE_VALUE) {
-    if (GetLastError() == ERROR_PIPE_BUSY) {
-      /* Wait for the server to make a pipe instance available. */
-      if (!QueueUserWorkItem(&pipe_connect_thread_proc,
-                             req,
-                             WT_EXECUTELONGFUNCTION)) {
-        err = GetLastError();
-        goto error;
-      }
-
-      REGISTER_HANDLE_REQ(loop, handle, req);
-      handle->reqs_pending++;
-
-      return;
-    }
-
-    err = GetLastError();
-    goto error;
-  }
-
-  assert(pipeHandle != INVALID_HANDLE_VALUE);
-
-  if (uv_set_pipe_handle(loop,
-                         (uv_pipe_t*) req->handle,
-                         pipeHandle,
-                         -1,
-                         duplex_flags)) {
-    err = GetLastError();
-    goto error;
-  }
-
-  SET_REQ_SUCCESS(req);
-  uv_insert_pending_req(loop, (uv_req_t*) req);
-  handle->reqs_pending++;
-  REGISTER_HANDLE_REQ(loop, handle, req);
-  return;
-
-error:
-  if (handle->name) {
-    uv__free(handle->name);
-    handle->name = NULL;
-  }
-
-  if (pipeHandle != INVALID_HANDLE_VALUE) {
-    CloseHandle(pipeHandle);
-  }
-
-  /* Make this req pending reporting an error. */
-  SET_REQ_ERROR(req, err);
-  uv_insert_pending_req(loop, (uv_req_t*) req);
-  handle->reqs_pending++;
-  REGISTER_HANDLE_REQ(loop, handle, req);
-  return;
-}
-
-
-void uv__pipe_interrupt_read(uv_pipe_t* handle) {
-  BOOL r;
-
-  if (!(handle->flags & UV_HANDLE_READ_PENDING))
-    return; /* No pending reads. */
-  if (handle->flags & UV_HANDLE_CANCELLATION_PENDING)
-    return; /* Already cancelled. */
-  if (handle->handle == INVALID_HANDLE_VALUE)
-    return; /* Pipe handle closed. */
-
-  if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) {
-    /* Cancel asynchronous read. */
-    r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
-    assert(r || GetLastError() == ERROR_NOT_FOUND);
-
-  } else {
-    /* Cancel synchronous read (which is happening in the thread pool). */
-    HANDLE thread;
-    volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
-
-    EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock);
-
-    thread = *thread_ptr;
-    if (thread == NULL) {
-      /* The thread pool thread has not yet reached the point of blocking, we
-       * can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */
-      *thread_ptr = INVALID_HANDLE_VALUE;
-
-    } else {
-      /* Spin until the thread has acknowledged (by setting the thread to
-       * INVALID_HANDLE_VALUE) that it is past the point of blocking. */
-      while (thread != INVALID_HANDLE_VALUE) {
-        r = CancelSynchronousIo(thread);
-        assert(r || GetLastError() == ERROR_NOT_FOUND);
-        SwitchToThread(); /* Yield thread. */
-        thread = *thread_ptr;
-      }
-    }
-
-    LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock);
-  }
-
-  /* Set flag to indicate that read has been cancelled. */
-  handle->flags |= UV_HANDLE_CANCELLATION_PENDING;
-}
-
-
-void uv__pipe_read_stop(uv_pipe_t* handle) {
-  handle->flags &= ~UV_HANDLE_READING;
-  DECREASE_ACTIVE_COUNT(handle->loop, handle);
-
-  uv__pipe_interrupt_read(handle);
-}
-
-
-/* Cleans up uv_pipe_t (server or connection) and all resources associated with
- * it. */
-void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) {
-  int i;
-  HANDLE pipeHandle;
-
-  uv__pipe_interrupt_read(handle);
-
-  if (handle->name) {
-    uv__free(handle->name);
-    handle->name = NULL;
-  }
-
-  if (handle->flags & UV_HANDLE_PIPESERVER) {
-    for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
-      pipeHandle = handle->pipe.serv.accept_reqs[i].pipeHandle;
-      if (pipeHandle != INVALID_HANDLE_VALUE) {
-        CloseHandle(pipeHandle);
-        handle->pipe.serv.accept_reqs[i].pipeHandle = INVALID_HANDLE_VALUE;
-      }
-    }
-    handle->handle = INVALID_HANDLE_VALUE;
-  }
-
-  if (handle->flags & UV_HANDLE_CONNECTION) {
-    handle->flags &= ~UV_HANDLE_WRITABLE;
-    eof_timer_destroy(handle);
-  }
-
-  if ((handle->flags & UV_HANDLE_CONNECTION)
-      && handle->handle != INVALID_HANDLE_VALUE)
-    close_pipe(handle);
-}
-
-
-void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {
-  if (handle->flags & UV_HANDLE_READING) {
-    handle->flags &= ~UV_HANDLE_READING;
-    DECREASE_ACTIVE_COUNT(loop, handle);
-  }
-
-  if (handle->flags & UV_HANDLE_LISTENING) {
-    handle->flags &= ~UV_HANDLE_LISTENING;
-    DECREASE_ACTIVE_COUNT(loop, handle);
-  }
-
-  uv_pipe_cleanup(loop, handle);
-
-  if (handle->reqs_pending == 0) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-  }
-
-  handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
-  uv__handle_closing(handle);
-}
-
-
-static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_pipe_accept_t* req, BOOL firstInstance) {
-  assert(handle->flags & UV_HANDLE_LISTENING);
-
-  if (!firstInstance) {
-    assert(req->pipeHandle == INVALID_HANDLE_VALUE);
-
-    req->pipeHandle = CreateNamedPipeW(handle->name,
-        PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC,
-        PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
-        PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
-
-    if (req->pipeHandle == INVALID_HANDLE_VALUE) {
-      SET_REQ_ERROR(req, GetLastError());
-      uv_insert_pending_req(loop, (uv_req_t*) req);
-      handle->reqs_pending++;
-      return;
-    }
-
-    if (uv_set_pipe_handle(loop, handle, req->pipeHandle, -1, 0)) {
-      CloseHandle(req->pipeHandle);
-      req->pipeHandle = INVALID_HANDLE_VALUE;
-      SET_REQ_ERROR(req, GetLastError());
-      uv_insert_pending_req(loop, (uv_req_t*) req);
-      handle->reqs_pending++;
-      return;
-    }
-  }
-
-  assert(req->pipeHandle != INVALID_HANDLE_VALUE);
-
-  /* Prepare the overlapped structure. */
-  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
-
-  if (!ConnectNamedPipe(req->pipeHandle, &req->u.io.overlapped) &&
-      GetLastError() != ERROR_IO_PENDING) {
-    if (GetLastError() == ERROR_PIPE_CONNECTED) {
-      SET_REQ_SUCCESS(req);
-    } else {
-      CloseHandle(req->pipeHandle);
-      req->pipeHandle = INVALID_HANDLE_VALUE;
-      /* Make this req pending reporting an error. */
-      SET_REQ_ERROR(req, GetLastError());
-    }
-    uv_insert_pending_req(loop, (uv_req_t*) req);
-    handle->reqs_pending++;
-    return;
-  }
-
-  /* Wait for completion via IOCP */
-  handle->reqs_pending++;
-}
-
-
-int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
-  uv_loop_t* loop = server->loop;
-  uv_pipe_t* pipe_client;
-  uv_pipe_accept_t* req;
-  QUEUE* q;
-  uv__ipc_xfer_queue_item_t* item;
-  int err;
-
-  if (server->ipc) {
-    if (QUEUE_EMPTY(&server->pipe.conn.ipc_xfer_queue)) {
-      /* No valid pending sockets. */
-      return WSAEWOULDBLOCK;
-    }
-
-    q = QUEUE_HEAD(&server->pipe.conn.ipc_xfer_queue);
-    QUEUE_REMOVE(q);
-    server->pipe.conn.ipc_xfer_queue_length--;
-    item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member);
-
-    err = uv__tcp_xfer_import(
-        (uv_tcp_t*) client, item->xfer_type, &item->xfer_info);
-    if (err != 0)
-      return err;
-
-    uv__free(item);
-
-  } else {
-    pipe_client = (uv_pipe_t*)client;
-
-    /* Find a connection instance that has been connected, but not yet
-     * accepted. */
-    req = server->pipe.serv.pending_accepts;
-
-    if (!req) {
-      /* No valid connections found, so we error out. */
-      return WSAEWOULDBLOCK;
-    }
-
-    /* Initialize the client handle and copy the pipeHandle to the client */
-    uv_pipe_connection_init(pipe_client);
-    pipe_client->handle = req->pipeHandle;
-    pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
-
-    /* Prepare the req to pick up a new connection */
-    server->pipe.serv.pending_accepts = req->next_pending;
-    req->next_pending = NULL;
-    req->pipeHandle = INVALID_HANDLE_VALUE;
-
-    if (!(server->flags & UV_HANDLE_CLOSING)) {
-      uv_pipe_queue_accept(loop, server, req, FALSE);
-    }
-  }
-
-  return 0;
-}
-
-
-/* Starts listening for connections for the given pipe. */
-int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
-  uv_loop_t* loop = handle->loop;
-  int i;
-
-  if (handle->flags & UV_HANDLE_LISTENING) {
-    handle->stream.serv.connection_cb = cb;
-  }
-
-  if (!(handle->flags & UV_HANDLE_BOUND)) {
-    return WSAEINVAL;
-  }
-
-  if (handle->flags & UV_HANDLE_READING) {
-    return WSAEISCONN;
-  }
-
-  if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
-    return ERROR_NOT_SUPPORTED;
-  }
-
-  handle->flags |= UV_HANDLE_LISTENING;
-  INCREASE_ACTIVE_COUNT(loop, handle);
-  handle->stream.serv.connection_cb = cb;
-
-  /* First pipe handle should have already been created in uv_pipe_bind */
-  assert(handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE);
-
-  for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
-    uv_pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0);
-  }
-
-  return 0;
-}
-
-
-static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* arg) {
-  uv_read_t* req = (uv_read_t*) arg;
-  uv_pipe_t* handle = (uv_pipe_t*) req->data;
-  uv_loop_t* loop = handle->loop;
-  volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle;
-  CRITICAL_SECTION* lock = &handle->pipe.conn.readfile_thread_lock;
-  HANDLE thread;
-  DWORD bytes;
-  DWORD err;
-
-  assert(req->type == UV_READ);
-  assert(handle->type == UV_NAMED_PIPE);
-
-  err = 0;
-
-  /* Create a handle to the current thread. */
-  if (!DuplicateHandle(GetCurrentProcess(),
-                       GetCurrentThread(),
-                       GetCurrentProcess(),
-                       &thread,
-                       0,
-                       FALSE,
-                       DUPLICATE_SAME_ACCESS)) {
-    err = GetLastError();
-    goto out1;
-  }
-
-  /* The lock needs to be held when thread handle is modified. */
-  EnterCriticalSection(lock);
-  if (*thread_ptr == INVALID_HANDLE_VALUE) {
-    /* uv__pipe_interrupt_read() cancelled reading before we got here. */
-    err = ERROR_OPERATION_ABORTED;
-  } else {
-    /* Let main thread know which worker thread is doing the blocking read. */
-    assert(*thread_ptr == NULL);
-    *thread_ptr = thread;
-  }
-  LeaveCriticalSection(lock);
-
-  if (err)
-    goto out2;
-
-  /* Block the thread until data is available on the pipe, or the read is
-   * cancelled. */
-  if (!ReadFile(handle->handle, &uv_zero_, 0, &bytes, NULL))
-    err = GetLastError();
-
-  /* Let the main thread know the worker is past the point of blocking. */
-  assert(thread == *thread_ptr);
-  *thread_ptr = INVALID_HANDLE_VALUE;
-
-  /* Briefly acquire the mutex. Since the main thread holds the lock while it
-   * is spinning trying to cancel this thread's I/O, we will block here until
-   * it stops doing that. */
-  EnterCriticalSection(lock);
-  LeaveCriticalSection(lock);
-
-out2:
-  /* Close the handle to the current thread. */
-  CloseHandle(thread);
-
-out1:
-  /* Set request status and post a completion record to the IOCP. */
-  if (err)
-    SET_REQ_ERROR(req, err);
-  else
-    SET_REQ_SUCCESS(req);
-  POST_COMPLETION_FOR_REQ(loop, req);
-
-  return 0;
-}
-
-
-static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) {
-  int result;
-  DWORD bytes;
-  uv_write_t* req = (uv_write_t*) parameter;
-  uv_pipe_t* handle = (uv_pipe_t*) req->handle;
-  uv_loop_t* loop = handle->loop;
-
-  assert(req != NULL);
-  assert(req->type == UV_WRITE);
-  assert(handle->type == UV_NAMED_PIPE);
-  assert(req->write_buffer.base);
-
-  result = WriteFile(handle->handle,
-                     req->write_buffer.base,
-                     req->write_buffer.len,
-                     &bytes,
-                     NULL);
-
-  if (!result) {
-    SET_REQ_ERROR(req, GetLastError());
-  }
-
-  POST_COMPLETION_FOR_REQ(loop, req);
-  return 0;
-}
-
-
-static void CALLBACK post_completion_read_wait(void* context, BOOLEAN timed_out) {
-  uv_read_t* req;
-  uv_tcp_t* handle;
-
-  req = (uv_read_t*) context;
-  assert(req != NULL);
-  handle = (uv_tcp_t*)req->data;
-  assert(handle != NULL);
-  assert(!timed_out);
-
-  if (!PostQueuedCompletionStatus(handle->loop->iocp,
-                                  req->u.io.overlapped.InternalHigh,
-                                  0,
-                                  &req->u.io.overlapped)) {
-    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
-  }
-}
-
-
-static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out) {
-  uv_write_t* req;
-  uv_tcp_t* handle;
-
-  req = (uv_write_t*) context;
-  assert(req != NULL);
-  handle = (uv_tcp_t*)req->handle;
-  assert(handle != NULL);
-  assert(!timed_out);
-
-  if (!PostQueuedCompletionStatus(handle->loop->iocp,
-                                  req->u.io.overlapped.InternalHigh,
-                                  0,
-                                  &req->u.io.overlapped)) {
-    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
-  }
-}
-
-
-static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) {
-  uv_read_t* req;
-  int result;
-
-  assert(handle->flags & UV_HANDLE_READING);
-  assert(!(handle->flags & UV_HANDLE_READ_PENDING));
-
-  assert(handle->handle != INVALID_HANDLE_VALUE);
-
-  req = &handle->read_req;
-
-  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
-    handle->pipe.conn.readfile_thread_handle = NULL; /* Reset cancellation. */
-    if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc,
-                           req,
-                           WT_EXECUTELONGFUNCTION)) {
-      /* Make this req pending reporting an error. */
-      SET_REQ_ERROR(req, GetLastError());
-      goto error;
-    }
-  } else {
-    memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-      req->u.io.overlapped.hEvent = (HANDLE) ((uintptr_t) req->event_handle | 1);
-    }
-
-    /* Do 0-read */
-    result = ReadFile(handle->handle,
-                      &uv_zero_,
-                      0,
-                      NULL,
-                      &req->u.io.overlapped);
-
-    if (!result && GetLastError() != ERROR_IO_PENDING) {
-      /* Make this req pending reporting an error. */
-      SET_REQ_ERROR(req, GetLastError());
-      goto error;
-    }
-
-    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-      if (!req->event_handle) {
-        req->event_handle = CreateEvent(NULL, 0, 0, NULL);
-        if (!req->event_handle) {
-          uv_fatal_error(GetLastError(), "CreateEvent");
-        }
-      }
-      if (req->wait_handle == INVALID_HANDLE_VALUE) {
-        if (!RegisterWaitForSingleObject(&req->wait_handle,
-            req->u.io.overlapped.hEvent, post_completion_read_wait, (void*) req,
-            INFINITE, WT_EXECUTEINWAITTHREAD)) {
-          SET_REQ_ERROR(req, GetLastError());
-          goto error;
-        }
-      }
-    }
-  }
-
-  /* Start the eof timer if there is one */
-  eof_timer_start(handle);
-  handle->flags |= UV_HANDLE_READ_PENDING;
-  handle->reqs_pending++;
-  return;
-
-error:
-  uv_insert_pending_req(loop, (uv_req_t*)req);
-  handle->flags |= UV_HANDLE_READ_PENDING;
-  handle->reqs_pending++;
-}
-
-
-int uv_pipe_read_start(uv_pipe_t* handle,
-                       uv_alloc_cb alloc_cb,
-                       uv_read_cb read_cb) {
-  uv_loop_t* loop = handle->loop;
-
-  handle->flags |= UV_HANDLE_READING;
-  INCREASE_ACTIVE_COUNT(loop, handle);
-  handle->read_cb = read_cb;
-  handle->alloc_cb = alloc_cb;
-
-  /* If reading was stopped and then started again, there could still be a read
-   * request pending. */
-  if (!(handle->flags & UV_HANDLE_READ_PENDING))
-    uv_pipe_queue_read(loop, handle);
-
-  return 0;
-}
-
-
-static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle,
-    uv_write_t* req) {
-  req->next_req = NULL;
-  if (handle->pipe.conn.non_overlapped_writes_tail) {
-    req->next_req =
-      handle->pipe.conn.non_overlapped_writes_tail->next_req;
-    handle->pipe.conn.non_overlapped_writes_tail->next_req = (uv_req_t*)req;
-    handle->pipe.conn.non_overlapped_writes_tail = req;
-  } else {
-    req->next_req = (uv_req_t*)req;
-    handle->pipe.conn.non_overlapped_writes_tail = req;
-  }
-}
-
-
-static uv_write_t* uv_remove_non_overlapped_write_req(uv_pipe_t* handle) {
-  uv_write_t* req;
-
-  if (handle->pipe.conn.non_overlapped_writes_tail) {
-    req = (uv_write_t*)handle->pipe.conn.non_overlapped_writes_tail->next_req;
-
-    if (req == handle->pipe.conn.non_overlapped_writes_tail) {
-      handle->pipe.conn.non_overlapped_writes_tail = NULL;
-    } else {
-      handle->pipe.conn.non_overlapped_writes_tail->next_req =
-        req->next_req;
-    }
-
-    return req;
-  } else {
-    /* queue empty */
-    return NULL;
-  }
-}
-
-
-static void uv_queue_non_overlapped_write(uv_pipe_t* handle) {
-  uv_write_t* req = uv_remove_non_overlapped_write_req(handle);
-  if (req) {
-    if (!QueueUserWorkItem(&uv_pipe_writefile_thread_proc,
-                           req,
-                           WT_EXECUTELONGFUNCTION)) {
-      uv_fatal_error(GetLastError(), "QueueUserWorkItem");
-    }
-  }
-}
-
-
-static int uv__build_coalesced_write_req(uv_write_t* user_req,
-                                         const uv_buf_t bufs[],
-                                         size_t nbufs,
-                                         uv_write_t** req_out,
-                                         uv_buf_t* write_buf_out) {
-  /* Pack into a single heap-allocated buffer:
-   *   (a) a uv_write_t structure where libuv stores the actual state.
-   *   (b) a pointer to the original uv_write_t.
-   *   (c) data from all `bufs` entries.
-   */
-  char* heap_buffer;
-  size_t heap_buffer_length, heap_buffer_offset;
-  uv__coalesced_write_t* coalesced_write_req; /* (a) + (b) */
-  char* data_start;                           /* (c) */
-  size_t data_length;
-  unsigned int i;
-
-  /* Compute combined size of all combined buffers from `bufs`. */
-  data_length = 0;
-  for (i = 0; i < nbufs; i++)
-    data_length += bufs[i].len;
-
-  /* The total combined size of data buffers should not exceed UINT32_MAX,
-   * because WriteFile() won't accept buffers larger than that. */
-  if (data_length > UINT32_MAX)
-    return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
-
-  /* Compute heap buffer size. */
-  heap_buffer_length = sizeof *coalesced_write_req + /* (a) + (b) */
-                       data_length;                  /* (c) */
-
-  /* Allocate buffer. */
-  heap_buffer = (char*)uv__malloc(heap_buffer_length);
-  if (heap_buffer == NULL)
-    return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */
-
-  /* Copy uv_write_t information to the buffer. */
-  coalesced_write_req = (uv__coalesced_write_t*) heap_buffer;
-  coalesced_write_req->req = *user_req; /* copy (a) */
-  coalesced_write_req->req.coalesced = 1;
-  coalesced_write_req->user_req = user_req;         /* copy (b) */
-  heap_buffer_offset = sizeof *coalesced_write_req; /* offset (a) + (b) */
-
-  /* Copy data buffers to the heap buffer. */
-  data_start = &heap_buffer[heap_buffer_offset];
-  for (i = 0; i < nbufs; i++) {
-    memcpy(&heap_buffer[heap_buffer_offset],
-           bufs[i].base,
-           bufs[i].len);               /* copy (c) */
-    heap_buffer_offset += bufs[i].len; /* offset (c) */
-  }
-  assert(heap_buffer_offset == heap_buffer_length);
-
-  /* Set out arguments and return. */
-  *req_out = &coalesced_write_req->req;
-  *write_buf_out = uv_buf_init(data_start, (unsigned int) data_length);
-  return 0;
-}
-
-
-static int uv__pipe_write_data(uv_loop_t* loop,
-                               uv_write_t* req,
-                               uv_pipe_t* handle,
-                               const uv_buf_t bufs[],
-                               size_t nbufs,
-                               uv_write_cb cb,
-                               int copy_always) {
-  int err;
-  int result;
-  uv_buf_t write_buf;
-
-  assert(handle->handle != INVALID_HANDLE_VALUE);
-
-  UV_REQ_INIT(req, UV_WRITE);
-  req->handle = (uv_stream_t*) handle;
-  req->send_handle = NULL;
-  req->cb = cb;
-  /* Private fields. */
-  req->coalesced = 0;
-  req->event_handle = NULL;
-  req->wait_handle = INVALID_HANDLE_VALUE;
-  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-  req->write_buffer = uv_null_buf_;
-
-  if (nbufs == 0) {
-    /* Write empty buffer. */
-    write_buf = uv_null_buf_;
-  } else if (nbufs == 1 && !copy_always) {
-    /* Write directly from bufs[0]. */
-    write_buf = bufs[0];
-  } else {
-    /* Coalesce all `bufs` into one big buffer. This also creates a new
-     * write-request structure that replaces the old one. */
-    err = uv__build_coalesced_write_req(req, bufs, nbufs, &req, &write_buf);
-    if (err != 0)
-      return err;
-  }
-
-  if ((handle->flags &
-      (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) ==
-      (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) {
-    DWORD bytes;
-    result =
-        WriteFile(handle->handle, write_buf.base, write_buf.len, &bytes, NULL);
-
-    if (!result) {
-      err = GetLastError();
-      return err;
-    } else {
-      /* Request completed immediately. */
-      req->u.io.queued_bytes = 0;
-    }
-
-    REGISTER_HANDLE_REQ(loop, handle, req);
-    handle->reqs_pending++;
-    handle->stream.conn.write_reqs_pending++;
-    POST_COMPLETION_FOR_REQ(loop, req);
-    return 0;
-  } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
-    req->write_buffer = write_buf;
-    uv_insert_non_overlapped_write_req(handle, req);
-    if (handle->stream.conn.write_reqs_pending == 0) {
-      uv_queue_non_overlapped_write(handle);
-    }
-
-    /* Request queued by the kernel. */
-    req->u.io.queued_bytes = write_buf.len;
-    handle->write_queue_size += req->u.io.queued_bytes;
-  } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) {
-    /* Using overlapped IO, but wait for completion before returning */
-    req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL);
-    if (!req->u.io.overlapped.hEvent) {
-      uv_fatal_error(GetLastError(), "CreateEvent");
-    }
-
-    result = WriteFile(handle->handle,
-                       write_buf.base,
-                       write_buf.len,
-                       NULL,
-                       &req->u.io.overlapped);
-
-    if (!result && GetLastError() != ERROR_IO_PENDING) {
-      err = GetLastError();
-      CloseHandle(req->u.io.overlapped.hEvent);
-      return err;
-    }
-
-    if (result) {
-      /* Request completed immediately. */
-      req->u.io.queued_bytes = 0;
-    } else {
-      /* Request queued by the kernel. */
-      req->u.io.queued_bytes = write_buf.len;
-      handle->write_queue_size += req->u.io.queued_bytes;
-      if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) !=
-          WAIT_OBJECT_0) {
-        err = GetLastError();
-        CloseHandle(req->u.io.overlapped.hEvent);
-        return err;
-      }
-    }
-    CloseHandle(req->u.io.overlapped.hEvent);
-
-    REGISTER_HANDLE_REQ(loop, handle, req);
-    handle->reqs_pending++;
-    handle->stream.conn.write_reqs_pending++;
-    return 0;
-  } else {
-    result = WriteFile(handle->handle,
-                       write_buf.base,
-                       write_buf.len,
-                       NULL,
-                       &req->u.io.overlapped);
-
-    if (!result && GetLastError() != ERROR_IO_PENDING) {
-      return GetLastError();
-    }
-
-    if (result) {
-      /* Request completed immediately. */
-      req->u.io.queued_bytes = 0;
-    } else {
-      /* Request queued by the kernel. */
-      req->u.io.queued_bytes = write_buf.len;
-      handle->write_queue_size += req->u.io.queued_bytes;
-    }
-
-    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-      req->event_handle = CreateEvent(NULL, 0, 0, NULL);
-      if (!req->event_handle) {
-        uv_fatal_error(GetLastError(), "CreateEvent");
-      }
-      if (!RegisterWaitForSingleObject(&req->wait_handle,
-          req->u.io.overlapped.hEvent, post_completion_write_wait, (void*) req,
-          INFINITE, WT_EXECUTEINWAITTHREAD)) {
-        return GetLastError();
-      }
-    }
-  }
-
-  REGISTER_HANDLE_REQ(loop, handle, req);
-  handle->reqs_pending++;
-  handle->stream.conn.write_reqs_pending++;
-
-  return 0;
-}
-
-
-static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t* handle) {
-  DWORD* pid = &handle->pipe.conn.ipc_remote_pid;
-
-  /* If the both ends of the IPC pipe are owned by the same process,
-   * the remote end pid may not yet be set. If so, do it here.
-   * TODO: this is weird; it'd probably better to use a handshake. */
-  if (*pid == 0)
-    *pid = GetCurrentProcessId();
-
-  return *pid;
-}
-
-
-int uv__pipe_write_ipc(uv_loop_t* loop,
-                       uv_write_t* req,
-                       uv_pipe_t* handle,
-                       const uv_buf_t data_bufs[],
-                       size_t data_buf_count,
-                       uv_stream_t* send_handle,
-                       uv_write_cb cb) {
-  uv_buf_t stack_bufs[6];
-  uv_buf_t* bufs;
-  size_t buf_count, buf_index;
-  uv__ipc_frame_header_t frame_header;
-  uv__ipc_socket_xfer_type_t xfer_type = UV__IPC_SOCKET_XFER_NONE;
-  uv__ipc_socket_xfer_info_t xfer_info;
-  uint64_t data_length;
-  size_t i;
-  int err;
-
-  /* Compute the combined size of data buffers. */
-  data_length = 0;
-  for (i = 0; i < data_buf_count; i++)
-    data_length += data_bufs[i].len;
-  if (data_length > UINT32_MAX)
-    return WSAENOBUFS; /* Maps to UV_ENOBUFS. */
-
-  /* Prepare the frame's socket xfer payload. */
-  if (send_handle != NULL) {
-    uv_tcp_t* send_tcp_handle = (uv_tcp_t*) send_handle;
-
-    /* Verify that `send_handle` it is indeed a tcp handle. */
-    if (send_tcp_handle->type != UV_TCP)
-      return ERROR_NOT_SUPPORTED;
-
-    /* Export the tcp handle. */
-    err = uv__tcp_xfer_export(send_tcp_handle,
-                              uv__pipe_get_ipc_remote_pid(handle),
-                              &xfer_type,
-                              &xfer_info);
-    if (err != 0)
-      return err;
-  }
-
-  /* Compute the number of uv_buf_t's required. */
-  buf_count = 1 + data_buf_count; /* Frame header and data buffers. */
-  if (send_handle != NULL)
-    buf_count += 1; /* One extra for the socket xfer information. */
-
-  /* Use the on-stack buffer array if it is big enough; otherwise allocate
-   * space for it on the heap. */
-  if (buf_count < ARRAY_SIZE(stack_bufs)) {
-    /* Use on-stack buffer array. */
-    bufs = stack_bufs;
-  } else {
-    /* Use heap-allocated buffer array. */
-    bufs = (uv_buf_t*)uv__calloc(buf_count, sizeof(uv_buf_t));
-    if (bufs == NULL)
-      return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */
-  }
-  buf_index = 0;
-
-  /* Initialize frame header and add it to the buffers list. */
-  memset(&frame_header, 0, sizeof frame_header);
-  bufs[buf_index++] = uv_buf_init((char*) &frame_header, sizeof frame_header);
-
-  if (send_handle != NULL) {
-    /* Add frame header flags. */
-    switch (xfer_type) {
-      case UV__IPC_SOCKET_XFER_TCP_CONNECTION:
-        frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER |
-                              UV__IPC_FRAME_XFER_IS_TCP_CONNECTION;
-        break;
-      case UV__IPC_SOCKET_XFER_TCP_SERVER:
-        frame_header.flags |= UV__IPC_FRAME_HAS_SOCKET_XFER;
-        break;
-      default:
-        assert(0);  /* Unreachable. */
-    }
-    /* Add xfer info buffer. */
-    bufs[buf_index++] = uv_buf_init((char*) &xfer_info, sizeof xfer_info);
-  }
-
-  if (data_length > 0) {
-    /* Update frame header. */
-    frame_header.flags |= UV__IPC_FRAME_HAS_DATA;
-    frame_header.data_length = (uint32_t) data_length;
-    /* Add data buffers to buffers list. */
-    for (i = 0; i < data_buf_count; i++)
-      bufs[buf_index++] = data_bufs[i];
-  }
-
-  /* Write buffers. We set the `always_copy` flag, so it is not a problem that
-   * some of the written data lives on the stack. */
-  err = uv__pipe_write_data(loop, req, handle, bufs, buf_count, cb, 1);
-
-  /* If we had to heap-allocate the bufs array, free it now. */
-  if (bufs != stack_bufs) {
-    uv__free(bufs);
-  }
-
-  return err;
-}
-
-
-int uv__pipe_write(uv_loop_t* loop,
-                   uv_write_t* req,
-                   uv_pipe_t* handle,
-                   const uv_buf_t bufs[],
-                   size_t nbufs,
-                   uv_stream_t* send_handle,
-                   uv_write_cb cb) {
-  if (handle->ipc) {
-    /* IPC pipe write: use framing protocol. */
-    return uv__pipe_write_ipc(loop, req, handle, bufs, nbufs, send_handle, cb);
-  } else {
-    /* Non-IPC pipe write: put data on the wire directly. */
-    assert(send_handle == NULL);
-    return uv__pipe_write_data(loop, req, handle, bufs, nbufs, cb, 0);
-  }
-}
-
-
-static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_buf_t buf) {
-  /* If there is an eof timer running, we don't need it any more, so discard
-   * it. */
-  eof_timer_destroy(handle);
-
-  handle->flags &= ~UV_HANDLE_READABLE;
-  uv_read_stop((uv_stream_t*) handle);
-
-  handle->read_cb((uv_stream_t*) handle, UV_EOF, &buf);
-}
-
-
-static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
-    uv_buf_t buf) {
-  /* If there is an eof timer running, we don't need it any more, so discard
-   * it. */
-  eof_timer_destroy(handle);
-
-  uv_read_stop((uv_stream_t*) handle);
-
-  handle->read_cb((uv_stream_t*)handle, uv_translate_sys_error(error), &buf);
-}
-
-
-static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
-    int error, uv_buf_t buf) {
-  if (error == ERROR_BROKEN_PIPE) {
-    uv_pipe_read_eof(loop, handle, buf);
-  } else {
-    uv_pipe_read_error(loop, handle, error, buf);
-  }
-}
-
-
-static void uv__pipe_queue_ipc_xfer_info(
-    uv_pipe_t* handle,
-    uv__ipc_socket_xfer_type_t xfer_type,
-    uv__ipc_socket_xfer_info_t* xfer_info) {
-  uv__ipc_xfer_queue_item_t* item;
-
-  item = (uv__ipc_xfer_queue_item_t*) uv__malloc(sizeof(*item));
-  if (item == NULL)
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-
-  item->xfer_type = xfer_type;
-  item->xfer_info = *xfer_info;
-
-  QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member);
-  handle->pipe.conn.ipc_xfer_queue_length++;
-}
-
-
-/* Read an exact number of bytes from a pipe. If an error or end-of-file is
- * encountered before the requested number of bytes are read, an error is
- * returned. */
-static int uv__pipe_read_exactly(HANDLE h, void* buffer, DWORD count) {
-  DWORD bytes_read, bytes_read_now;
-
-  bytes_read = 0;
-  while (bytes_read < count) {
-    if (!ReadFile(h,
-                  (char*) buffer + bytes_read,
-                  count - bytes_read,
-                  &bytes_read_now,
-                  NULL)) {
-      return GetLastError();
-    }
-
-    bytes_read += bytes_read_now;
-  }
-
-  assert(bytes_read == count);
-  return 0;
-}
-
-
-static DWORD uv__pipe_read_data(uv_loop_t* loop,
-                                uv_pipe_t* handle,
-                                DWORD suggested_bytes,
-                                DWORD max_bytes) {
-  DWORD bytes_read;
-  uv_buf_t buf;
-
-  /* Ask the user for a buffer to read data into. */
-  buf = uv_buf_init(NULL, 0);
-  handle->alloc_cb((uv_handle_t*) handle, suggested_bytes, &buf);
-  if (buf.base == NULL || buf.len == 0) {
-    handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
-    return 0; /* Break out of read loop. */
-  }
-
-  /* Ensure we read at most the smaller of:
-   *   (a) the length of the user-allocated buffer.
-   *   (b) the maximum data length as specified by the `max_bytes` argument.
-   */
-  if (max_bytes > buf.len)
-    max_bytes = buf.len;
-
-  /* Read into the user buffer. */
-  if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) {
-    uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf);
-    return 0; /* Break out of read loop. */
-  }
-
-  /* Call the read callback. */
-  handle->read_cb((uv_stream_t*) handle, bytes_read, &buf);
-
-  return bytes_read;
-}
-
-
-static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
-  uint32_t* data_remaining = &handle->pipe.conn.ipc_data_frame.payload_remaining;
-  int err;
-
-  if (*data_remaining > 0) {
-    /* Read frame data payload. */
-    DWORD bytes_read =
-        uv__pipe_read_data(loop, handle, *data_remaining, *data_remaining);
-    *data_remaining -= bytes_read;
-    return bytes_read;
-
-  } else {
-    /* Start of a new IPC frame. */
-    uv__ipc_frame_header_t frame_header;
-    uint32_t xfer_flags;
-    uv__ipc_socket_xfer_type_t xfer_type;
-    uv__ipc_socket_xfer_info_t xfer_info;
-
-    /* Read the IPC frame header. */
-    err = uv__pipe_read_exactly(
-        handle->handle, &frame_header, sizeof frame_header);
-    if (err)
-      goto error;
-
-    /* Validate that flags are valid. */
-    if ((frame_header.flags & ~UV__IPC_FRAME_VALID_FLAGS) != 0)
-      goto invalid;
-    /* Validate that reserved2 is zero. */
-    if (frame_header.reserved2 != 0)
-      goto invalid;
-
-    /* Parse xfer flags. */
-    xfer_flags = frame_header.flags & UV__IPC_FRAME_XFER_FLAGS;
-    if (xfer_flags & UV__IPC_FRAME_HAS_SOCKET_XFER) {
-      /* Socket coming -- determine the type. */
-      xfer_type = xfer_flags & UV__IPC_FRAME_XFER_IS_TCP_CONNECTION
-                      ? UV__IPC_SOCKET_XFER_TCP_CONNECTION
-                      : UV__IPC_SOCKET_XFER_TCP_SERVER;
-    } else if (xfer_flags == 0) {
-      /* No socket. */
-      xfer_type = UV__IPC_SOCKET_XFER_NONE;
-    } else {
-      /* Invalid flags. */
-      goto invalid;
-    }
-
-    /* Parse data frame information. */
-    if (frame_header.flags & UV__IPC_FRAME_HAS_DATA) {
-      *data_remaining = frame_header.data_length;
-    } else if (frame_header.data_length != 0) {
-      /* Data length greater than zero but data flag not set -- invalid. */
-      goto invalid;
-    }
-
-    /* If no socket xfer info follows, return here. Data will be read in a
-     * subsequent invocation of uv__pipe_read_ipc(). */
-    if (xfer_type == UV__IPC_SOCKET_XFER_NONE)
-      return sizeof frame_header; /* Number of bytes read. */
-
-    /* Read transferred socket information. */
-    err = uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info);
-    if (err)
-      goto error;
-
-    /* Store the pending socket info. */
-    uv__pipe_queue_ipc_xfer_info(handle, xfer_type, &xfer_info);
-
-    /* Return number of bytes read. */
-    return sizeof frame_header + sizeof xfer_info;
-  }
-
-invalid:
-  /* Invalid frame. */
-  err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */
-
-error:
-  uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
-  return 0; /* Break out of read loop. */
-}
-
-
-void uv_process_pipe_read_req(uv_loop_t* loop,
-                              uv_pipe_t* handle,
-                              uv_req_t* req) {
-  assert(handle->type == UV_NAMED_PIPE);
-
-  handle->flags &= ~(UV_HANDLE_READ_PENDING | UV_HANDLE_CANCELLATION_PENDING);
-  DECREASE_PENDING_REQ_COUNT(handle);
-  eof_timer_stop(handle);
-
-  /* At this point, we're done with bookkeeping. If the user has stopped
-   * reading the pipe in the meantime, there is nothing left to do, since there
-   * is no callback that we can call. */
-  if (!(handle->flags & UV_HANDLE_READING))
-    return;
-
-  if (!REQ_SUCCESS(req)) {
-    /* An error occurred doing the zero-read. */
-    DWORD err = GET_REQ_ERROR(req);
-
-    /* If the read was cancelled by uv__pipe_interrupt_read(), the request may
-     * indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to
-     * the user; we'll start a new zero-read at the end of this function. */
-    if (err != ERROR_OPERATION_ABORTED)
-      uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_);
-
-  } else {
-    /* The zero-read completed without error, indicating there is data
-     * available in the kernel buffer. */
-    DWORD avail;
-
-    /* Get the number of bytes available. */
-    avail = 0;
-    if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL))
-      uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_);
-
-    /* Read until we've either read all the bytes available, or the 'reading'
-     * flag is cleared. */
-    while (avail > 0 && handle->flags & UV_HANDLE_READING) {
-      /* Depending on the type of pipe, read either IPC frames or raw data. */
-      DWORD bytes_read =
-          handle->ipc ? uv__pipe_read_ipc(loop, handle)
-                      : uv__pipe_read_data(loop, handle, avail, (DWORD) -1);
-
-      /* If no bytes were read, treat this as an indication that an error
-       * occurred, and break out of the read loop. */
-      if (bytes_read == 0)
-        break;
-
-      /* It is possible that more bytes were read than we thought were
-       * available. To prevent `avail` from underflowing, break out of the loop
-       * if this is the case. */
-      if (bytes_read > avail)
-        break;
-
-      /* Recompute the number of bytes available. */
-      avail -= bytes_read;
-    }
-  }
-
-  /* Start another zero-read request if necessary. */
-  if ((handle->flags & UV_HANDLE_READING) &&
-      !(handle->flags & UV_HANDLE_READ_PENDING)) {
-    uv_pipe_queue_read(loop, handle);
-  }
-}
-
-
-void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_write_t* req) {
-  int err;
-
-  assert(handle->type == UV_NAMED_PIPE);
-
-  assert(handle->write_queue_size >= req->u.io.queued_bytes);
-  handle->write_queue_size -= req->u.io.queued_bytes;
-
-  UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-    if (req->wait_handle != INVALID_HANDLE_VALUE) {
-      UnregisterWait(req->wait_handle);
-      req->wait_handle = INVALID_HANDLE_VALUE;
-    }
-    if (req->event_handle) {
-      CloseHandle(req->event_handle);
-      req->event_handle = NULL;
-    }
-  }
-
-  err = GET_REQ_ERROR(req);
-
-  /* If this was a coalesced write, extract pointer to the user_provided
-   * uv_write_t structure so we can pass the expected pointer to the callback,
-   * then free the heap-allocated write req. */
-  if (req->coalesced) {
-    uv__coalesced_write_t* coalesced_write =
-        container_of(req, uv__coalesced_write_t, req);
-    req = coalesced_write->user_req;
-    uv__free(coalesced_write);
-  }
-  if (req->cb) {
-    req->cb(req, uv_translate_sys_error(err));
-  }
-
-  handle->stream.conn.write_reqs_pending--;
-
-  if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE &&
-      handle->pipe.conn.non_overlapped_writes_tail) {
-    assert(handle->stream.conn.write_reqs_pending > 0);
-    uv_queue_non_overlapped_write(handle);
-  }
-
-  if (handle->stream.conn.shutdown_req != NULL &&
-      handle->stream.conn.write_reqs_pending == 0) {
-    uv_want_endgame(loop, (uv_handle_t*)handle);
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_req_t* raw_req) {
-  uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req;
-
-  assert(handle->type == UV_NAMED_PIPE);
-
-  if (handle->flags & UV_HANDLE_CLOSING) {
-    /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */
-    assert(req->pipeHandle == INVALID_HANDLE_VALUE);
-    DECREASE_PENDING_REQ_COUNT(handle);
-    return;
-  }
-
-  if (REQ_SUCCESS(req)) {
-    assert(req->pipeHandle != INVALID_HANDLE_VALUE);
-    req->next_pending = handle->pipe.serv.pending_accepts;
-    handle->pipe.serv.pending_accepts = req;
-
-    if (handle->stream.serv.connection_cb) {
-      handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);
-    }
-  } else {
-    if (req->pipeHandle != INVALID_HANDLE_VALUE) {
-      CloseHandle(req->pipeHandle);
-      req->pipeHandle = INVALID_HANDLE_VALUE;
-    }
-    if (!(handle->flags & UV_HANDLE_CLOSING)) {
-      uv_pipe_queue_accept(loop, handle, req, FALSE);
-    }
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_connect_t* req) {
-  int err;
-
-  assert(handle->type == UV_NAMED_PIPE);
-
-  UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-  if (req->cb) {
-    err = 0;
-    if (REQ_SUCCESS(req)) {
-      uv_pipe_connection_init(handle);
-    } else {
-      err = GET_REQ_ERROR(req);
-    }
-    req->cb(req, uv_translate_sys_error(err));
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle,
-    uv_shutdown_t* req) {
-  assert(handle->type == UV_NAMED_PIPE);
-
-  UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-  if (handle->flags & UV_HANDLE_READABLE) {
-    /* Initialize and optionally start the eof timer. Only do this if the pipe
-     * is readable and we haven't seen EOF come in ourselves. */
-    eof_timer_init(handle);
-
-    /* If reading start the timer right now. Otherwise uv_pipe_queue_read will
-     * start it. */
-    if (handle->flags & UV_HANDLE_READ_PENDING) {
-      eof_timer_start(handle);
-    }
-
-  } else {
-    /* This pipe is not readable. We can just close it to let the other end
-     * know that we're done writing. */
-    close_pipe(handle);
-  }
-
-  if (req->cb) {
-    req->cb(req, 0);
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-static void eof_timer_init(uv_pipe_t* pipe) {
-  int r;
-
-  assert(pipe->pipe.conn.eof_timer == NULL);
-  assert(pipe->flags & UV_HANDLE_CONNECTION);
-
-  pipe->pipe.conn.eof_timer = (uv_timer_t*) uv__malloc(sizeof *pipe->pipe.conn.eof_timer);
-
-  r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer);
-  assert(r == 0); /* timers can't fail */
-  pipe->pipe.conn.eof_timer->data = pipe;
-  uv_unref((uv_handle_t*) pipe->pipe.conn.eof_timer);
-}
-
-
-static void eof_timer_start(uv_pipe_t* pipe) {
-  assert(pipe->flags & UV_HANDLE_CONNECTION);
-
-  if (pipe->pipe.conn.eof_timer != NULL) {
-    uv_timer_start(pipe->pipe.conn.eof_timer, eof_timer_cb, eof_timeout, 0);
-  }
-}
-
-
-static void eof_timer_stop(uv_pipe_t* pipe) {
-  assert(pipe->flags & UV_HANDLE_CONNECTION);
-
-  if (pipe->pipe.conn.eof_timer != NULL) {
-    uv_timer_stop(pipe->pipe.conn.eof_timer);
-  }
-}
-
-
-static void eof_timer_cb(uv_timer_t* timer) {
-  uv_pipe_t* pipe = (uv_pipe_t*) timer->data;
-  uv_loop_t* loop = timer->loop;
-
-  assert(pipe->type == UV_NAMED_PIPE);
-
-  /* This should always be true, since we start the timer only in
-   * uv_pipe_queue_read after successfully calling ReadFile, or in
-   * uv_process_pipe_shutdown_req if a read is pending, and we always
-   * immediately stop the timer in uv_process_pipe_read_req. */
-  assert(pipe->flags & UV_HANDLE_READ_PENDING);
-
-  /* If there are many packets coming off the iocp then the timer callback may
-   * be called before the read request is coming off the queue. Therefore we
-   * check here if the read request has completed but will be processed later.
-   */
-  if ((pipe->flags & UV_HANDLE_READ_PENDING) &&
-      HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) {
-    return;
-  }
-
-  /* Force both ends off the pipe. */
-  close_pipe(pipe);
-
-  /* Stop reading, so the pending read that is going to fail will not be
-   * reported to the user. */
-  uv_read_stop((uv_stream_t*) pipe);
-
-  /* Report the eof and update flags. This will get reported even if the user
-   * stopped reading in the meantime. TODO: is that okay? */
-  uv_pipe_read_eof(loop, pipe, uv_null_buf_);
-}
-
-
-static void eof_timer_destroy(uv_pipe_t* pipe) {
-  assert(pipe->flags & UV_HANDLE_CONNECTION);
-
-  if (pipe->pipe.conn.eof_timer) {
-    uv_close((uv_handle_t*) pipe->pipe.conn.eof_timer, eof_timer_close_cb);
-    pipe->pipe.conn.eof_timer = NULL;
-  }
-}
-
-
-static void eof_timer_close_cb(uv_handle_t* handle) {
-  assert(handle->type == UV_TIMER);
-  uv__free(handle);
-}
-
-
-int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
-  HANDLE os_handle = uv__get_osfhandle(file);
-  NTSTATUS nt_status;
-  IO_STATUS_BLOCK io_status;
-  FILE_ACCESS_INFORMATION access;
-  DWORD duplex_flags = 0;
-
-  if (os_handle == INVALID_HANDLE_VALUE)
-    return UV_EBADF;
-
-  uv__once_init();
-  /* In order to avoid closing a stdio file descriptor 0-2, duplicate the
-   * underlying OS handle and forget about the original fd.
-   * We could also opt to use the original OS handle and just never close it,
-   * but then there would be no reliable way to cancel pending read operations
-   * upon close.
-   */
-  if (file <= 2) {
-    if (!DuplicateHandle(INVALID_HANDLE_VALUE,
-                         os_handle,
-                         INVALID_HANDLE_VALUE,
-                         &os_handle,
-                         0,
-                         FALSE,
-                         DUPLICATE_SAME_ACCESS))
-      return uv_translate_sys_error(GetLastError());
-    file = -1;
-  }
-
-  /* Determine what kind of permissions we have on this handle.
-   * Cygwin opens the pipe in message mode, but we can support it,
-   * just query the access flags and set the stream flags accordingly.
-   */
-  nt_status = pNtQueryInformationFile(os_handle,
-                                      &io_status,
-                                      &access,
-                                      sizeof(access),
-                                      FileAccessInformation);
-  if (nt_status != STATUS_SUCCESS)
-    return UV_EINVAL;
-
-  if (pipe->ipc) {
-    if (!(access.AccessFlags & FILE_WRITE_DATA) ||
-        !(access.AccessFlags & FILE_READ_DATA)) {
-      return UV_EINVAL;
-    }
-  }
-
-  if (access.AccessFlags & FILE_WRITE_DATA)
-    duplex_flags |= UV_HANDLE_WRITABLE;
-  if (access.AccessFlags & FILE_READ_DATA)
-    duplex_flags |= UV_HANDLE_READABLE;
-
-  if (os_handle == INVALID_HANDLE_VALUE ||
-      uv_set_pipe_handle(pipe->loop,
-                         pipe,
-                         os_handle,
-                         file,
-                         duplex_flags) == -1) {
-    return UV_EINVAL;
-  }
-
-  uv_pipe_connection_init(pipe);
-
-  if (pipe->ipc) {
-    assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
-    pipe->pipe.conn.ipc_remote_pid = uv_os_getppid();
-    assert(pipe->pipe.conn.ipc_remote_pid != (DWORD) -1);
-  }
-  return 0;
-}
-
-
-static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) {
-  NTSTATUS nt_status;
-  IO_STATUS_BLOCK io_status;
-  FILE_NAME_INFORMATION tmp_name_info;
-  FILE_NAME_INFORMATION* name_info;
-  WCHAR* name_buf;
-  unsigned int addrlen;
-  unsigned int name_size;
-  unsigned int name_len;
-  int err;
-
-  uv__once_init();
-  name_info = NULL;
-
-  if (handle->handle == INVALID_HANDLE_VALUE) {
-    *size = 0;
-    return UV_EINVAL;
-  }
-
-  /* NtQueryInformationFile will block if another thread is performing a
-   * blocking operation on the queried handle. If the pipe handle is
-   * synchronous, there may be a worker thread currently calling ReadFile() on
-   * the pipe handle, which could cause a deadlock. To avoid this, interrupt
-   * the read. */
-  if (handle->flags & UV_HANDLE_CONNECTION &&
-      handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) {
-    uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */
-  }
-
-  nt_status = pNtQueryInformationFile(handle->handle,
-                                      &io_status,
-                                      &tmp_name_info,
-                                      sizeof tmp_name_info,
-                                      FileNameInformation);
-  if (nt_status == STATUS_BUFFER_OVERFLOW) {
-    name_size = sizeof(*name_info) + tmp_name_info.FileNameLength;
-    name_info = (FILE_NAME_INFORMATION*)uv__malloc(name_size);
-    if (!name_info) {
-      *size = 0;
-      err = UV_ENOMEM;
-      goto cleanup;
-    }
-
-    nt_status = pNtQueryInformationFile(handle->handle,
-                                        &io_status,
-                                        name_info,
-                                        name_size,
-                                        FileNameInformation);
-  }
-
-  if (nt_status != STATUS_SUCCESS) {
-    *size = 0;
-    err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status));
-    goto error;
-  }
-
-  if (!name_info) {
-    /* the struct on stack was used */
-    name_buf = tmp_name_info.FileName;
-    name_len = tmp_name_info.FileNameLength;
-  } else {
-    name_buf = name_info->FileName;
-    name_len = name_info->FileNameLength;
-  }
-
-  if (name_len == 0) {
-    *size = 0;
-    err = 0;
-    goto error;
-  }
-
-  name_len /= sizeof(WCHAR);
-
-  /* check how much space we need */
-  addrlen = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                name_buf,
-                                name_len,
-                                NULL,
-                                0,
-                                NULL,
-                                NULL);
-  if (!addrlen) {
-    *size = 0;
-    err = uv_translate_sys_error(GetLastError());
-    goto error;
-  } else if (pipe_prefix_len + addrlen >= *size) {
-    /* "\\\\.\\pipe" + name */
-    *size = pipe_prefix_len + addrlen + 1;
-    err = UV_ENOBUFS;
-    goto error;
-  }
-
-  memcpy(buffer, pipe_prefix, pipe_prefix_len);
-  addrlen = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                name_buf,
-                                name_len,
-                                buffer+pipe_prefix_len,
-                                *size-pipe_prefix_len,
-                                NULL,
-                                NULL);
-  if (!addrlen) {
-    *size = 0;
-    err = uv_translate_sys_error(GetLastError());
-    goto error;
-  }
-
-  addrlen += pipe_prefix_len;
-  *size = addrlen;
-  buffer[addrlen] = '\0';
-
-  err = 0;
-
-error:
-  uv__free(name_info);
-
-cleanup:
-  return err;
-}
-
-
-int uv_pipe_pending_count(uv_pipe_t* handle) {
-  if (!handle->ipc)
-    return 0;
-  return handle->pipe.conn.ipc_xfer_queue_length;
-}
-
-
-int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
-  if (handle->flags & UV_HANDLE_BOUND)
-    return uv__pipe_getname(handle, buffer, size);
-
-  if (handle->flags & UV_HANDLE_CONNECTION ||
-      handle->handle != INVALID_HANDLE_VALUE) {
-    *size = 0;
-    return 0;
-  }
-
-  return UV_EBADF;
-}
-
-
-int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
-  /* emulate unix behaviour */
-  if (handle->flags & UV_HANDLE_BOUND)
-    return UV_ENOTCONN;
-
-  if (handle->handle != INVALID_HANDLE_VALUE)
-    return uv__pipe_getname(handle, buffer, size);
-
-  return UV_EBADF;
-}
-
-
-uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
-  if (!handle->ipc)
-    return UV_UNKNOWN_HANDLE;
-  if (handle->pipe.conn.ipc_xfer_queue_length == 0)
-    return UV_UNKNOWN_HANDLE;
-  else
-    return UV_TCP;
-}
-
-int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
-  SID_IDENTIFIER_AUTHORITY sid_world = { SECURITY_WORLD_SID_AUTHORITY };
-  PACL old_dacl, new_dacl;
-  PSECURITY_DESCRIPTOR sd;
-  EXPLICIT_ACCESS ea;
-  PSID everyone;
-  int error;
-
-  if (handle == NULL || handle->handle == INVALID_HANDLE_VALUE)
-    return UV_EBADF;
-
-  if (mode != UV_READABLE &&
-      mode != UV_WRITABLE &&
-      mode != (UV_WRITABLE | UV_READABLE))
-    return UV_EINVAL;
-
-  if (!AllocateAndInitializeSid(&sid_world,
-                                1,
-                                SECURITY_WORLD_RID,
-                                0, 0, 0, 0, 0, 0, 0,
-                                &everyone)) {
-    error = GetLastError();
-    goto done;
-  }
-
-  if (GetSecurityInfo(handle->handle,
-                      SE_KERNEL_OBJECT,
-                      DACL_SECURITY_INFORMATION,
-                      NULL,
-                      NULL,
-                      &old_dacl,
-                      NULL,
-                      &sd)) {
-    error = GetLastError();
-    goto clean_sid;
-  }
-
-  memset(&ea, 0, sizeof(EXPLICIT_ACCESS));
-  if (mode & UV_READABLE)
-    ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
-  if (mode & UV_WRITABLE)
-    ea.grfAccessPermissions |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
-  ea.grfAccessPermissions |= SYNCHRONIZE;
-  ea.grfAccessMode = SET_ACCESS;
-  ea.grfInheritance = NO_INHERITANCE;
-  ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
-  ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
-  ea.Trustee.ptstrName = (LPTSTR)everyone;
-
-  if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl)) {
-    error = GetLastError();
-    goto clean_sd;
-  }
-
-  if (SetSecurityInfo(handle->handle,
-                      SE_KERNEL_OBJECT,
-                      DACL_SECURITY_INFORMATION,
-                      NULL,
-                      NULL,
-                      new_dacl,
-                      NULL)) {
-    error = GetLastError();
-    goto clean_dacl;
-  }
-
-  error = 0;
-
-clean_dacl:
-  LocalFree((HLOCAL) new_dacl);
-clean_sd:
-  LocalFree((HLOCAL) sd);
-clean_sid:
-  FreeSid(everyone);
-done:
-  return uv_translate_sys_error(error);
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/poll.cpp b/wpiutil/src/main/native/libuv/src/win/poll.cpp
deleted file mode 100644
index 3c66786..0000000
--- a/wpiutil/src/main/native/libuv/src/win/poll.cpp
+++ /dev/null
@@ -1,643 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <io.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "req-inl.h"
-
-
-static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = {
-  {0xe70f1aa0, 0xab8b, 0x11cf,
-      {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
-  {0xf9eab0c0, 0x26d4, 0x11d0,
-      {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
-  {0x9fc48064, 0x7298, 0x43e4,
-      {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}}
-};
-
-typedef struct uv_single_fd_set_s {
-  unsigned int fd_count;
-  SOCKET fd_array[1];
-} uv_single_fd_set_t;
-
-
-static OVERLAPPED overlapped_dummy_;
-static uv_once_t overlapped_dummy_init_guard_ = UV_ONCE_INIT;
-
-static AFD_POLL_INFO afd_poll_info_dummy_;
-
-
-static void uv__init_overlapped_dummy(void) {
-  HANDLE event;
-
-  event = CreateEvent(NULL, TRUE, TRUE, NULL);
-  if (event == NULL)
-    uv_fatal_error(GetLastError(), "CreateEvent");
-
-  memset(&overlapped_dummy_, 0, sizeof overlapped_dummy_);
-  overlapped_dummy_.hEvent = (HANDLE) ((uintptr_t) event | 1);
-}
-
-
-static OVERLAPPED* uv__get_overlapped_dummy(void) {
-  uv_once(&overlapped_dummy_init_guard_, uv__init_overlapped_dummy);
-  return &overlapped_dummy_;
-}
-
-
-static AFD_POLL_INFO* uv__get_afd_poll_info_dummy(void) {
-  return &afd_poll_info_dummy_;
-}
-
-
-static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
-  uv_req_t* req;
-  AFD_POLL_INFO* afd_poll_info;
-  int result;
-
-  /* Find a yet unsubmitted req to submit. */
-  if (handle->submitted_events_1 == 0) {
-    req = &handle->poll_req_1;
-    afd_poll_info = &handle->afd_poll_info_1;
-    handle->submitted_events_1 = handle->events;
-    handle->mask_events_1 = 0;
-    handle->mask_events_2 = handle->events;
-  } else if (handle->submitted_events_2 == 0) {
-    req = &handle->poll_req_2;
-    afd_poll_info = &handle->afd_poll_info_2;
-    handle->submitted_events_2 = handle->events;
-    handle->mask_events_1 = handle->events;
-    handle->mask_events_2 = 0;
-  } else {
-    /* Just wait until there's an unsubmitted req. This will happen almost
-     * immediately as one of the 2 outstanding requests is about to return.
-     * When this happens, uv__fast_poll_process_poll_req will be called, and
-     * the pending events, if needed, will be processed in a subsequent
-     * request. */
-    return;
-  }
-
-  /* Setting Exclusive to TRUE makes the other poll request return if there is
-   * any. */
-  afd_poll_info->Exclusive = TRUE;
-  afd_poll_info->NumberOfHandles = 1;
-  afd_poll_info->Timeout.QuadPart = INT64_MAX;
-  afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket;
-  afd_poll_info->Handles[0].Status = 0;
-  afd_poll_info->Handles[0].Events = 0;
-
-  if (handle->events & UV_READABLE) {
-    afd_poll_info->Handles[0].Events |= AFD_POLL_RECEIVE |
-        AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT;
-  } else {
-    if (handle->events & UV_DISCONNECT) {
-      afd_poll_info->Handles[0].Events |= AFD_POLL_DISCONNECT;
-    }
-  }
-  if (handle->events & UV_WRITABLE) {
-    afd_poll_info->Handles[0].Events |= AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL;
-  }
-
-  memset(&req->u.io.overlapped, 0, sizeof req->u.io.overlapped);
-
-  result = uv_msafd_poll((SOCKET) handle->peer_socket,
-                         afd_poll_info,
-                         afd_poll_info,
-                         &req->u.io.overlapped);
-  if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) {
-    /* Queue this req, reporting an error. */
-    SET_REQ_ERROR(req, WSAGetLastError());
-    uv_insert_pending_req(loop, req);
-  }
-}
-
-
-static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
-  AFD_POLL_INFO afd_poll_info;
-  int result;
-
-  afd_poll_info.Exclusive = TRUE;
-  afd_poll_info.NumberOfHandles = 1;
-  afd_poll_info.Timeout.QuadPart = INT64_MAX;
-  afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket;
-  afd_poll_info.Handles[0].Status = 0;
-  afd_poll_info.Handles[0].Events = AFD_POLL_ALL;
-
-  result = uv_msafd_poll(handle->socket,
-                         &afd_poll_info,
-                         uv__get_afd_poll_info_dummy(),
-                         uv__get_overlapped_dummy());
-
-  if (result == SOCKET_ERROR) {
-    DWORD error = WSAGetLastError();
-    if (error != WSA_IO_PENDING)
-      return error;
-  }
-
-  return 0;
-}
-
-
-static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
-    uv_req_t* req) {
-  unsigned char mask_events;
-  AFD_POLL_INFO* afd_poll_info;
-
-  if (req == &handle->poll_req_1) {
-    afd_poll_info = &handle->afd_poll_info_1;
-    handle->submitted_events_1 = 0;
-    mask_events = handle->mask_events_1;
-  } else if (req == &handle->poll_req_2) {
-    afd_poll_info = &handle->afd_poll_info_2;
-    handle->submitted_events_2 = 0;
-    mask_events = handle->mask_events_2;
-  } else {
-    assert(0);
-    return;
-  }
-
-  /* Report an error unless the select was just interrupted. */
-  if (!REQ_SUCCESS(req)) {
-    DWORD error = GET_REQ_SOCK_ERROR(req);
-    if (error != WSAEINTR && handle->events != 0) {
-      handle->events = 0; /* Stop the watcher */
-      handle->poll_cb(handle, uv_translate_sys_error(error), 0);
-    }
-
-  } else if (afd_poll_info->NumberOfHandles >= 1) {
-    unsigned char events = 0;
-
-    if ((afd_poll_info->Handles[0].Events & (AFD_POLL_RECEIVE |
-        AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT | AFD_POLL_ABORT)) != 0) {
-      events |= UV_READABLE;
-      if ((afd_poll_info->Handles[0].Events & AFD_POLL_DISCONNECT) != 0) {
-        events |= UV_DISCONNECT;
-      }
-    }
-    if ((afd_poll_info->Handles[0].Events & (AFD_POLL_SEND |
-        AFD_POLL_CONNECT_FAIL)) != 0) {
-      events |= UV_WRITABLE;
-    }
-
-    events &= handle->events & ~mask_events;
-
-    if (afd_poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) {
-      /* Stop polling. */
-      handle->events = 0;
-      if (uv__is_active(handle))
-        uv__handle_stop(handle);
-    }
-
-    if (events != 0) {
-      handle->poll_cb(handle, 0, events);
-    }
-  }
-
-  if ((handle->events & ~(handle->submitted_events_1 |
-      handle->submitted_events_2)) != 0) {
-    uv__fast_poll_submit_poll_req(loop, handle);
-  } else if ((handle->flags & UV_HANDLE_CLOSING) &&
-             handle->submitted_events_1 == 0 &&
-             handle->submitted_events_2 == 0) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-  }
-}
-
-
-static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
-  assert(handle->type == UV_POLL);
-  assert(!(handle->flags & UV_HANDLE_CLOSING));
-  assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
-
-  handle->events = events;
-
-  if (handle->events != 0) {
-    uv__handle_start(handle);
-  } else {
-    uv__handle_stop(handle);
-  }
-
-  if ((handle->events & ~(handle->submitted_events_1 |
-      handle->submitted_events_2)) != 0) {
-    uv__fast_poll_submit_poll_req(handle->loop, handle);
-  }
-
-  return 0;
-}
-
-
-static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
-  handle->events = 0;
-  uv__handle_closing(handle);
-
-  if (handle->submitted_events_1 == 0 &&
-      handle->submitted_events_2 == 0) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-    return 0;
-  } else {
-    /* Cancel outstanding poll requests by executing another, unique poll
-     * request that forces the outstanding ones to return. */
-    return uv__fast_poll_cancel_poll_req(loop, handle);
-  }
-}
-
-
-static SOCKET uv__fast_poll_create_peer_socket(HANDLE iocp,
-    WSAPROTOCOL_INFOW* protocol_info) {
-  SOCKET sock = 0;
-
-  sock = WSASocketW(protocol_info->iAddressFamily,
-                    protocol_info->iSocketType,
-                    protocol_info->iProtocol,
-                    protocol_info,
-                    0,
-                    WSA_FLAG_OVERLAPPED);
-  if (sock == INVALID_SOCKET) {
-    return INVALID_SOCKET;
-  }
-
-  if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) {
-    goto error;
-  };
-
-  if (CreateIoCompletionPort((HANDLE) sock,
-                             iocp,
-                             (ULONG_PTR) sock,
-                             0) == NULL) {
-    goto error;
-  }
-
-  return sock;
-
- error:
-  closesocket(sock);
-  return INVALID_SOCKET;
-}
-
-
-static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop,
-    WSAPROTOCOL_INFOW* protocol_info) {
-  int index, i;
-  SOCKET peer_socket;
-
-  index = -1;
-  for (i = 0; (size_t) i < ARRAY_SIZE(uv_msafd_provider_ids); i++) {
-    if (memcmp((void*) &protocol_info->ProviderId,
-               (void*) &uv_msafd_provider_ids[i],
-               sizeof protocol_info->ProviderId) == 0) {
-      index = i;
-    }
-  }
-
-  /* Check if the protocol uses an msafd socket. */
-  if (index < 0) {
-    return INVALID_SOCKET;
-  }
-
-  /* If we didn't (try) to create a peer socket yet, try to make one. Don't try
-   * again if the peer socket creation failed earlier for the same protocol. */
-  peer_socket = loop->poll_peer_sockets[index];
-  if (peer_socket == 0) {
-    peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info);
-    loop->poll_peer_sockets[index] = peer_socket;
-  }
-
-  return peer_socket;
-}
-
-
-static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) {
-  uv_req_t* req = (uv_req_t*) arg;
-  uv_poll_t* handle = (uv_poll_t*) req->data;
-  unsigned char reported_events;
-  int r;
-  uv_single_fd_set_t rfds, wfds, efds;
-  struct timeval timeout;
-
-  assert(handle->type == UV_POLL);
-  assert(req->type == UV_POLL_REQ);
-
-  if (handle->events & UV_READABLE) {
-    rfds.fd_count = 1;
-    rfds.fd_array[0] = handle->socket;
-  } else {
-    rfds.fd_count = 0;
-  }
-
-  if (handle->events & UV_WRITABLE) {
-    wfds.fd_count = 1;
-    wfds.fd_array[0] = handle->socket;
-    efds.fd_count = 1;
-    efds.fd_array[0] = handle->socket;
-  } else {
-    wfds.fd_count = 0;
-    efds.fd_count = 0;
-  }
-
-  /* Make the select() time out after 3 minutes. If select() hangs because the
-   * user closed the socket, we will at least not hang indefinitely. */
-  timeout.tv_sec = 3 * 60;
-  timeout.tv_usec = 0;
-
-  r = select(1, (fd_set*) &rfds, (fd_set*) &wfds, (fd_set*) &efds, &timeout);
-  if (r == SOCKET_ERROR) {
-    /* Queue this req, reporting an error. */
-    SET_REQ_ERROR(&handle->poll_req_1, WSAGetLastError());
-    POST_COMPLETION_FOR_REQ(handle->loop, req);
-    return 0;
-  }
-
-  reported_events = 0;
-
-  if (r > 0) {
-    if (rfds.fd_count > 0) {
-      assert(rfds.fd_count == 1);
-      assert(rfds.fd_array[0] == handle->socket);
-      reported_events |= UV_READABLE;
-    }
-
-    if (wfds.fd_count > 0) {
-      assert(wfds.fd_count == 1);
-      assert(wfds.fd_array[0] == handle->socket);
-      reported_events |= UV_WRITABLE;
-    } else if (efds.fd_count > 0) {
-      assert(efds.fd_count == 1);
-      assert(efds.fd_array[0] == handle->socket);
-      reported_events |= UV_WRITABLE;
-    }
-  }
-
-  SET_REQ_SUCCESS(req);
-  req->u.io.overlapped.InternalHigh = (DWORD) reported_events;
-  POST_COMPLETION_FOR_REQ(handle->loop, req);
-
-  return 0;
-}
-
-
-static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) {
-  uv_req_t* req;
-
-  /* Find a yet unsubmitted req to submit. */
-  if (handle->submitted_events_1 == 0) {
-    req = &handle->poll_req_1;
-    handle->submitted_events_1 = handle->events;
-    handle->mask_events_1 = 0;
-    handle->mask_events_2 = handle->events;
-  } else if (handle->submitted_events_2 == 0) {
-    req = &handle->poll_req_2;
-    handle->submitted_events_2 = handle->events;
-    handle->mask_events_1 = handle->events;
-    handle->mask_events_2 = 0;
-  } else {
-    assert(0);
-    return;
-  }
-
-  if (!QueueUserWorkItem(uv__slow_poll_thread_proc,
-                         (void*) req,
-                         WT_EXECUTELONGFUNCTION)) {
-    /* Make this req pending, reporting an error. */
-    SET_REQ_ERROR(req, GetLastError());
-    uv_insert_pending_req(loop, req);
-  }
-}
-
-
-
-static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle,
-    uv_req_t* req) {
-  unsigned char mask_events;
-  int err;
-
-  if (req == &handle->poll_req_1) {
-    handle->submitted_events_1 = 0;
-    mask_events = handle->mask_events_1;
-  } else if (req == &handle->poll_req_2) {
-    handle->submitted_events_2 = 0;
-    mask_events = handle->mask_events_2;
-  } else {
-    assert(0);
-    return;
-  }
-
-  if (!REQ_SUCCESS(req)) {
-    /* Error. */
-    if (handle->events != 0) {
-      err = GET_REQ_ERROR(req);
-      handle->events = 0; /* Stop the watcher */
-      handle->poll_cb(handle, uv_translate_sys_error(err), 0);
-    }
-  } else {
-    /* Got some events. */
-    int events = req->u.io.overlapped.InternalHigh & handle->events & ~mask_events;
-    if (events != 0) {
-      handle->poll_cb(handle, 0, events);
-    }
-  }
-
-  if ((handle->events & ~(handle->submitted_events_1 |
-      handle->submitted_events_2)) != 0) {
-    uv__slow_poll_submit_poll_req(loop, handle);
-  } else if ((handle->flags & UV_HANDLE_CLOSING) &&
-             handle->submitted_events_1 == 0 &&
-             handle->submitted_events_2 == 0) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-  }
-}
-
-
-static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) {
-  assert(handle->type == UV_POLL);
-  assert(!(handle->flags & UV_HANDLE_CLOSING));
-  assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0);
-
-  handle->events = events;
-
-  if (handle->events != 0) {
-    uv__handle_start(handle);
-  } else {
-    uv__handle_stop(handle);
-  }
-
-  if ((handle->events &
-      ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) {
-    uv__slow_poll_submit_poll_req(handle->loop, handle);
-  }
-
-  return 0;
-}
-
-
-static int uv__slow_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
-  handle->events = 0;
-  uv__handle_closing(handle);
-
-  if (handle->submitted_events_1 == 0 &&
-      handle->submitted_events_2 == 0) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-  }
-
-  return 0;
-}
-
-
-int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
-  return uv_poll_init_socket(loop, handle, (SOCKET) uv__get_osfhandle(fd));
-}
-
-
-int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
-    uv_os_sock_t socket) {
-  WSAPROTOCOL_INFOW protocol_info;
-  int len;
-  SOCKET peer_socket, base_socket;
-  DWORD bytes;
-  DWORD yes = 1;
-
-  /* Set the socket to nonblocking mode */
-  if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR)
-    return uv_translate_sys_error(WSAGetLastError());
-
-/* Try to obtain a base handle for the socket. This increases this chances that
- * we find an AFD handle and are able to use the fast poll mechanism. This will
- * always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE
- * ioctl. */
-#ifndef NDEBUG
-  base_socket = INVALID_SOCKET;
-#endif
-
-  if (WSAIoctl(socket,
-               SIO_BASE_HANDLE,
-               NULL,
-               0,
-               &base_socket,
-               sizeof base_socket,
-               &bytes,
-               NULL,
-               NULL) == 0) {
-    assert(base_socket != 0 && base_socket != INVALID_SOCKET);
-    socket = base_socket;
-  }
-
-  uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL);
-  handle->socket = socket;
-  handle->events = 0;
-
-  /* Obtain protocol information about the socket. */
-  len = sizeof protocol_info;
-  if (getsockopt(socket,
-                 SOL_SOCKET,
-                 SO_PROTOCOL_INFOW,
-                 (char*) &protocol_info,
-                 &len) != 0) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
-
-  /* Get the peer socket that is needed to enable fast poll. If the returned
-   * value is NULL, the protocol is not implemented by MSAFD and we'll have to
-   * use slow mode. */
-  peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info);
-
-  if (peer_socket != INVALID_SOCKET) {
-    /* Initialize fast poll specific fields. */
-    handle->peer_socket = peer_socket;
-  } else {
-    /* Initialize slow poll specific fields. */
-    handle->flags |= UV_HANDLE_POLL_SLOW;
-  }
-
-  /* Initialize 2 poll reqs. */
-  handle->submitted_events_1 = 0;
-  UV_REQ_INIT(&handle->poll_req_1, UV_POLL_REQ);
-  handle->poll_req_1.data = handle;
-
-  handle->submitted_events_2 = 0;
-  UV_REQ_INIT(&handle->poll_req_2, UV_POLL_REQ);
-  handle->poll_req_2.data = handle;
-
-  return 0;
-}
-
-
-int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb) {
-  int err;
-
-  if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
-    err = uv__fast_poll_set(handle->loop, handle, events);
-  } else {
-    err = uv__slow_poll_set(handle->loop, handle, events);
-  }
-
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  handle->poll_cb = cb;
-
-  return 0;
-}
-
-
-int uv_poll_stop(uv_poll_t* handle) {
-  int err;
-
-  if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
-    err = uv__fast_poll_set(handle->loop, handle, 0);
-  } else {
-    err = uv__slow_poll_set(handle->loop, handle, 0);
-  }
-
-  return uv_translate_sys_error(err);
-}
-
-
-void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) {
-  if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
-    uv__fast_poll_process_poll_req(loop, handle, req);
-  } else {
-    uv__slow_poll_process_poll_req(loop, handle, req);
-  }
-}
-
-
-int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) {
-  if (!(handle->flags & UV_HANDLE_POLL_SLOW)) {
-    return uv__fast_poll_close(loop, handle);
-  } else {
-    return uv__slow_poll_close(loop, handle);
-  }
-}
-
-
-void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) {
-  assert(handle->flags & UV_HANDLE_CLOSING);
-  assert(!(handle->flags & UV_HANDLE_CLOSED));
-
-  assert(handle->submitted_events_1 == 0);
-  assert(handle->submitted_events_2 == 0);
-
-  uv__handle_close(handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/process-stdio.cpp b/wpiutil/src/main/native/libuv/src/win/process-stdio.cpp
deleted file mode 100644
index 4701938..0000000
--- a/wpiutil/src/main/native/libuv/src/win/process-stdio.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <io.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-
-
-/*
- * The `child_stdio_buffer` buffer has the following layout:
- *   int number_of_fds
- *   unsigned char crt_flags[number_of_fds]
- *   HANDLE os_handle[number_of_fds]
- */
-#define CHILD_STDIO_SIZE(count)                     \
-    (sizeof(int) +                                  \
-     sizeof(unsigned char) * (count) +              \
-     sizeof(uintptr_t) * (count))
-
-#define CHILD_STDIO_COUNT(buffer)                   \
-    *((unsigned int*) (buffer))
-
-#define CHILD_STDIO_CRT_FLAGS(buffer, fd)           \
-    *((unsigned char*) (buffer) + sizeof(int) + fd)
-
-#define CHILD_STDIO_HANDLE(buffer, fd)              \
-    *((HANDLE*) ((unsigned char*) (buffer) +        \
-                 sizeof(int) +                      \
-                 sizeof(unsigned char) *            \
-                 CHILD_STDIO_COUNT((buffer)) +      \
-                 sizeof(HANDLE) * (fd)))
-
-
-/* CRT file descriptor mode flags */
-#define FOPEN       0x01
-#define FEOFLAG     0x02
-#define FCRLF       0x04
-#define FPIPE       0x08
-#define FNOINHERIT  0x10
-#define FAPPEND     0x20
-#define FDEV        0x40
-#define FTEXT       0x80
-
-
-/*
- * Clear the HANDLE_FLAG_INHERIT flag from all HANDLEs that were inherited
- * the parent process. Don't check for errors - the stdio handles may not be
- * valid, or may be closed already. There is no guarantee that this function
- * does a perfect job.
- */
-void uv_disable_stdio_inheritance(void) {
-  HANDLE handle;
-  STARTUPINFOW si;
-
-  /* Make the windows stdio handles non-inheritable. */
-  handle = GetStdHandle(STD_INPUT_HANDLE);
-  if (handle != NULL && handle != INVALID_HANDLE_VALUE)
-    SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
-
-  handle = GetStdHandle(STD_OUTPUT_HANDLE);
-  if (handle != NULL && handle != INVALID_HANDLE_VALUE)
-    SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
-
-  handle = GetStdHandle(STD_ERROR_HANDLE);
-  if (handle != NULL && handle != INVALID_HANDLE_VALUE)
-    SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
-
-  /* Make inherited CRT FDs non-inheritable. */
-  GetStartupInfoW(&si);
-  if (uv__stdio_verify(si.lpReserved2, si.cbReserved2))
-    uv__stdio_noinherit(si.lpReserved2);
-}
-
-
-static int uv__create_stdio_pipe_pair(uv_loop_t* loop,
-    uv_pipe_t* server_pipe, HANDLE* child_pipe_ptr, unsigned int flags) {
-  char pipe_name[64];
-  SECURITY_ATTRIBUTES sa;
-  DWORD server_access = 0;
-  DWORD client_access = 0;
-  HANDLE child_pipe = INVALID_HANDLE_VALUE;
-  int err;
-  BOOL overlap;
-
-  if (flags & UV_READABLE_PIPE) {
-    /* The server needs inbound access too, otherwise CreateNamedPipe() won't
-     * give us the FILE_READ_ATTRIBUTES permission. We need that to probe the
-     * state of the write buffer when we're trying to shutdown the pipe. */
-    server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND;
-    client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
-  }
-  if (flags & UV_WRITABLE_PIPE) {
-    server_access |= PIPE_ACCESS_INBOUND;
-    client_access |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
-  }
-
-  /* Create server pipe handle. */
-  err = uv_stdio_pipe_server(loop,
-                             server_pipe,
-                             server_access,
-                             pipe_name,
-                             sizeof(pipe_name));
-  if (err)
-    goto error;
-
-  /* Create child pipe handle. */
-  sa.nLength = sizeof sa;
-  sa.lpSecurityDescriptor = NULL;
-  sa.bInheritHandle = TRUE;
-
-  overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE);
-  child_pipe = CreateFileA(pipe_name,
-                           client_access,
-                           0,
-                           &sa,
-                           OPEN_EXISTING,
-                           overlap ? FILE_FLAG_OVERLAPPED : 0,
-                           NULL);
-  if (child_pipe == INVALID_HANDLE_VALUE) {
-    err = GetLastError();
-    goto error;
-  }
-
-#ifndef NDEBUG
-  /* Validate that the pipe was opened in the right mode. */
-  {
-    DWORD mode;
-    BOOL r = GetNamedPipeHandleState(child_pipe,
-                                     &mode,
-                                     NULL,
-                                     NULL,
-                                     NULL,
-                                     NULL,
-                                     0);
-    assert(r == TRUE);
-    assert(mode == (PIPE_READMODE_BYTE | PIPE_WAIT));
-  }
-#endif
-
-  /* Do a blocking ConnectNamedPipe. This should not block because we have both
-   * ends of the pipe created. */
-  if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
-    if (GetLastError() != ERROR_PIPE_CONNECTED) {
-      err = GetLastError();
-      goto error;
-    }
-  }
-
-  /* The server end is now readable and/or writable. */
-  if (flags & UV_READABLE_PIPE)
-    server_pipe->flags |= UV_HANDLE_WRITABLE;
-  if (flags & UV_WRITABLE_PIPE)
-    server_pipe->flags |= UV_HANDLE_READABLE;
-
-  *child_pipe_ptr = child_pipe;
-  return 0;
-
- error:
-  if (server_pipe->handle != INVALID_HANDLE_VALUE) {
-    uv_pipe_cleanup(loop, server_pipe);
-  }
-
-  if (child_pipe != INVALID_HANDLE_VALUE) {
-    CloseHandle(child_pipe);
-  }
-
-  return err;
-}
-
-
-static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) {
-  HANDLE current_process;
-
-
-  /* _get_osfhandle will sometimes return -2 in case of an error. This seems to
-   * happen when fd <= 2 and the process' corresponding stdio handle is set to
-   * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so
-   * this situation goes unnoticed until someone tries to use the duplicate.
-   * Therefore we filter out known-invalid handles here. */
-  if (handle == INVALID_HANDLE_VALUE ||
-      handle == NULL ||
-      handle == (HANDLE) -2) {
-    *dup = INVALID_HANDLE_VALUE;
-    return ERROR_INVALID_HANDLE;
-  }
-
-  current_process = GetCurrentProcess();
-
-  if (!DuplicateHandle(current_process,
-                       handle,
-                       current_process,
-                       dup,
-                       0,
-                       TRUE,
-                       DUPLICATE_SAME_ACCESS)) {
-    *dup = INVALID_HANDLE_VALUE;
-    return GetLastError();
-  }
-
-  return 0;
-}
-
-
-static int uv__duplicate_fd(uv_loop_t* loop, int fd, HANDLE* dup) {
-  HANDLE handle;
-
-  if (fd == -1) {
-    *dup = INVALID_HANDLE_VALUE;
-    return ERROR_INVALID_HANDLE;
-  }
-
-  handle = uv__get_osfhandle(fd);
-  return uv__duplicate_handle(loop, handle, dup);
-}
-
-
-int uv__create_nul_handle(HANDLE* handle_ptr,
-    DWORD access) {
-  HANDLE handle;
-  SECURITY_ATTRIBUTES sa;
-
-  sa.nLength = sizeof sa;
-  sa.lpSecurityDescriptor = NULL;
-  sa.bInheritHandle = TRUE;
-
-  handle = CreateFileW(L"NUL",
-                       access,
-                       FILE_SHARE_READ | FILE_SHARE_WRITE,
-                       &sa,
-                       OPEN_EXISTING,
-                       0,
-                       NULL);
-  if (handle == INVALID_HANDLE_VALUE) {
-    return GetLastError();
-  }
-
-  *handle_ptr = handle;
-  return 0;
-}
-
-
-int uv__stdio_create(uv_loop_t* loop,
-                     const uv_process_options_t* options,
-                     BYTE** buffer_ptr) {
-  BYTE* buffer;
-  int count, i;
-  int err;
-
-  count = options->stdio_count;
-
-  if (count < 0 || count > 255) {
-    /* Only support FDs 0-255 */
-    return ERROR_NOT_SUPPORTED;
-  } else if (count < 3) {
-    /* There should always be at least 3 stdio handles. */
-    count = 3;
-  }
-
-  /* Allocate the child stdio buffer */
-  buffer = (BYTE*) uv__malloc(CHILD_STDIO_SIZE(count));
-  if (buffer == NULL) {
-    return ERROR_OUTOFMEMORY;
-  }
-
-  /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean
-   * up on failure. */
-  CHILD_STDIO_COUNT(buffer) = count;
-  for (i = 0; i < count; i++) {
-    CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
-    CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
-  }
-
-  for (i = 0; i < count; i++) {
-    uv_stdio_container_t fdopt;
-    if (i < options->stdio_count) {
-      fdopt = options->stdio[i];
-    } else {
-      fdopt.flags = UV_IGNORE;
-    }
-
-    switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD |
-            UV_INHERIT_STREAM)) {
-      case UV_IGNORE:
-        /* Starting a process with no stdin/stout/stderr can confuse it. So no
-         * matter what the user specified, we make sure the first three FDs are
-         * always open in their typical modes, e. g. stdin be readable and
-         * stdout/err should be writable. For FDs > 2, don't do anything - all
-         * handles in the stdio buffer are initialized with.
-         * INVALID_HANDLE_VALUE, which should be okay. */
-        if (i <= 2) {
-          DWORD access = (i == 0) ? FILE_GENERIC_READ :
-                                    FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES;
-
-          err = uv__create_nul_handle(&CHILD_STDIO_HANDLE(buffer, i),
-                                      access);
-          if (err)
-            goto error;
-
-          CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
-        }
-        break;
-
-      case UV_CREATE_PIPE: {
-        /* Create a pair of two connected pipe ends; one end is turned into an
-         * uv_pipe_t for use by the parent. The other one is given to the
-         * child. */
-        uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream;
-        HANDLE child_pipe = INVALID_HANDLE_VALUE;
-
-        /* Create a new, connected pipe pair. stdio[i]. stream should point to
-         * an uninitialized, but not connected pipe handle. */
-        assert(fdopt.data.stream->type == UV_NAMED_PIPE);
-        assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION));
-        assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER));
-
-        err = uv__create_stdio_pipe_pair(loop,
-                                         parent_pipe,
-                                         &child_pipe,
-                                         fdopt.flags);
-        if (err)
-          goto error;
-
-        CHILD_STDIO_HANDLE(buffer, i) = child_pipe;
-        CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
-        break;
-      }
-
-      case UV_INHERIT_FD: {
-        /* Inherit a raw FD. */
-        HANDLE child_handle;
-
-        /* Make an inheritable duplicate of the handle. */
-        err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle);
-        if (err) {
-          /* If fdopt. data. fd is not valid and fd <= 2, then ignore the
-           * error. */
-          if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) {
-            CHILD_STDIO_CRT_FLAGS(buffer, i) = 0;
-            CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE;
-            break;
-          }
-          goto error;
-        }
-
-        /* Figure out what the type is. */
-        switch (GetFileType(child_handle)) {
-          case FILE_TYPE_DISK:
-            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN;
-            break;
-
-          case FILE_TYPE_PIPE:
-            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
-            break;
-
-          case FILE_TYPE_CHAR:
-          case FILE_TYPE_REMOTE:
-            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
-            break;
-
-          case FILE_TYPE_UNKNOWN:
-            if (GetLastError() != 0) {
-              err = GetLastError();
-              CloseHandle(child_handle);
-              goto error;
-            }
-            CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FDEV;
-            break;
-
-          default:
-            assert(0);
-            return -1;
-        }
-
-        CHILD_STDIO_HANDLE(buffer, i) = child_handle;
-        break;
-      }
-
-      case UV_INHERIT_STREAM: {
-        /* Use an existing stream as the stdio handle for the child. */
-        HANDLE stream_handle, child_handle;
-        unsigned char crt_flags;
-        uv_stream_t* stream = fdopt.data.stream;
-
-        /* Leech the handle out of the stream. */
-        if (stream->type == UV_TTY) {
-          stream_handle = ((uv_tty_t*) stream)->handle;
-          crt_flags = FOPEN | FDEV;
-        } else if (stream->type == UV_NAMED_PIPE &&
-                   stream->flags & UV_HANDLE_CONNECTION) {
-          stream_handle = ((uv_pipe_t*) stream)->handle;
-          crt_flags = FOPEN | FPIPE;
-        } else {
-          stream_handle = INVALID_HANDLE_VALUE;
-          crt_flags = 0;
-        }
-
-        if (stream_handle == NULL ||
-            stream_handle == INVALID_HANDLE_VALUE) {
-          /* The handle is already closed, or not yet created, or the stream
-           * type is not supported. */
-          err = ERROR_NOT_SUPPORTED;
-          goto error;
-        }
-
-        /* Make an inheritable copy of the handle. */
-        err = uv__duplicate_handle(loop, stream_handle, &child_handle);
-        if (err)
-          goto error;
-
-        CHILD_STDIO_HANDLE(buffer, i) = child_handle;
-        CHILD_STDIO_CRT_FLAGS(buffer, i) = crt_flags;
-        break;
-      }
-
-      default:
-        assert(0);
-        return -1;
-    }
-  }
-
-  *buffer_ptr  = buffer;
-  return 0;
-
- error:
-  uv__stdio_destroy(buffer);
-  return err;
-}
-
-
-void uv__stdio_destroy(BYTE* buffer) {
-  int i, count;
-
-  count = CHILD_STDIO_COUNT(buffer);
-  for (i = 0; i < count; i++) {
-    HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
-    if (handle != INVALID_HANDLE_VALUE) {
-      CloseHandle(handle);
-    }
-  }
-
-  uv__free(buffer);
-}
-
-
-void uv__stdio_noinherit(BYTE* buffer) {
-  int i, count;
-
-  count = CHILD_STDIO_COUNT(buffer);
-  for (i = 0; i < count; i++) {
-    HANDLE handle = CHILD_STDIO_HANDLE(buffer, i);
-    if (handle != INVALID_HANDLE_VALUE) {
-      SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
-    }
-  }
-}
-
-
-int uv__stdio_verify(BYTE* buffer, WORD size) {
-  unsigned int count;
-
-  /* Check the buffer pointer. */
-  if (buffer == NULL)
-    return 0;
-
-  /* Verify that the buffer is at least big enough to hold the count. */
-  if (size < CHILD_STDIO_SIZE(0))
-    return 0;
-
-  /* Verify if the count is within range. */
-  count = CHILD_STDIO_COUNT(buffer);
-  if (count > 256)
-    return 0;
-
-  /* Verify that the buffer size is big enough to hold info for N FDs. */
-  if (size < CHILD_STDIO_SIZE(count))
-    return 0;
-
-  return 1;
-}
-
-
-WORD uv__stdio_size(BYTE* buffer) {
-  return (WORD) CHILD_STDIO_SIZE(CHILD_STDIO_COUNT((buffer)));
-}
-
-
-HANDLE uv__stdio_handle(BYTE* buffer, int fd) {
-  return CHILD_STDIO_HANDLE(buffer, fd);
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/process.cpp b/wpiutil/src/main/native/libuv/src/win/process.cpp
deleted file mode 100644
index 3b8675a..0000000
--- a/wpiutil/src/main/native/libuv/src/win/process.cpp
+++ /dev/null
@@ -1,1284 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#define _CRT_NONSTDC_NO_WARNINGS
-
-#include <assert.h>
-#include <io.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <limits.h>
-#include <wchar.h>
-#include <malloc.h>    /* alloca */
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "req-inl.h"
-
-#define SIGKILL         9
-
-
-typedef struct env_var {
-  const WCHAR* const wide;
-  const WCHAR* const wide_eq;
-  const size_t len; /* including null or '=' */
-} env_var_t;
-
-#define E_V(str) { L##str, L##str L"=", sizeof(str) }
-
-static const env_var_t required_vars[] = { /* keep me sorted */
-  E_V("HOMEDRIVE"),
-  E_V("HOMEPATH"),
-  E_V("LOGONSERVER"),
-  E_V("PATH"),
-  E_V("SYSTEMDRIVE"),
-  E_V("SYSTEMROOT"),
-  E_V("TEMP"),
-  E_V("USERDOMAIN"),
-  E_V("USERNAME"),
-  E_V("USERPROFILE"),
-  E_V("WINDIR"),
-};
-static size_t n_required_vars = ARRAY_SIZE(required_vars);
-
-
-static HANDLE uv_global_job_handle_;
-static uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT;
-
-
-static void uv__init_global_job_handle(void) {
-  /* Create a job object and set it up to kill all contained processes when
-   * it's closed. Since this handle is made non-inheritable and we're not
-   * giving it to anyone, we're the only process holding a reference to it.
-   * That means that if this process exits it is closed and all the processes
-   * it contains are killed. All processes created with uv_spawn that are not
-   * spawned with the UV_PROCESS_DETACHED flag are assigned to this job.
-   *
-   * We're setting the JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag so only the
-   * processes that we explicitly add are affected, and *their* subprocesses
-   * are not. This ensures that our child processes are not limited in their
-   * ability to use job control on Windows versions that don't deal with
-   * nested jobs (prior to Windows 8 / Server 2012). It also lets our child
-   * processes created detached processes without explicitly breaking away
-   * from job control (which uv_spawn doesn't, either).
-   */
-  SECURITY_ATTRIBUTES attr;
-  JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
-
-  memset(&attr, 0, sizeof attr);
-  attr.bInheritHandle = FALSE;
-
-  memset(&info, 0, sizeof info);
-  info.BasicLimitInformation.LimitFlags =
-      JOB_OBJECT_LIMIT_BREAKAWAY_OK |
-      JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK |
-      JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |
-      JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
-
-  uv_global_job_handle_ = CreateJobObjectW(&attr, NULL);
-  if (uv_global_job_handle_ == NULL)
-    uv_fatal_error(GetLastError(), "CreateJobObjectW");
-
-  if (!SetInformationJobObject(uv_global_job_handle_,
-                               JobObjectExtendedLimitInformation,
-                               &info,
-                               sizeof info))
-    uv_fatal_error(GetLastError(), "SetInformationJobObject");
-}
-
-
-static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
-  int ws_len, r;
-  WCHAR* ws;
-
-  ws_len = MultiByteToWideChar(CP_UTF8,
-                               0,
-                               s,
-                               -1,
-                               NULL,
-                               0);
-  if (ws_len <= 0) {
-    return GetLastError();
-  }
-
-  ws = (WCHAR*) uv__malloc(ws_len * sizeof(WCHAR));
-  if (ws == NULL) {
-    return ERROR_OUTOFMEMORY;
-  }
-
-  r = MultiByteToWideChar(CP_UTF8,
-                          0,
-                          s,
-                          -1,
-                          ws,
-                          ws_len);
-  assert(r == ws_len);
-
-  *ws_ptr = ws;
-  return 0;
-}
-
-
-static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) {
-  uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS);
-  handle->exit_cb = NULL;
-  handle->pid = 0;
-  handle->exit_signal = 0;
-  handle->wait_handle = INVALID_HANDLE_VALUE;
-  handle->process_handle = INVALID_HANDLE_VALUE;
-  handle->child_stdio_buffer = NULL;
-  handle->exit_cb_pending = 0;
-
-  UV_REQ_INIT(&handle->exit_req, UV_PROCESS_EXIT);
-  handle->exit_req.data = handle;
-}
-
-
-/*
- * Path search functions
- */
-
-/*
- * Helper function for search_path
- */
-static WCHAR* search_path_join_test(const WCHAR* dir,
-                                    size_t dir_len,
-                                    const WCHAR* name,
-                                    size_t name_len,
-                                    const WCHAR* ext,
-                                    size_t ext_len,
-                                    const WCHAR* cwd,
-                                    size_t cwd_len) {
-  WCHAR *result, *result_pos;
-  DWORD attrs;
-  if (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') {
-    /* It's a UNC path so ignore cwd */
-    cwd_len = 0;
-  } else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) {
-    /* It's a full path without drive letter, use cwd's drive letter only */
-    cwd_len = 2;
-  } else if (dir_len >= 2 && dir[1] == L':' &&
-      (dir_len < 3 || (dir[2] != L'/' && dir[2] != L'\\'))) {
-    /* It's a relative path with drive letter (ext.g. D:../some/file)
-     * Replace drive letter in dir by full cwd if it points to the same drive,
-     * otherwise use the dir only.
-     */
-    if (cwd_len < 2 || _wcsnicmp(cwd, dir, 2) != 0) {
-      cwd_len = 0;
-    } else {
-      dir += 2;
-      dir_len -= 2;
-    }
-  } else if (dir_len > 2 && dir[1] == L':') {
-    /* It's an absolute path with drive letter
-     * Don't use the cwd at all
-     */
-    cwd_len = 0;
-  }
-
-  /* Allocate buffer for output */
-  result = result_pos = (WCHAR*)uv__malloc(sizeof(WCHAR) *
-      (cwd_len + 1 + dir_len + 1 + name_len + 1 + ext_len + 1));
-
-  /* Copy cwd */
-  wcsncpy(result_pos, cwd, cwd_len);
-  result_pos += cwd_len;
-
-  /* Add a path separator if cwd didn't end with one */
-  if (cwd_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {
-    result_pos[0] = L'\\';
-    result_pos++;
-  }
-
-  /* Copy dir */
-  wcsncpy(result_pos, dir, dir_len);
-  result_pos += dir_len;
-
-  /* Add a separator if the dir didn't end with one */
-  if (dir_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {
-    result_pos[0] = L'\\';
-    result_pos++;
-  }
-
-  /* Copy filename */
-  wcsncpy(result_pos, name, name_len);
-  result_pos += name_len;
-
-  if (ext_len) {
-    /* Add a dot if the filename didn't end with one */
-    if (name_len && result_pos[-1] != '.') {
-      result_pos[0] = L'.';
-      result_pos++;
-    }
-
-    /* Copy extension */
-    wcsncpy(result_pos, ext, ext_len);
-    result_pos += ext_len;
-  }
-
-  /* Null terminator */
-  result_pos[0] = L'\0';
-
-  attrs = GetFileAttributesW(result);
-
-  if (attrs != INVALID_FILE_ATTRIBUTES &&
-      !(attrs & FILE_ATTRIBUTE_DIRECTORY)) {
-    return result;
-  }
-
-  uv__free(result);
-  return NULL;
-}
-
-
-/*
- * Helper function for search_path
- */
-static WCHAR* path_search_walk_ext(const WCHAR *dir,
-                                   size_t dir_len,
-                                   const WCHAR *name,
-                                   size_t name_len,
-                                   WCHAR *cwd,
-                                   size_t cwd_len,
-                                   int name_has_ext) {
-  WCHAR* result;
-
-  /* If the name itself has a nonempty extension, try this extension first */
-  if (name_has_ext) {
-    result = search_path_join_test(dir, dir_len,
-                                   name, name_len,
-                                   L"", 0,
-                                   cwd, cwd_len);
-    if (result != NULL) {
-      return result;
-    }
-  }
-
-  /* Try .com extension */
-  result = search_path_join_test(dir, dir_len,
-                                 name, name_len,
-                                 L"com", 3,
-                                 cwd, cwd_len);
-  if (result != NULL) {
-    return result;
-  }
-
-  /* Try .exe extension */
-  result = search_path_join_test(dir, dir_len,
-                                 name, name_len,
-                                 L"exe", 3,
-                                 cwd, cwd_len);
-  if (result != NULL) {
-    return result;
-  }
-
-  return NULL;
-}
-
-
-/*
- * search_path searches the system path for an executable filename -
- * the windows API doesn't provide this as a standalone function nor as an
- * option to CreateProcess.
- *
- * It tries to return an absolute filename.
- *
- * Furthermore, it tries to follow the semantics that cmd.exe, with this
- * exception that PATHEXT environment variable isn't used. Since CreateProcess
- * can start only .com and .exe files, only those extensions are tried. This
- * behavior equals that of msvcrt's spawn functions.
- *
- * - Do not search the path if the filename already contains a path (either
- *   relative or absolute).
- *
- * - If there's really only a filename, check the current directory for file,
- *   then search all path directories.
- *
- * - If filename specified has *any* extension, search for the file with the
- *   specified extension first.
- *
- * - If the literal filename is not found in a directory, try *appending*
- *   (not replacing) .com first and then .exe.
- *
- * - The path variable may contain relative paths; relative paths are relative
- *   to the cwd.
- *
- * - Directories in path may or may not end with a trailing backslash.
- *
- * - CMD does not trim leading/trailing whitespace from path/pathex entries
- *   nor from the environment variables as a whole.
- *
- * - When cmd.exe cannot read a directory, it will just skip it and go on
- *   searching. However, unlike posix-y systems, it will happily try to run a
- *   file that is not readable/executable; if the spawn fails it will not
- *   continue searching.
- *
- * UNC path support: we are dealing with UNC paths in both the path and the
- * filename. This is a deviation from what cmd.exe does (it does not let you
- * start a program by specifying an UNC path on the command line) but this is
- * really a pointless restriction.
- *
- */
-static WCHAR* search_path(const WCHAR *file,
-                            WCHAR *cwd,
-                            const WCHAR *path) {
-  int file_has_dir;
-  WCHAR* result = NULL;
-  WCHAR *file_name_start;
-  WCHAR *dot;
-  const WCHAR *dir_start, *dir_end, *dir_path;
-  size_t dir_len;
-  int name_has_ext;
-
-  size_t file_len = wcslen(file);
-  size_t cwd_len = wcslen(cwd);
-
-  /* If the caller supplies an empty filename,
-   * we're not gonna return c:\windows\.exe -- GFY!
-   */
-  if (file_len == 0
-      || (file_len == 1 && file[0] == L'.')) {
-    return NULL;
-  }
-
-  /* Find the start of the filename so we can split the directory from the
-   * name. */
-  for (file_name_start = (WCHAR*)file + file_len;
-       file_name_start > file
-           && file_name_start[-1] != L'\\'
-           && file_name_start[-1] != L'/'
-           && file_name_start[-1] != L':';
-       file_name_start--);
-
-  file_has_dir = file_name_start != file;
-
-  /* Check if the filename includes an extension */
-  dot = wcschr(file_name_start, L'.');
-  name_has_ext = (dot != NULL && dot[1] != L'\0');
-
-  if (file_has_dir) {
-    /* The file has a path inside, don't use path */
-    result = path_search_walk_ext(
-        file, file_name_start - file,
-        file_name_start, file_len - (file_name_start - file),
-        cwd, cwd_len,
-        name_has_ext);
-
-  } else {
-    dir_end = path;
-
-    /* The file is really only a name; look in cwd first, then scan path */
-    result = path_search_walk_ext(L"", 0,
-                                  file, file_len,
-                                  cwd, cwd_len,
-                                  name_has_ext);
-
-    while (result == NULL) {
-      if (*dir_end == L'\0') {
-        break;
-      }
-
-      /* Skip the separator that dir_end now points to */
-      if (dir_end != path || *path == L';') {
-        dir_end++;
-      }
-
-      /* Next slice starts just after where the previous one ended */
-      dir_start = dir_end;
-
-      /* If path is quoted, find quote end */
-      if (*dir_start == L'"' || *dir_start == L'\'') {
-        dir_end = wcschr(dir_start + 1, *dir_start);
-        if (dir_end == NULL) {
-          dir_end = wcschr(dir_start, L'\0');
-        }
-      }
-      /* Slice until the next ; or \0 is found */
-      dir_end = wcschr(dir_end, L';');
-      if (dir_end == NULL) {
-        dir_end = wcschr(dir_start, L'\0');
-      }
-
-      /* If the slice is zero-length, don't bother */
-      if (dir_end - dir_start == 0) {
-        continue;
-      }
-
-      dir_path = dir_start;
-      dir_len = dir_end - dir_start;
-
-      /* Adjust if the path is quoted. */
-      if (dir_path[0] == '"' || dir_path[0] == '\'') {
-        ++dir_path;
-        --dir_len;
-      }
-
-      if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') {
-        --dir_len;
-      }
-
-      result = path_search_walk_ext(dir_path, dir_len,
-                                    file, file_len,
-                                    cwd, cwd_len,
-                                    name_has_ext);
-    }
-  }
-
-  return result;
-}
-
-
-/*
- * Quotes command line arguments
- * Returns a pointer to the end (next char to be written) of the buffer
- */
-WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) {
-  size_t len = wcslen(source);
-  size_t i;
-  int quote_hit;
-  WCHAR* start;
-
-  if (len == 0) {
-    /* Need double quotation for empty argument */
-    *(target++) = L'"';
-    *(target++) = L'"';
-    return target;
-  }
-
-  if (NULL == wcspbrk(source, L" \t\"")) {
-    /* No quotation needed */
-    wcsncpy(target, source, len);
-    target += len;
-    return target;
-  }
-
-  if (NULL == wcspbrk(source, L"\"\\")) {
-    /*
-     * No embedded double quotes or backlashes, so I can just wrap
-     * quote marks around the whole thing.
-     */
-    *(target++) = L'"';
-    wcsncpy(target, source, len);
-    target += len;
-    *(target++) = L'"';
-    return target;
-  }
-
-  /*
-   * Expected input/output:
-   *   input : hello"world
-   *   output: "hello\"world"
-   *   input : hello""world
-   *   output: "hello\"\"world"
-   *   input : hello\world
-   *   output: hello\world
-   *   input : hello\\world
-   *   output: hello\\world
-   *   input : hello\"world
-   *   output: "hello\\\"world"
-   *   input : hello\\"world
-   *   output: "hello\\\\\"world"
-   *   input : hello world\
-   *   output: "hello world\\"
-   */
-
-  *(target++) = L'"';
-  start = target;
-  quote_hit = 1;
-
-  for (i = len; i > 0; --i) {
-    *(target++) = source[i - 1];
-
-    if (quote_hit && source[i - 1] == L'\\') {
-      *(target++) = L'\\';
-    } else if(source[i - 1] == L'"') {
-      quote_hit = 1;
-      *(target++) = L'\\';
-    } else {
-      quote_hit = 0;
-    }
-  }
-  target[0] = L'\0';
-  wcsrev(start);
-  *(target++) = L'"';
-  return target;
-}
-
-
-int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {
-  char** arg;
-  WCHAR* dst = NULL;
-  WCHAR* temp_buffer = NULL;
-  size_t dst_len = 0;
-  size_t temp_buffer_len = 0;
-  WCHAR* pos;
-  int arg_count = 0;
-  int err = 0;
-
-  /* Count the required size. */
-  for (arg = args; *arg; arg++) {
-    DWORD arg_len;
-
-    arg_len = MultiByteToWideChar(CP_UTF8,
-                                  0,
-                                  *arg,
-                                  -1,
-                                  NULL,
-                                  0);
-    if (arg_len == 0) {
-      return GetLastError();
-    }
-
-    dst_len += arg_len;
-
-    if (arg_len > temp_buffer_len)
-      temp_buffer_len = arg_len;
-
-    arg_count++;
-  }
-
-  /* Adjust for potential quotes. Also assume the worst-case scenario that
-   * every character needs escaping, so we need twice as much space. */
-  dst_len = dst_len * 2 + arg_count * 2;
-
-  /* Allocate buffer for the final command line. */
-  dst = (WCHAR*) uv__malloc(dst_len * sizeof(WCHAR));
-  if (dst == NULL) {
-    err = ERROR_OUTOFMEMORY;
-    goto error;
-  }
-
-  /* Allocate temporary working buffer. */
-  temp_buffer = (WCHAR*) uv__malloc(temp_buffer_len * sizeof(WCHAR));
-  if (temp_buffer == NULL) {
-    err = ERROR_OUTOFMEMORY;
-    goto error;
-  }
-
-  pos = dst;
-  for (arg = args; *arg; arg++) {
-    DWORD arg_len;
-
-    /* Convert argument to wide char. */
-    arg_len = MultiByteToWideChar(CP_UTF8,
-                                  0,
-                                  *arg,
-                                  -1,
-                                  temp_buffer,
-                                  (int) (dst + dst_len - pos));
-    if (arg_len == 0) {
-      err = GetLastError();
-      goto error;
-    }
-
-    if (verbatim_arguments) {
-      /* Copy verbatim. */
-      wcscpy(pos, temp_buffer);
-      pos += arg_len - 1;
-    } else {
-      /* Quote/escape, if needed. */
-      pos = quote_cmd_arg(temp_buffer, pos);
-    }
-
-    *pos++ = *(arg + 1) ? L' ' : L'\0';
-  }
-
-  uv__free(temp_buffer);
-
-  *dst_ptr = dst;
-  return 0;
-
-error:
-  uv__free(dst);
-  uv__free(temp_buffer);
-  return err;
-}
-
-
-int env_strncmp(const wchar_t* a, int na, const wchar_t* b) {
-  const wchar_t* a_eq;
-  const wchar_t* b_eq;
-  wchar_t* A;
-  wchar_t* B;
-  int nb;
-  int r;
-
-  if (na < 0) {
-    a_eq = wcschr(a, L'=');
-    assert(a_eq);
-    na = (int)(long)(a_eq - a);
-  } else {
-    na--;
-  }
-  b_eq = wcschr(b, L'=');
-  assert(b_eq);
-  nb = b_eq - b;
-
-  A = (wchar_t*)alloca((na+1) * sizeof(wchar_t));
-  B = (wchar_t*)alloca((nb+1) * sizeof(wchar_t));
-
-  r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na);
-  assert(r==na);
-  A[na] = L'\0';
-  r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, b, nb, B, nb);
-  assert(r==nb);
-  B[nb] = L'\0';
-
-  while (1) {
-    wchar_t AA = *A++;
-    wchar_t BB = *B++;
-    if (AA < BB) {
-      return -1;
-    } else if (AA > BB) {
-      return 1;
-    } else if (!AA && !BB) {
-      return 0;
-    }
-  }
-}
-
-
-static int qsort_wcscmp(const void *a, const void *b) {
-  wchar_t* astr = *(wchar_t* const*)a;
-  wchar_t* bstr = *(wchar_t* const*)b;
-  return env_strncmp(astr, -1, bstr);
-}
-
-
-/*
- * The way windows takes environment variables is different than what C does;
- * Windows wants a contiguous block of null-terminated strings, terminated
- * with an additional null.
- *
- * Windows has a few "essential" environment variables. winsock will fail
- * to initialize if SYSTEMROOT is not defined; some APIs make reference to
- * TEMP. SYSTEMDRIVE is probably also important. We therefore ensure that
- * these get defined if the input environment block does not contain any
- * values for them.
- *
- * Also add variables known to Cygwin to be required for correct
- * subprocess operation in many cases:
- * https://github.com/Alexpux/Cygwin/blob/b266b04fbbd3a595f02ea149e4306d3ab9b1fe3d/winsup/cygwin/environ.cc#L955
- *
- */
-int make_program_env(char* env_block[], WCHAR** dst_ptr) {
-  WCHAR* dst;
-  WCHAR* ptr;
-  char** env;
-  size_t env_len = 0;
-  int len;
-  size_t i;
-  DWORD var_size;
-  size_t env_block_count = 1; /* 1 for null-terminator */
-  WCHAR* dst_copy;
-  WCHAR** ptr_copy;
-  WCHAR** env_copy;
-  DWORD* required_vars_value_len =
-      (DWORD*)alloca(n_required_vars * sizeof(DWORD*));
-
-  /* first pass: determine size in UTF-16 */
-  for (env = env_block; *env; env++) {
-    int len;
-    if (strchr(*env, '=')) {
-      len = MultiByteToWideChar(CP_UTF8,
-                                0,
-                                *env,
-                                -1,
-                                NULL,
-                                0);
-      if (len <= 0) {
-        return GetLastError();
-      }
-      env_len += len;
-      env_block_count++;
-    }
-  }
-
-  /* second pass: copy to UTF-16 environment block */
-  dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR));
-  if (!dst_copy) {
-    return ERROR_OUTOFMEMORY;
-  }
-  env_copy = (WCHAR**)alloca(env_block_count * sizeof(WCHAR*));
-
-  ptr = dst_copy;
-  ptr_copy = env_copy;
-  for (env = env_block; *env; env++) {
-    if (strchr(*env, '=')) {
-      len = MultiByteToWideChar(CP_UTF8,
-                                0,
-                                *env,
-                                -1,
-                                ptr,
-                                (int) (env_len - (ptr - dst_copy)));
-      if (len <= 0) {
-        DWORD err = GetLastError();
-        uv__free(dst_copy);
-        return err;
-      }
-      *ptr_copy++ = ptr;
-      ptr += len;
-    }
-  }
-  *ptr_copy = NULL;
-  assert(env_len == (size_t) (ptr - dst_copy));
-
-  /* sort our (UTF-16) copy */
-  qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);
-
-  /* third pass: check for required variables */
-  for (ptr_copy = env_copy, i = 0; i < n_required_vars; ) {
-    int cmp;
-    if (!*ptr_copy) {
-      cmp = -1;
-    } else {
-      cmp = env_strncmp(required_vars[i].wide_eq,
-                       required_vars[i].len,
-                        *ptr_copy);
-    }
-    if (cmp < 0) {
-      /* missing required var */
-      var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);
-      required_vars_value_len[i] = var_size;
-      if (var_size != 0) {
-        env_len += required_vars[i].len;
-        env_len += var_size;
-      }
-      i++;
-    } else {
-      ptr_copy++;
-      if (cmp == 0)
-        i++;
-    }
-  }
-
-  /* final pass: copy, in sort order, and inserting required variables */
-  dst = (WCHAR*)uv__malloc((1+env_len) * sizeof(WCHAR));
-  if (!dst) {
-    uv__free(dst_copy);
-    return ERROR_OUTOFMEMORY;
-  }
-
-  for (ptr = dst, ptr_copy = env_copy, i = 0;
-       *ptr_copy || i < n_required_vars;
-       ptr += len) {
-    int cmp;
-    if (i >= n_required_vars) {
-      cmp = 1;
-    } else if (!*ptr_copy) {
-      cmp = -1;
-    } else {
-      cmp = env_strncmp(required_vars[i].wide_eq,
-                        required_vars[i].len,
-                        *ptr_copy);
-    }
-    if (cmp < 0) {
-      /* missing required var */
-      len = required_vars_value_len[i];
-      if (len) {
-        wcscpy(ptr, required_vars[i].wide_eq);
-        ptr += required_vars[i].len;
-        var_size = GetEnvironmentVariableW(required_vars[i].wide,
-                                           ptr,
-                                           (int) (env_len - (ptr - dst)));
-        if (var_size != (DWORD) (len - 1)) { /* TODO: handle race condition? */
-          uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
-        }
-      }
-      i++;
-    } else {
-      /* copy var from env_block */
-      len = wcslen(*ptr_copy) + 1;
-      wmemcpy(ptr, *ptr_copy, len);
-      ptr_copy++;
-      if (cmp == 0)
-        i++;
-    }
-  }
-
-  /* Terminate with an extra NULL. */
-  assert(env_len == (size_t) (ptr - dst));
-  *ptr = L'\0';
-
-  uv__free(dst_copy);
-  *dst_ptr = dst;
-  return 0;
-}
-
-/*
- * Attempt to find the value of the PATH environment variable in the child's
- * preprocessed environment.
- *
- * If found, a pointer into `env` is returned. If not found, NULL is returned.
- */
-static WCHAR* find_path(WCHAR *env) {
-  for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
-    if ((env[0] == L'P' || env[0] == L'p') &&
-        (env[1] == L'A' || env[1] == L'a') &&
-        (env[2] == L'T' || env[2] == L't') &&
-        (env[3] == L'H' || env[3] == L'h') &&
-        (env[4] == L'=')) {
-      return &env[5];
-    }
-  }
-
-  return NULL;
-}
-
-/*
- * Called on Windows thread-pool thread to indicate that
- * a child process has exited.
- */
-static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) {
-  uv_process_t* process = (uv_process_t*) data;
-  uv_loop_t* loop = process->loop;
-
-  assert(didTimeout == FALSE);
-  assert(process);
-  assert(!process->exit_cb_pending);
-
-  process->exit_cb_pending = 1;
-
-  /* Post completed */
-  POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
-}
-
-
-/* Called on main thread after a child process has exited. */
-void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) {
-  int64_t exit_code;
-  DWORD status;
-
-  assert(handle->exit_cb_pending);
-  handle->exit_cb_pending = 0;
-
-  /* If we're closing, don't call the exit callback. Just schedule a close
-   * callback now. */
-  if (handle->flags & UV_HANDLE_CLOSING) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-    return;
-  }
-
-  /* Unregister from process notification. */
-  if (handle->wait_handle != INVALID_HANDLE_VALUE) {
-    UnregisterWait(handle->wait_handle);
-    handle->wait_handle = INVALID_HANDLE_VALUE;
-  }
-
-  /* Set the handle to inactive: no callbacks will be made after the exit
-   * callback. */
-  uv__handle_stop(handle);
-
-  if (GetExitCodeProcess(handle->process_handle, &status)) {
-    exit_code = status;
-  } else {
-    /* Unable to obtain the exit code. This should never happen. */
-    exit_code = uv_translate_sys_error(GetLastError());
-  }
-
-  /* Fire the exit callback. */
-  if (handle->exit_cb) {
-    handle->exit_cb(handle, exit_code, handle->exit_signal);
-  }
-}
-
-
-void uv_process_close(uv_loop_t* loop, uv_process_t* handle) {
-  uv__handle_closing(handle);
-
-  if (handle->wait_handle != INVALID_HANDLE_VALUE) {
-    /* This blocks until either the wait was cancelled, or the callback has
-     * completed. */
-    BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
-    if (!r) {
-      /* This should never happen, and if it happens, we can't recover... */
-      uv_fatal_error(GetLastError(), "UnregisterWaitEx");
-    }
-
-    handle->wait_handle = INVALID_HANDLE_VALUE;
-  }
-
-  if (!handle->exit_cb_pending) {
-    uv_want_endgame(loop, (uv_handle_t*)handle);
-  }
-}
-
-
-void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) {
-  assert(!handle->exit_cb_pending);
-  assert(handle->flags & UV_HANDLE_CLOSING);
-  assert(!(handle->flags & UV_HANDLE_CLOSED));
-
-  /* Clean-up the process handle. */
-  CloseHandle(handle->process_handle);
-
-  uv__handle_close(handle);
-}
-
-
-int uv_spawn(uv_loop_t* loop,
-             uv_process_t* process,
-             const uv_process_options_t* options) {
-  int i;
-  int err = 0;
-  WCHAR* path = NULL, *alloc_path = NULL;
-  BOOL result;
-  WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
-         *env = NULL, *cwd = NULL;
-  STARTUPINFOW startup;
-  PROCESS_INFORMATION info;
-  DWORD process_flags;
-
-  uv_process_init(loop, process);
-  process->exit_cb = options->exit_cb;
-
-  if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
-    return UV_ENOTSUP;
-  }
-
-  if (options->file == NULL ||
-      options->args == NULL) {
-    return UV_EINVAL;
-  }
-
-  assert(options->file != NULL);
-  assert(!(options->flags & ~(UV_PROCESS_DETACHED |
-                              UV_PROCESS_SETGID |
-                              UV_PROCESS_SETUID |
-                              UV_PROCESS_WINDOWS_HIDE |
-                              UV_PROCESS_WINDOWS_HIDE_CONSOLE |
-                              UV_PROCESS_WINDOWS_HIDE_GUI |
-                              UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
-
-  err = uv_utf8_to_utf16_alloc(options->file, &application);
-  if (err)
-    goto done;
-
-  err = make_program_args(
-      options->args,
-      options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
-      &arguments);
-  if (err)
-    goto done;
-
-  if (options->env) {
-     err = make_program_env(options->env, &env);
-     if (err)
-       goto done;
-  }
-
-  if (options->cwd) {
-    /* Explicit cwd */
-    err = uv_utf8_to_utf16_alloc(options->cwd, &cwd);
-    if (err)
-      goto done;
-
-  } else {
-    /* Inherit cwd */
-    DWORD cwd_len, r;
-
-    cwd_len = GetCurrentDirectoryW(0, NULL);
-    if (!cwd_len) {
-      err = GetLastError();
-      goto done;
-    }
-
-    cwd = (WCHAR*) uv__malloc(cwd_len * sizeof(WCHAR));
-    if (cwd == NULL) {
-      err = ERROR_OUTOFMEMORY;
-      goto done;
-    }
-
-    r = GetCurrentDirectoryW(cwd_len, cwd);
-    if (r == 0 || r >= cwd_len) {
-      err = GetLastError();
-      goto done;
-    }
-  }
-
-  /* Get PATH environment variable. */
-  path = find_path(env);
-  if (path == NULL) {
-    DWORD path_len, r;
-
-    path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);
-    if (path_len == 0) {
-      err = GetLastError();
-      goto done;
-    }
-
-    alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
-    if (alloc_path == NULL) {
-      err = ERROR_OUTOFMEMORY;
-      goto done;
-    }
-    path = alloc_path;
-
-    r = GetEnvironmentVariableW(L"PATH", path, path_len);
-    if (r == 0 || r >= path_len) {
-      err = GetLastError();
-      goto done;
-    }
-  }
-
-  err = uv__stdio_create(loop, options, &process->child_stdio_buffer);
-  if (err)
-    goto done;
-
-  application_path = search_path(application,
-                                 cwd,
-                                 path);
-  if (application_path == NULL) {
-    /* Not found. */
-    err = ERROR_FILE_NOT_FOUND;
-    goto done;
-  }
-
-  startup.cb = sizeof(startup);
-  startup.lpReserved = NULL;
-  startup.lpDesktop = NULL;
-  startup.lpTitle = NULL;
-  startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-
-  startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer);
-  startup.lpReserved2 = (BYTE*) process->child_stdio_buffer;
-
-  startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0);
-  startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);
-  startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);
-
-  process_flags = CREATE_UNICODE_ENVIRONMENT;
-
-  if ((options->flags & UV_PROCESS_WINDOWS_HIDE_CONSOLE) ||
-      (options->flags & UV_PROCESS_WINDOWS_HIDE)) {
-    /* Avoid creating console window if stdio is not inherited. */
-    for (i = 0; i < options->stdio_count; i++) {
-      if (options->stdio[i].flags & UV_INHERIT_FD)
-        break;
-      if (i == options->stdio_count - 1)
-        process_flags |= CREATE_NO_WINDOW;
-    }
-  }
-  if ((options->flags & UV_PROCESS_WINDOWS_HIDE_GUI) ||
-      (options->flags & UV_PROCESS_WINDOWS_HIDE)) {
-    /* Use SW_HIDE to avoid any potential process window. */
-    startup.wShowWindow = SW_HIDE;
-  } else {
-    startup.wShowWindow = SW_SHOWDEFAULT;
-  }
-
-  if (options->flags & UV_PROCESS_DETACHED) {
-    /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That
-     * means that libuv might not let you create a fully daemonized process
-     * when run under job control. However the type of job control that libuv
-     * itself creates doesn't trickle down to subprocesses so they can still
-     * daemonize.
-     *
-     * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the
-     * CreateProcess call fail if we're under job control that doesn't allow
-     * breakaway.
-     */
-    process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
-  }
-
-  if (!CreateProcessW(application_path,
-                     arguments,
-                     NULL,
-                     NULL,
-                     1,
-                     process_flags,
-                     env,
-                     cwd,
-                     &startup,
-                     &info)) {
-    /* CreateProcessW failed. */
-    err = GetLastError();
-    goto done;
-  }
-
-  /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
-
-  process->process_handle = info.hProcess;
-  process->pid = info.dwProcessId;
-
-  /* If the process isn't spawned as detached, assign to the global job object
-   * so windows will kill it when the parent process dies. */
-  if (!(options->flags & UV_PROCESS_DETACHED)) {
-    uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle);
-
-    if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) {
-      /* AssignProcessToJobObject might fail if this process is under job
-       * control and the job doesn't have the
-       * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version
-       * that doesn't support nested jobs.
-       *
-       * When that happens we just swallow the error and continue without
-       * establishing a kill-child-on-parent-exit relationship, otherwise
-       * there would be no way for libuv applications run under job control
-       * to spawn processes at all.
-       */
-      DWORD err = GetLastError();
-      if (err != ERROR_ACCESS_DENIED)
-        uv_fatal_error(err, "AssignProcessToJobObject");
-    }
-  }
-
-  /* Set IPC pid to all IPC pipes. */
-  for (i = 0; i < options->stdio_count; i++) {
-    const uv_stdio_container_t* fdopt = &options->stdio[i];
-    if (fdopt->flags & UV_CREATE_PIPE &&
-        fdopt->data.stream->type == UV_NAMED_PIPE &&
-        ((uv_pipe_t*) fdopt->data.stream)->ipc) {
-      ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid =
-          info.dwProcessId;
-    }
-  }
-
-  /* Setup notifications for when the child process exits. */
-  result = RegisterWaitForSingleObject(&process->wait_handle,
-      process->process_handle, exit_wait_callback, (void*)process, INFINITE,
-      WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
-  if (!result) {
-    uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
-  }
-
-  CloseHandle(info.hThread);
-
-  assert(!err);
-
-  /* Make the handle active. It will remain active until the exit callback is
-   * made or the handle is closed, whichever happens first. */
-  uv__handle_start(process);
-
-  /* Cleanup, whether we succeeded or failed. */
- done:
-  uv__free(application);
-  uv__free(application_path);
-  uv__free(arguments);
-  uv__free(cwd);
-  uv__free(env);
-  uv__free(alloc_path);
-
-  if (process->child_stdio_buffer != NULL) {
-    /* Clean up child stdio handles. */
-    uv__stdio_destroy(process->child_stdio_buffer);
-    process->child_stdio_buffer = NULL;
-  }
-
-  return uv_translate_sys_error(err);
-}
-
-
-static int uv__kill(HANDLE process_handle, int signum) {
-  if (signum < 0 || signum >= NSIG) {
-    return UV_EINVAL;
-  }
-
-  switch (signum) {
-    case SIGTERM:
-    case SIGKILL:
-    case SIGINT: {
-      /* Unconditionally terminate the process. On Windows, killed processes
-       * normally return 1. */
-      DWORD status;
-      int err;
-
-      if (TerminateProcess(process_handle, 1))
-        return 0;
-
-      /* If the process already exited before TerminateProcess was called,.
-       * TerminateProcess will fail with ERROR_ACCESS_DENIED. */
-      err = GetLastError();
-      if (err == ERROR_ACCESS_DENIED &&
-          GetExitCodeProcess(process_handle, &status) &&
-          status != STILL_ACTIVE) {
-        return UV_ESRCH;
-      }
-
-      return uv_translate_sys_error(err);
-    }
-
-    case 0: {
-      /* Health check: is the process still alive? */
-      DWORD status;
-
-      if (!GetExitCodeProcess(process_handle, &status))
-        return uv_translate_sys_error(GetLastError());
-
-      if (status != STILL_ACTIVE)
-        return UV_ESRCH;
-
-      return 0;
-    }
-
-    default:
-      /* Unsupported signal. */
-      return UV_ENOSYS;
-  }
-}
-
-
-int uv_process_kill(uv_process_t* process, int signum) {
-  int err;
-
-  if (process->process_handle == INVALID_HANDLE_VALUE) {
-    return UV_EINVAL;
-  }
-
-  err = uv__kill(process->process_handle, signum);
-  if (err) {
-    return err;  /* err is already translated. */
-  }
-
-  process->exit_signal = signum;
-
-  return 0;
-}
-
-
-int uv_kill(int pid, int signum) {
-  int err;
-  HANDLE process_handle;
-
-  if (pid == 0) {
-    process_handle = GetCurrentProcess();
-  } else {
-    process_handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
-                                 FALSE,
-                                 pid);
-  }
-
-  if (process_handle == NULL) {
-    err = GetLastError();
-    if (err == ERROR_INVALID_PARAMETER) {
-      return UV_ESRCH;
-    } else {
-      return uv_translate_sys_error(err);
-    }
-  }
-
-  err = uv__kill(process_handle, signum);
-  CloseHandle(process_handle);
-
-  return err;  /* err is already translated. */
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/req-inl.h b/wpiutil/src/main/native/libuv/src/win/req-inl.h
deleted file mode 100644
index f2513b7..0000000
--- a/wpiutil/src/main/native/libuv/src/win/req-inl.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_WIN_REQ_INL_H_
-#define UV_WIN_REQ_INL_H_
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
-
-
-#define SET_REQ_STATUS(req, status)                                     \
-   (req)->u.io.overlapped.Internal = (ULONG_PTR) (status)
-
-#define SET_REQ_ERROR(req, error)                                       \
-  SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error)))
-
-/* Note: used open-coded in UV_REQ_INIT() because of a circular dependency
- * between src/uv-common.h and src/win/internal.h.
- */
-#define SET_REQ_SUCCESS(req)                                            \
-  SET_REQ_STATUS((req), STATUS_SUCCESS)
-
-#define GET_REQ_STATUS(req)                                             \
-  ((NTSTATUS) (req)->u.io.overlapped.Internal)
-
-#define REQ_SUCCESS(req)                                                \
-  (NT_SUCCESS(GET_REQ_STATUS((req))))
-
-#define GET_REQ_ERROR(req)                                              \
-  (pRtlNtStatusToDosError(GET_REQ_STATUS((req))))
-
-#define GET_REQ_SOCK_ERROR(req)                                         \
-  (uv_ntstatus_to_winsock_error(GET_REQ_STATUS((req))))
-
-
-#define REGISTER_HANDLE_REQ(loop, handle, req)                          \
-  do {                                                                  \
-    INCREASE_ACTIVE_COUNT((loop), (handle));                            \
-    uv__req_register((loop), (req));                                    \
-  } while (0)
-
-#define UNREGISTER_HANDLE_REQ(loop, handle, req)                        \
-  do {                                                                  \
-    DECREASE_ACTIVE_COUNT((loop), (handle));                            \
-    uv__req_unregister((loop), (req));                                  \
-  } while (0)
-
-
-#define UV_SUCCEEDED_WITHOUT_IOCP(result)                               \
-  ((result) && (handle->flags & UV_HANDLE_SYNC_BYPASS_IOCP))
-
-#define UV_SUCCEEDED_WITH_IOCP(result)                                  \
-  ((result) || (GetLastError() == ERROR_IO_PENDING))
-
-
-#define POST_COMPLETION_FOR_REQ(loop, req)                              \
-  if (!PostQueuedCompletionStatus((loop)->iocp,                         \
-                                  0,                                    \
-                                  0,                                    \
-                                  &((req)->u.io.overlapped))) {         \
-    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");       \
-  }
-
-
-INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) {
-  return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped);
-}
-
-
-INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) {
-  req->next_req = NULL;
-  if (loop->pending_reqs_tail) {
-#ifdef _DEBUG
-    /* Ensure the request is not already in the queue, or the queue
-     * will get corrupted.
-     */
-    uv_req_t* current = loop->pending_reqs_tail;
-    do {
-      assert(req != current);
-      current = current->next_req;
-    } while(current != loop->pending_reqs_tail);
-#endif
-
-    req->next_req = loop->pending_reqs_tail->next_req;
-    loop->pending_reqs_tail->next_req = req;
-    loop->pending_reqs_tail = req;
-  } else {
-    req->next_req = req;
-    loop->pending_reqs_tail = req;
-  }
-}
-
-
-#define DELEGATE_STREAM_REQ(loop, req, method, handle_at)                     \
-  do {                                                                        \
-    switch (((uv_handle_t*) (req)->handle_at)->type) {                        \
-      case UV_TCP:                                                            \
-        uv_process_tcp_##method##_req(loop,                                   \
-                                      (uv_tcp_t*) ((req)->handle_at),         \
-                                      req);                                   \
-        break;                                                                \
-                                                                              \
-      case UV_NAMED_PIPE:                                                     \
-        uv_process_pipe_##method##_req(loop,                                  \
-                                       (uv_pipe_t*) ((req)->handle_at),       \
-                                       req);                                  \
-        break;                                                                \
-                                                                              \
-      case UV_TTY:                                                            \
-        uv_process_tty_##method##_req(loop,                                   \
-                                      (uv_tty_t*) ((req)->handle_at),         \
-                                      req);                                   \
-        break;                                                                \
-                                                                              \
-      default:                                                                \
-        assert(0);                                                            \
-    }                                                                         \
-  } while (0)
-
-
-INLINE static int uv_process_reqs(uv_loop_t* loop) {
-  uv_req_t* req;
-  uv_req_t* first;
-  uv_req_t* next;
-
-  if (loop->pending_reqs_tail == NULL)
-    return 0;
-
-  first = loop->pending_reqs_tail->next_req;
-  next = first;
-  loop->pending_reqs_tail = NULL;
-
-  while (next != NULL) {
-    req = next;
-    next = req->next_req != first ? req->next_req : NULL;
-
-    switch (req->type) {
-      case UV_READ:
-        DELEGATE_STREAM_REQ(loop, req, read, data);
-        break;
-
-      case UV_WRITE:
-        DELEGATE_STREAM_REQ(loop, (uv_write_t*) req, write, handle);
-        break;
-
-      case UV_ACCEPT:
-        DELEGATE_STREAM_REQ(loop, req, accept, data);
-        break;
-
-      case UV_CONNECT:
-        DELEGATE_STREAM_REQ(loop, (uv_connect_t*) req, connect, handle);
-        break;
-
-      case UV_SHUTDOWN:
-        /* Tcp shutdown requests don't come here. */
-        assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE);
-        uv_process_pipe_shutdown_req(
-            loop,
-            (uv_pipe_t*) ((uv_shutdown_t*) req)->handle,
-            (uv_shutdown_t*) req);
-        break;
-
-      case UV_UDP_RECV:
-        uv_process_udp_recv_req(loop, (uv_udp_t*) req->data, req);
-        break;
-
-      case UV_UDP_SEND:
-        uv_process_udp_send_req(loop,
-                                ((uv_udp_send_t*) req)->handle,
-                                (uv_udp_send_t*) req);
-        break;
-
-      case UV_WAKEUP:
-        uv_process_async_wakeup_req(loop, (uv_async_t*) req->data, req);
-        break;
-
-      case UV_SIGNAL_REQ:
-        uv_process_signal_req(loop, (uv_signal_t*) req->data, req);
-        break;
-
-      case UV_POLL_REQ:
-        uv_process_poll_req(loop, (uv_poll_t*) req->data, req);
-        break;
-
-      case UV_PROCESS_EXIT:
-        uv_process_proc_exit(loop, (uv_process_t*) req->data);
-        break;
-
-      case UV_FS_EVENT_REQ:
-        uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data);
-        break;
-
-      default:
-        assert(0);
-    }
-  }
-
-  return 1;
-}
-
-#endif /* UV_WIN_REQ_INL_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/win/signal.cpp b/wpiutil/src/main/native/libuv/src/win/signal.cpp
deleted file mode 100644
index 276dc60..0000000
--- a/wpiutil/src/main/native/libuv/src/win/signal.cpp
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <signal.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "req-inl.h"
-
-
-RB_HEAD(uv_signal_tree_s, uv_signal_s);
-
-static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree);
-static CRITICAL_SECTION uv__signal_lock;
-
-static BOOL WINAPI uv__signal_control_handler(DWORD type);
-
-int uv__signal_start(uv_signal_t* handle,
-                     uv_signal_cb signal_cb,
-                     int signum,
-                     int oneshot);
-
-void uv_signals_init(void) {
-  InitializeCriticalSection(&uv__signal_lock);
-  if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
-    abort();
-}
-
-
-static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
-  /* Compare signums first so all watchers with the same signnum end up
-   * adjacent. */
-  if (w1->signum < w2->signum) return -1;
-  if (w1->signum > w2->signum) return 1;
-
-  /* Sort by loop pointer, so we can easily look up the first item after
-   * { .signum = x, .loop = NULL }. */
-  if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1;
-  if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1;
-
-  if ((uintptr_t) w1 < (uintptr_t) w2) return -1;
-  if ((uintptr_t) w1 > (uintptr_t) w2) return 1;
-
-  return 0;
-}
-
-
-RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare)
-
-
-/*
- * Dispatches signal {signum} to all active uv_signal_t watchers in all loops.
- * Returns 1 if the signal was dispatched to any watcher, or 0 if there were
- * no active signal watchers observing this signal.
- */
-int uv__signal_dispatch(int signum) {
-  uv_signal_t lookup;
-  uv_signal_t* handle;
-  int dispatched;
-
-  dispatched = 0;
-
-  EnterCriticalSection(&uv__signal_lock);
-
-  lookup.signum = signum;
-  lookup.loop = NULL;
-
-  for (handle = RB_NFIND(uv_signal_tree_s, &uv__signal_tree, &lookup);
-       handle != NULL && handle->signum == signum;
-       handle = RB_NEXT(uv_signal_tree_s, &uv__signal_tree, handle)) {
-    unsigned long previous = InterlockedExchange(
-            (volatile LONG*) &handle->pending_signum, signum);
-
-    if (handle->flags & UV_SIGNAL_ONE_SHOT_DISPATCHED)
-      continue;
-
-    if (!previous) {
-      POST_COMPLETION_FOR_REQ(handle->loop, &handle->signal_req);
-    }
-
-    dispatched = 1;
-    if (handle->flags & UV_SIGNAL_ONE_SHOT)
-      handle->flags |= UV_SIGNAL_ONE_SHOT_DISPATCHED;
-  }
-
-  LeaveCriticalSection(&uv__signal_lock);
-
-  return dispatched;
-}
-
-
-static BOOL WINAPI uv__signal_control_handler(DWORD type) {
-  switch (type) {
-    case CTRL_C_EVENT:
-      return uv__signal_dispatch(SIGINT);
-
-    case CTRL_BREAK_EVENT:
-      return uv__signal_dispatch(SIGBREAK);
-
-    case CTRL_CLOSE_EVENT:
-      if (uv__signal_dispatch(SIGHUP)) {
-        /* Windows will terminate the process after the control handler
-         * returns. After that it will just terminate our process. Therefore
-         * block the signal handler so the main loop has some time to pick up
-         * the signal and do something for a few seconds. */
-        Sleep(INFINITE);
-        return TRUE;
-      }
-      return FALSE;
-
-    case CTRL_LOGOFF_EVENT:
-    case CTRL_SHUTDOWN_EVENT:
-      /* These signals are only sent to services. Services have their own
-       * notification mechanism, so there's no point in handling these. */
-
-    default:
-      /* We don't handle these. */
-      return FALSE;
-  }
-}
-
-
-int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
-  uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
-  handle->pending_signum = 0;
-  handle->signum = 0;
-  handle->signal_cb = NULL;
-
-  UV_REQ_INIT(&handle->signal_req, UV_SIGNAL_REQ);
-  handle->signal_req.data = handle;
-
-  return 0;
-}
-
-
-int uv_signal_stop(uv_signal_t* handle) {
-  uv_signal_t* removed_handle;
-
-  /* If the watcher wasn't started, this is a no-op. */
-  if (handle->signum == 0)
-    return 0;
-
-  EnterCriticalSection(&uv__signal_lock);
-
-  removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle);
-  assert(removed_handle == handle);
-
-  LeaveCriticalSection(&uv__signal_lock);
-
-  handle->signum = 0;
-  uv__handle_stop(handle);
-
-  return 0;
-}
-
-
-int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
-  return uv__signal_start(handle, signal_cb, signum, 0);
-}
-
-
-int uv_signal_start_oneshot(uv_signal_t* handle,
-                            uv_signal_cb signal_cb,
-                            int signum) {
-  return uv__signal_start(handle, signal_cb, signum, 1);
-}
-
-
-int uv__signal_start(uv_signal_t* handle,
-                            uv_signal_cb signal_cb,
-                            int signum,
-                            int oneshot) {
-  /* Test for invalid signal values. */
-  if (signum <= 0 || signum >= NSIG)
-    return UV_EINVAL;
-
-  /* Short circuit: if the signal watcher is already watching {signum} don't go
-   * through the process of deregistering and registering the handler.
-   * Additionally, this avoids pending signals getting lost in the (small) time
-   * frame that handle->signum == 0. */
-  if (signum == handle->signum) {
-    handle->signal_cb = signal_cb;
-    return 0;
-  }
-
-  /* If the signal handler was already active, stop it first. */
-  if (handle->signum != 0) {
-    int r = uv_signal_stop(handle);
-    /* uv_signal_stop is infallible. */
-    assert(r == 0);
-  }
-
-  EnterCriticalSection(&uv__signal_lock);
-
-  handle->signum = signum;
-  if (oneshot)
-    handle->flags |= UV_SIGNAL_ONE_SHOT;
-
-  RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
-
-  LeaveCriticalSection(&uv__signal_lock);
-
-  handle->signal_cb = signal_cb;
-  uv__handle_start(handle);
-
-  return 0;
-}
-
-
-void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle,
-    uv_req_t* req) {
-  long dispatched_signum;
-
-  assert(handle->type == UV_SIGNAL);
-  assert(req->type == UV_SIGNAL_REQ);
-
-  dispatched_signum = InterlockedExchange(
-          (volatile LONG*) &handle->pending_signum, 0);
-  assert(dispatched_signum != 0);
-
-  /* Check if the pending signal equals the signum that we are watching for.
-   * These can get out of sync when the handler is stopped and restarted while
-   * the signal_req is pending. */
-  if (dispatched_signum == handle->signum)
-    handle->signal_cb(handle, dispatched_signum);
-
-  if (handle->flags & UV_SIGNAL_ONE_SHOT)
-    uv_signal_stop(handle);
-
-  if (handle->flags & UV_HANDLE_CLOSING) {
-    /* When it is closing, it must be stopped at this point. */
-    assert(handle->signum == 0);
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-  }
-}
-
-
-void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) {
-  uv_signal_stop(handle);
-  uv__handle_closing(handle);
-
-  if (handle->pending_signum == 0) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-  }
-}
-
-
-void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) {
-  assert(handle->flags & UV_HANDLE_CLOSING);
-  assert(!(handle->flags & UV_HANDLE_CLOSED));
-
-  assert(handle->signum == 0);
-  assert(handle->pending_signum == 0);
-
-  handle->flags |= UV_HANDLE_CLOSED;
-
-  uv__handle_close(handle);
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/snprintf.cpp b/wpiutil/src/main/native/libuv/src/win/snprintf.cpp
deleted file mode 100644
index 776c0e3..0000000
--- a/wpiutil/src/main/native/libuv/src/win/snprintf.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright the libuv project contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#if defined(_MSC_VER) && _MSC_VER < 1900
-
-#include <stdio.h>
-#include <stdarg.h>
-
-/* Emulate snprintf() on MSVC<2015, _snprintf() doesn't zero-terminate the buffer
- * on overflow...
- */
-int snprintf(char* buf, size_t len, const char* fmt, ...) {
-  int n;
-  va_list ap;
-  va_start(ap, fmt);
-
-  n = _vscprintf(fmt, ap);
-  vsnprintf_s(buf, len, _TRUNCATE, fmt, ap);
-
-  va_end(ap);
-  return n;
-}
-
-#endif
diff --git a/wpiutil/src/main/native/libuv/src/win/stream-inl.h b/wpiutil/src/main/native/libuv/src/win/stream-inl.h
deleted file mode 100644
index 40f5ddd..0000000
--- a/wpiutil/src/main/native/libuv/src/win/stream-inl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_WIN_STREAM_INL_H_
-#define UV_WIN_STREAM_INL_H_
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "req-inl.h"
-
-
-INLINE static void uv_stream_init(uv_loop_t* loop,
-                                  uv_stream_t* handle,
-                                  uv_handle_type type) {
-  uv__handle_init(loop, (uv_handle_t*) handle, type);
-  handle->write_queue_size = 0;
-  handle->activecnt = 0;
-  handle->stream.conn.shutdown_req = NULL;
-  handle->stream.conn.write_reqs_pending = 0;
-
-  UV_REQ_INIT(&handle->read_req, UV_READ);
-  handle->read_req.event_handle = NULL;
-  handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
-  handle->read_req.data = handle;
-}
-
-
-INLINE static void uv_connection_init(uv_stream_t* handle) {
-  handle->flags |= UV_HANDLE_CONNECTION;
-}
-
-
-#endif /* UV_WIN_STREAM_INL_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/win/stream.cpp b/wpiutil/src/main/native/libuv/src/win/stream.cpp
deleted file mode 100644
index 7656627..0000000
--- a/wpiutil/src/main/native/libuv/src/win/stream.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "req-inl.h"
-
-
-int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
-  int err;
-
-  err = ERROR_INVALID_PARAMETER;
-  switch (stream->type) {
-    case UV_TCP:
-      err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb);
-      break;
-    case UV_NAMED_PIPE:
-      err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb);
-      break;
-    default:
-      assert(0);
-  }
-
-  return uv_translate_sys_error(err);
-}
-
-
-int uv_accept(uv_stream_t* server, uv_stream_t* client) {
-  int err;
-
-  err = ERROR_INVALID_PARAMETER;
-  switch (server->type) {
-    case UV_TCP:
-      err = uv_tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client);
-      break;
-    case UV_NAMED_PIPE:
-      err = uv_pipe_accept((uv_pipe_t*)server, client);
-      break;
-    default:
-      assert(0);
-  }
-
-  return uv_translate_sys_error(err);
-}
-
-
-int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb,
-    uv_read_cb read_cb) {
-  int err;
-
-  if (handle->flags & UV_HANDLE_READING) {
-    return UV_EALREADY;
-  }
-
-  if (!(handle->flags & UV_HANDLE_READABLE)) {
-    return UV_ENOTCONN;
-  }
-
-  err = ERROR_INVALID_PARAMETER;
-  switch (handle->type) {
-    case UV_TCP:
-      err = uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb);
-      break;
-    case UV_NAMED_PIPE:
-      err = uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb);
-      break;
-    case UV_TTY:
-      err = uv_tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb);
-      break;
-    default:
-      assert(0);
-  }
-
-  return uv_translate_sys_error(err);
-}
-
-
-int uv_read_stop(uv_stream_t* handle) {
-  int err;
-
-  if (!(handle->flags & UV_HANDLE_READING))
-    return 0;
-
-  err = 0;
-  if (handle->type == UV_TTY) {
-    err = uv_tty_read_stop((uv_tty_t*) handle);
-  } else if (handle->type == UV_NAMED_PIPE) {
-    uv__pipe_read_stop((uv_pipe_t*) handle);
-  } else {
-    handle->flags &= ~UV_HANDLE_READING;
-    DECREASE_ACTIVE_COUNT(handle->loop, handle);
-  }
-
-  return uv_translate_sys_error(err);
-}
-
-
-int uv_write(uv_write_t* req,
-             uv_stream_t* handle,
-             const uv_buf_t bufs[],
-             unsigned int nbufs,
-             uv_write_cb cb) {
-  uv_loop_t* loop = handle->loop;
-  int err;
-
-  if (!(handle->flags & UV_HANDLE_WRITABLE)) {
-    return UV_EPIPE;
-  }
-
-  err = ERROR_INVALID_PARAMETER;
-  switch (handle->type) {
-    case UV_TCP:
-      err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb);
-      break;
-    case UV_NAMED_PIPE:
-      err = uv__pipe_write(
-          loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb);
-      break;
-    case UV_TTY:
-      err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb);
-      break;
-    default:
-      assert(0);
-  }
-
-  return uv_translate_sys_error(err);
-}
-
-
-int uv_write2(uv_write_t* req,
-              uv_stream_t* handle,
-              const uv_buf_t bufs[],
-              unsigned int nbufs,
-              uv_stream_t* send_handle,
-              uv_write_cb cb) {
-  uv_loop_t* loop = handle->loop;
-  int err;
-
-  if (send_handle == NULL) {
-    return uv_write(req, handle, bufs, nbufs, cb);
-  }
-
-  if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) {
-    return UV_EINVAL;
-  } else if (!(handle->flags & UV_HANDLE_WRITABLE)) {
-    return UV_EPIPE;
-  }
-
-  err = uv__pipe_write(
-      loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb);
-  return uv_translate_sys_error(err);
-}
-
-
-int uv_try_write(uv_stream_t* stream,
-                 const uv_buf_t bufs[],
-                 unsigned int nbufs) {
-  if (stream->flags & UV_HANDLE_CLOSING)
-    return UV_EBADF;
-  if (!(stream->flags & UV_HANDLE_WRITABLE))
-    return UV_EPIPE;
-
-  switch (stream->type) {
-    case UV_TCP:
-      return uv__tcp_try_write((uv_tcp_t*) stream, bufs, nbufs);
-    case UV_TTY:
-      return uv__tty_try_write((uv_tty_t*) stream, bufs, nbufs);
-    case UV_NAMED_PIPE:
-      return UV_EAGAIN;
-    default:
-      assert(0);
-      return UV_ENOSYS;
-  }
-}
-
-
-int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
-  uv_loop_t* loop = handle->loop;
-
-  if (!(handle->flags & UV_HANDLE_WRITABLE)) {
-    return UV_EPIPE;
-  }
-
-  UV_REQ_INIT(req, UV_SHUTDOWN);
-  req->handle = handle;
-  req->cb = cb;
-
-  handle->flags &= ~UV_HANDLE_WRITABLE;
-  handle->stream.conn.shutdown_req = req;
-  handle->reqs_pending++;
-  REGISTER_HANDLE_REQ(loop, handle, req);
-
-  uv_want_endgame(loop, (uv_handle_t*)handle);
-
-  return 0;
-}
-
-
-int uv_is_readable(const uv_stream_t* handle) {
-  return !!(handle->flags & UV_HANDLE_READABLE);
-}
-
-
-int uv_is_writable(const uv_stream_t* handle) {
-  return !!(handle->flags & UV_HANDLE_WRITABLE);
-}
-
-
-int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
-  if (handle->type != UV_NAMED_PIPE)
-    return UV_EINVAL;
-
-  if (blocking != 0)
-    handle->flags |= UV_HANDLE_BLOCKING_WRITES;
-  else
-    handle->flags &= ~UV_HANDLE_BLOCKING_WRITES;
-
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/tcp.cpp b/wpiutil/src/main/native/libuv/src/win/tcp.cpp
deleted file mode 100644
index f2cb527..0000000
--- a/wpiutil/src/main/native/libuv/src/win/tcp.cpp
+++ /dev/null
@@ -1,1505 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "stream-inl.h"
-#include "req-inl.h"
-
-
-/*
- * Threshold of active tcp streams for which to preallocate tcp read buffers.
- * (Due to node slab allocator performing poorly under this pattern,
- *  the optimization is temporarily disabled (threshold=0).  This will be
- *  revisited once node allocator is improved.)
- */
-const unsigned int uv_active_tcp_streams_threshold = 0;
-
-/*
- * Number of simultaneous pending AcceptEx calls.
- */
-const unsigned int uv_simultaneous_server_accepts = 32;
-
-/* A zero-size buffer for use by uv_tcp_read */
-static char uv_zero_[] = "";
-
-static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
-  if (setsockopt(socket,
-                 IPPROTO_TCP,
-                 TCP_NODELAY,
-                 (const char*)&enable,
-                 sizeof enable) == -1) {
-    return WSAGetLastError();
-  }
-  return 0;
-}
-
-
-static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) {
-  if (setsockopt(socket,
-                 SOL_SOCKET,
-                 SO_KEEPALIVE,
-                 (const char*)&enable,
-                 sizeof enable) == -1) {
-    return WSAGetLastError();
-  }
-
-  if (enable && setsockopt(socket,
-                           IPPROTO_TCP,
-                           TCP_KEEPALIVE,
-                           (const char*)&delay,
-                           sizeof delay) == -1) {
-    return WSAGetLastError();
-  }
-
-  return 0;
-}
-
-
-static int uv_tcp_set_socket(uv_loop_t* loop,
-                             uv_tcp_t* handle,
-                             SOCKET socket,
-                             int family,
-                             int imported) {
-  DWORD yes = 1;
-  int non_ifs_lsp;
-  int err;
-
-  if (handle->socket != INVALID_SOCKET)
-    return UV_EBUSY;
-
-  /* Set the socket to nonblocking mode */
-  if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
-    return WSAGetLastError();
-  }
-
-  /* Make the socket non-inheritable */
-  if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0))
-    return GetLastError();
-
-  /* Associate it with the I/O completion port. Use uv_handle_t pointer as
-   * completion key. */
-  if (CreateIoCompletionPort((HANDLE)socket,
-                             loop->iocp,
-                             (ULONG_PTR)socket,
-                             0) == NULL) {
-    if (imported) {
-      handle->flags |= UV_HANDLE_EMULATE_IOCP;
-    } else {
-      return GetLastError();
-    }
-  }
-
-  if (family == AF_INET6) {
-    non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6;
-  } else {
-    non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4;
-  }
-
-  if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) {
-    UCHAR sfcnm_flags =
-        FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
-    if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags))
-      return GetLastError();
-    handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
-  }
-
-  if (handle->flags & UV_HANDLE_TCP_NODELAY) {
-    err = uv__tcp_nodelay(handle, socket, 1);
-    if (err)
-      return err;
-  }
-
-  /* TODO: Use stored delay. */
-  if (handle->flags & UV_HANDLE_TCP_KEEPALIVE) {
-    err = uv__tcp_keepalive(handle, socket, 1, 60);
-    if (err)
-      return err;
-  }
-
-  handle->socket = socket;
-
-  if (family == AF_INET6) {
-    handle->flags |= UV_HANDLE_IPV6;
-  } else {
-    assert(!(handle->flags & UV_HANDLE_IPV6));
-  }
-
-  return 0;
-}
-
-
-int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) {
-  int domain;
-
-  /* Use the lower 8 bits for the domain */
-  domain = flags & 0xFF;
-  if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
-    return UV_EINVAL;
-
-  if (flags & ~0xFF)
-    return UV_EINVAL;
-
-  uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP);
-  handle->tcp.serv.accept_reqs = NULL;
-  handle->tcp.serv.pending_accepts = NULL;
-  handle->socket = INVALID_SOCKET;
-  handle->reqs_pending = 0;
-  handle->tcp.serv.func_acceptex = NULL;
-  handle->tcp.conn.func_connectex = NULL;
-  handle->tcp.serv.processed_accepts = 0;
-  handle->delayed_error = 0;
-
-  /* If anything fails beyond this point we need to remove the handle from
-   * the handle queue, since it was added by uv__handle_init in uv_stream_init.
-   */
-
-  if (domain != AF_UNSPEC) {
-    SOCKET sock;
-    DWORD err;
-
-    sock = socket(domain, SOCK_STREAM, 0);
-    if (sock == INVALID_SOCKET) {
-      err = WSAGetLastError();
-      QUEUE_REMOVE(&handle->handle_queue);
-      return uv_translate_sys_error(err);
-    }
-
-    err = uv_tcp_set_socket(handle->loop, handle, sock, domain, 0);
-    if (err) {
-      closesocket(sock);
-      QUEUE_REMOVE(&handle->handle_queue);
-      return uv_translate_sys_error(err);
-    }
-
-  }
-
-  return 0;
-}
-
-
-int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
-  return uv_tcp_init_ex(loop, handle, AF_UNSPEC);
-}
-
-
-void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) {
-  int err;
-  unsigned int i;
-  uv_tcp_accept_t* req;
-
-  if (handle->flags & UV_HANDLE_CONNECTION &&
-      handle->stream.conn.shutdown_req != NULL &&
-      handle->stream.conn.write_reqs_pending == 0) {
-
-    UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
-
-    err = 0;
-    if (handle->flags & UV_HANDLE_CLOSING) {
-      err = ERROR_OPERATION_ABORTED;
-    } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) {
-      err = WSAGetLastError();
-    }
-
-    if (handle->stream.conn.shutdown_req->cb) {
-      handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req,
-                               uv_translate_sys_error(err));
-    }
-
-    handle->stream.conn.shutdown_req = NULL;
-    DECREASE_PENDING_REQ_COUNT(handle);
-    return;
-  }
-
-  if (handle->flags & UV_HANDLE_CLOSING &&
-      handle->reqs_pending == 0) {
-    assert(!(handle->flags & UV_HANDLE_CLOSED));
-
-    if (!(handle->flags & UV_HANDLE_TCP_SOCKET_CLOSED)) {
-      closesocket(handle->socket);
-      handle->socket = INVALID_SOCKET;
-      handle->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
-    }
-
-    if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) {
-      if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-        for (i = 0; i < uv_simultaneous_server_accepts; i++) {
-          req = &handle->tcp.serv.accept_reqs[i];
-          if (req->wait_handle != INVALID_HANDLE_VALUE) {
-            UnregisterWait(req->wait_handle);
-            req->wait_handle = INVALID_HANDLE_VALUE;
-          }
-          if (req->event_handle) {
-            CloseHandle(req->event_handle);
-            req->event_handle = NULL;
-          }
-        }
-      }
-
-      uv__free(handle->tcp.serv.accept_reqs);
-      handle->tcp.serv.accept_reqs = NULL;
-    }
-
-    if (handle->flags & UV_HANDLE_CONNECTION &&
-        handle->flags & UV_HANDLE_EMULATE_IOCP) {
-      if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) {
-        UnregisterWait(handle->read_req.wait_handle);
-        handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
-      }
-      if (handle->read_req.event_handle) {
-        CloseHandle(handle->read_req.event_handle);
-        handle->read_req.event_handle = NULL;
-      }
-    }
-
-    uv__handle_close(handle);
-    loop->active_tcp_streams--;
-  }
-}
-
-
-/* Unlike on Unix, here we don't set SO_REUSEADDR, because it doesn't just
- * allow binding to addresses that are in use by sockets in TIME_WAIT, it
- * effectively allows 'stealing' a port which is in use by another application.
- *
- * SO_EXCLUSIVEADDRUSE is also not good here because it does check all sockets,
- * regardless of state, so we'd get an error even if the port is in use by a
- * socket in TIME_WAIT state.
- *
- * See issue #1360.
- *
- */
-static int uv_tcp_try_bind(uv_tcp_t* handle,
-                           const struct sockaddr* addr,
-                           unsigned int addrlen,
-                           unsigned int flags) {
-  DWORD err;
-  int r;
-
-  if (handle->socket == INVALID_SOCKET) {
-    SOCKET sock;
-
-    /* Cannot set IPv6-only mode on non-IPv6 socket. */
-    if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
-      return ERROR_INVALID_PARAMETER;
-
-    sock = socket(addr->sa_family, SOCK_STREAM, 0);
-    if (sock == INVALID_SOCKET) {
-      return WSAGetLastError();
-    }
-
-    err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0);
-    if (err) {
-      closesocket(sock);
-      return err;
-    }
-  }
-
-#ifdef IPV6_V6ONLY
-  if (addr->sa_family == AF_INET6) {
-    int on;
-
-    on = (flags & UV_TCP_IPV6ONLY) != 0;
-
-    /* TODO: how to handle errors? This may fail if there is no ipv4 stack
-     * available, or when run on XP/2003 which have no support for dualstack
-     * sockets. For now we're silently ignoring the error. */
-    setsockopt(handle->socket,
-               IPPROTO_IPV6,
-               IPV6_V6ONLY,
-               (const char*)&on,
-               sizeof on);
-  }
-#endif
-
-  r = bind(handle->socket, addr, addrlen);
-
-  if (r == SOCKET_ERROR) {
-    err = WSAGetLastError();
-    if (err == WSAEADDRINUSE) {
-      /* Some errors are not to be reported until connect() or listen() */
-      handle->delayed_error = err;
-    } else {
-      return err;
-    }
-  }
-
-  handle->flags |= UV_HANDLE_BOUND;
-
-  return 0;
-}
-
-
-static void CALLBACK post_completion(void* context, BOOLEAN timed_out) {
-  uv_req_t* req;
-  uv_tcp_t* handle;
-
-  req = (uv_req_t*) context;
-  assert(req != NULL);
-  handle = (uv_tcp_t*)req->data;
-  assert(handle != NULL);
-  assert(!timed_out);
-
-  if (!PostQueuedCompletionStatus(handle->loop->iocp,
-                                  req->u.io.overlapped.InternalHigh,
-                                  0,
-                                  &req->u.io.overlapped)) {
-    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
-  }
-}
-
-
-static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) {
-  uv_write_t* req;
-  uv_tcp_t* handle;
-
-  req = (uv_write_t*) context;
-  assert(req != NULL);
-  handle = (uv_tcp_t*)req->handle;
-  assert(handle != NULL);
-  assert(!timed_out);
-
-  if (!PostQueuedCompletionStatus(handle->loop->iocp,
-                                  req->u.io.overlapped.InternalHigh,
-                                  0,
-                                  &req->u.io.overlapped)) {
-    uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus");
-  }
-}
-
-
-static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
-  uv_loop_t* loop = handle->loop;
-  BOOL success;
-  DWORD bytes;
-  SOCKET accept_socket;
-  short family;
-
-  assert(handle->flags & UV_HANDLE_LISTENING);
-  assert(req->accept_socket == INVALID_SOCKET);
-
-  /* choose family and extension function */
-  if (handle->flags & UV_HANDLE_IPV6) {
-    family = AF_INET6;
-  } else {
-    family = AF_INET;
-  }
-
-  /* Open a socket for the accepted connection. */
-  accept_socket = socket(family, SOCK_STREAM, 0);
-  if (accept_socket == INVALID_SOCKET) {
-    SET_REQ_ERROR(req, WSAGetLastError());
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-    handle->reqs_pending++;
-    return;
-  }
-
-  /* Make the socket non-inheritable */
-  if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) {
-    SET_REQ_ERROR(req, GetLastError());
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-    handle->reqs_pending++;
-    closesocket(accept_socket);
-    return;
-  }
-
-  /* Prepare the overlapped structure. */
-  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
-  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-    req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
-  }
-
-  success = handle->tcp.serv.func_acceptex(handle->socket,
-                                          accept_socket,
-                                          (void*)req->accept_buffer,
-                                          0,
-                                          sizeof(struct sockaddr_storage),
-                                          sizeof(struct sockaddr_storage),
-                                          &bytes,
-                                          &req->u.io.overlapped);
-
-  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
-    /* Process the req without IOCP. */
-    req->accept_socket = accept_socket;
-    handle->reqs_pending++;
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
-    /* The req will be processed with IOCP. */
-    req->accept_socket = accept_socket;
-    handle->reqs_pending++;
-    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
-        req->wait_handle == INVALID_HANDLE_VALUE &&
-        !RegisterWaitForSingleObject(&req->wait_handle,
-          req->event_handle, post_completion, (void*) req,
-          INFINITE, WT_EXECUTEINWAITTHREAD)) {
-      SET_REQ_ERROR(req, GetLastError());
-      uv_insert_pending_req(loop, (uv_req_t*)req);
-    }
-  } else {
-    /* Make this req pending reporting an error. */
-    SET_REQ_ERROR(req, WSAGetLastError());
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-    handle->reqs_pending++;
-    /* Destroy the preallocated client socket. */
-    closesocket(accept_socket);
-    /* Destroy the event handle */
-    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-      CloseHandle(req->u.io.overlapped.hEvent);
-      req->event_handle = NULL;
-    }
-  }
-}
-
-
-static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
-  uv_read_t* req;
-  uv_buf_t buf;
-  int result;
-  DWORD bytes, flags;
-
-  assert(handle->flags & UV_HANDLE_READING);
-  assert(!(handle->flags & UV_HANDLE_READ_PENDING));
-
-  req = &handle->read_req;
-  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-
-  /*
-   * Preallocate a read buffer if the number of active streams is below
-   * the threshold.
-  */
-  if (loop->active_tcp_streams < uv_active_tcp_streams_threshold) {
-    handle->flags &= ~UV_HANDLE_ZERO_READ;
-    handle->tcp.conn.read_buffer = uv_buf_init(NULL, 0);
-    handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->tcp.conn.read_buffer);
-    if (handle->tcp.conn.read_buffer.base == NULL ||
-        handle->tcp.conn.read_buffer.len == 0) {
-      handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &handle->tcp.conn.read_buffer);
-      return;
-    }
-    assert(handle->tcp.conn.read_buffer.base != NULL);
-    buf = handle->tcp.conn.read_buffer;
-  } else {
-    handle->flags |= UV_HANDLE_ZERO_READ;
-    buf.base = (char*) &uv_zero_;
-    buf.len = 0;
-  }
-
-  /* Prepare the overlapped structure. */
-  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
-  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-    assert(req->event_handle);
-    req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
-  }
-
-  flags = 0;
-  result = WSARecv(handle->socket,
-                   (WSABUF*)&buf,
-                   1,
-                   &bytes,
-                   &flags,
-                   &req->u.io.overlapped,
-                   NULL);
-
-  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
-    /* Process the req without IOCP. */
-    handle->flags |= UV_HANDLE_READ_PENDING;
-    req->u.io.overlapped.InternalHigh = bytes;
-    handle->reqs_pending++;
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
-    /* The req will be processed with IOCP. */
-    handle->flags |= UV_HANDLE_READ_PENDING;
-    handle->reqs_pending++;
-    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
-        req->wait_handle == INVALID_HANDLE_VALUE &&
-        !RegisterWaitForSingleObject(&req->wait_handle,
-          req->event_handle, post_completion, (void*) req,
-          INFINITE, WT_EXECUTEINWAITTHREAD)) {
-      SET_REQ_ERROR(req, GetLastError());
-      uv_insert_pending_req(loop, (uv_req_t*)req);
-    }
-  } else {
-    /* Make this req pending reporting an error. */
-    SET_REQ_ERROR(req, WSAGetLastError());
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-    handle->reqs_pending++;
-  }
-}
-
-
-int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
-  unsigned int i, simultaneous_accepts;
-  uv_tcp_accept_t* req;
-  int err;
-
-  assert(backlog > 0);
-
-  if (handle->flags & UV_HANDLE_LISTENING) {
-    handle->stream.serv.connection_cb = cb;
-  }
-
-  if (handle->flags & UV_HANDLE_READING) {
-    return WSAEISCONN;
-  }
-
-  if (handle->delayed_error) {
-    return handle->delayed_error;
-  }
-
-  if (!(handle->flags & UV_HANDLE_BOUND)) {
-    err = uv_tcp_try_bind(handle,
-                          (const struct sockaddr*) &uv_addr_ip4_any_,
-                          sizeof(uv_addr_ip4_any_),
-                          0);
-    if (err)
-      return err;
-    if (handle->delayed_error)
-      return handle->delayed_error;
-  }
-
-  if (!handle->tcp.serv.func_acceptex) {
-    if (!uv_get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) {
-      return WSAEAFNOSUPPORT;
-    }
-  }
-
-  if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
-      listen(handle->socket, backlog) == SOCKET_ERROR) {
-    return WSAGetLastError();
-  }
-
-  handle->flags |= UV_HANDLE_LISTENING;
-  handle->stream.serv.connection_cb = cb;
-  INCREASE_ACTIVE_COUNT(loop, handle);
-
-  simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1
-    : uv_simultaneous_server_accepts;
-
-  if(!handle->tcp.serv.accept_reqs) {
-    handle->tcp.serv.accept_reqs = (uv_tcp_accept_t*)
-      uv__malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));
-    if (!handle->tcp.serv.accept_reqs) {
-      uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-    }
-
-    for (i = 0; i < simultaneous_accepts; i++) {
-      req = &handle->tcp.serv.accept_reqs[i];
-      UV_REQ_INIT(req, UV_ACCEPT);
-      req->accept_socket = INVALID_SOCKET;
-      req->data = handle;
-
-      req->wait_handle = INVALID_HANDLE_VALUE;
-      if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-        req->event_handle = CreateEvent(NULL, 0, 0, NULL);
-        if (!req->event_handle) {
-          uv_fatal_error(GetLastError(), "CreateEvent");
-        }
-      } else {
-        req->event_handle = NULL;
-      }
-
-      uv_tcp_queue_accept(handle, req);
-    }
-
-    /* Initialize other unused requests too, because uv_tcp_endgame doesn't
-     * know how many requests were initialized, so it will try to clean up
-     * {uv_simultaneous_server_accepts} requests. */
-    for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) {
-      req = &handle->tcp.serv.accept_reqs[i];
-      UV_REQ_INIT(req, UV_ACCEPT);
-      req->accept_socket = INVALID_SOCKET;
-      req->data = handle;
-      req->wait_handle = INVALID_HANDLE_VALUE;
-      req->event_handle = NULL;
-    }
-  }
-
-  return 0;
-}
-
-
-int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
-  uv_loop_t* loop = server->loop;
-  int err = 0;
-  int family;
-
-  uv_tcp_accept_t* req = server->tcp.serv.pending_accepts;
-
-  if (!req) {
-    /* No valid connections found, so we error out. */
-    return WSAEWOULDBLOCK;
-  }
-
-  if (req->accept_socket == INVALID_SOCKET) {
-    return WSAENOTCONN;
-  }
-
-  if (server->flags & UV_HANDLE_IPV6) {
-    family = AF_INET6;
-  } else {
-    family = AF_INET;
-  }
-
-  err = uv_tcp_set_socket(client->loop,
-                          client,
-                          req->accept_socket,
-                          family,
-                          0);
-  if (err) {
-    closesocket(req->accept_socket);
-  } else {
-    uv_connection_init((uv_stream_t*) client);
-    /* AcceptEx() implicitly binds the accepted socket. */
-    client->flags |= UV_HANDLE_BOUND | UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
-  }
-
-  /* Prepare the req to pick up a new connection */
-  server->tcp.serv.pending_accepts = req->next_pending;
-  req->next_pending = NULL;
-  req->accept_socket = INVALID_SOCKET;
-
-  if (!(server->flags & UV_HANDLE_CLOSING)) {
-    /* Check if we're in a middle of changing the number of pending accepts. */
-    if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {
-      uv_tcp_queue_accept(server, req);
-    } else {
-      /* We better be switching to a single pending accept. */
-      assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT);
-
-      server->tcp.serv.processed_accepts++;
-
-      if (server->tcp.serv.processed_accepts >= uv_simultaneous_server_accepts) {
-        server->tcp.serv.processed_accepts = 0;
-        /*
-         * All previously queued accept requests are now processed.
-         * We now switch to queueing just a single accept.
-         */
-        uv_tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]);
-        server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
-        server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
-      }
-    }
-  }
-
-  loop->active_tcp_streams++;
-
-  return err;
-}
-
-
-int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb,
-    uv_read_cb read_cb) {
-  uv_loop_t* loop = handle->loop;
-
-  handle->flags |= UV_HANDLE_READING;
-  handle->read_cb = read_cb;
-  handle->alloc_cb = alloc_cb;
-  INCREASE_ACTIVE_COUNT(loop, handle);
-
-  /* If reading was stopped and then started again, there could still be a read
-   * request pending. */
-  if (!(handle->flags & UV_HANDLE_READ_PENDING)) {
-    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
-        !handle->read_req.event_handle) {
-      handle->read_req.event_handle = CreateEvent(NULL, 0, 0, NULL);
-      if (!handle->read_req.event_handle) {
-        uv_fatal_error(GetLastError(), "CreateEvent");
-      }
-    }
-    uv_tcp_queue_read(loop, handle);
-  }
-
-  return 0;
-}
-
-
-static int uv_tcp_try_connect(uv_connect_t* req,
-                              uv_tcp_t* handle,
-                              const struct sockaddr* addr,
-                              unsigned int addrlen,
-                              uv_connect_cb cb) {
-  uv_loop_t* loop = handle->loop;
-  const struct sockaddr* bind_addr;
-  struct sockaddr_storage converted;
-  BOOL success;
-  DWORD bytes;
-  int err;
-
-  err = uv__convert_to_localhost_if_unspecified(addr, &converted);
-  if (err)
-    return err;
-
-  if (handle->delayed_error) {
-    return handle->delayed_error;
-  }
-
-  if (!(handle->flags & UV_HANDLE_BOUND)) {
-    if (addrlen == sizeof(uv_addr_ip4_any_)) {
-      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
-    } else if (addrlen == sizeof(uv_addr_ip6_any_)) {
-      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
-    } else {
-      abort();
-    }
-    err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0);
-    if (err)
-      return err;
-    if (handle->delayed_error)
-      return handle->delayed_error;
-  }
-
-  if (!handle->tcp.conn.func_connectex) {
-    if (!uv_get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) {
-      return WSAEAFNOSUPPORT;
-    }
-  }
-
-  UV_REQ_INIT(req, UV_CONNECT);
-  req->handle = (uv_stream_t*) handle;
-  req->cb = cb;
-  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-
-  success = handle->tcp.conn.func_connectex(handle->socket,
-                                            (const struct sockaddr*) &converted,
-                                            addrlen,
-                                            NULL,
-                                            0,
-                                            &bytes,
-                                            &req->u.io.overlapped);
-
-  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
-    /* Process the req without IOCP. */
-    handle->reqs_pending++;
-    REGISTER_HANDLE_REQ(loop, handle, req);
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
-    /* The req will be processed with IOCP. */
-    handle->reqs_pending++;
-    REGISTER_HANDLE_REQ(loop, handle, req);
-  } else {
-    return WSAGetLastError();
-  }
-
-  return 0;
-}
-
-
-int uv_tcp_getsockname(const uv_tcp_t* handle,
-                       struct sockaddr* name,
-                       int* namelen) {
-
-  return uv__getsockpeername((const uv_handle_t*) handle,
-                             getsockname,
-                             name,
-                             namelen,
-                             handle->delayed_error);
-}
-
-
-int uv_tcp_getpeername(const uv_tcp_t* handle,
-                       struct sockaddr* name,
-                       int* namelen) {
-
-  return uv__getsockpeername((const uv_handle_t*) handle,
-                             getpeername,
-                             name,
-                             namelen,
-                             handle->delayed_error);
-}
-
-
-int uv_tcp_write(uv_loop_t* loop,
-                 uv_write_t* req,
-                 uv_tcp_t* handle,
-                 const uv_buf_t bufs[],
-                 unsigned int nbufs,
-                 uv_write_cb cb) {
-  int result;
-  DWORD bytes;
-
-  UV_REQ_INIT(req, UV_WRITE);
-  req->handle = (uv_stream_t*) handle;
-  req->cb = cb;
-
-  /* Prepare the overlapped structure. */
-  memset(&(req->u.io.overlapped), 0, sizeof(req->u.io.overlapped));
-  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-    req->event_handle = CreateEvent(NULL, 0, 0, NULL);
-    if (!req->event_handle) {
-      uv_fatal_error(GetLastError(), "CreateEvent");
-    }
-    req->u.io.overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
-    req->wait_handle = INVALID_HANDLE_VALUE;
-  }
-
-  result = WSASend(handle->socket,
-                   (WSABUF*) bufs,
-                   nbufs,
-                   &bytes,
-                   0,
-                   &req->u.io.overlapped,
-                   NULL);
-
-  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
-    /* Request completed immediately. */
-    req->u.io.queued_bytes = 0;
-    handle->reqs_pending++;
-    handle->stream.conn.write_reqs_pending++;
-    REGISTER_HANDLE_REQ(loop, handle, req);
-    uv_insert_pending_req(loop, (uv_req_t*) req);
-  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
-    /* Request queued by the kernel. */
-    req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
-    handle->reqs_pending++;
-    handle->stream.conn.write_reqs_pending++;
-    REGISTER_HANDLE_REQ(loop, handle, req);
-    handle->write_queue_size += req->u.io.queued_bytes;
-    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
-        !RegisterWaitForSingleObject(&req->wait_handle,
-          req->event_handle, post_write_completion, (void*) req,
-          INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
-      SET_REQ_ERROR(req, GetLastError());
-      uv_insert_pending_req(loop, (uv_req_t*)req);
-    }
-  } else {
-    /* Send failed due to an error, report it later */
-    req->u.io.queued_bytes = 0;
-    handle->reqs_pending++;
-    handle->stream.conn.write_reqs_pending++;
-    REGISTER_HANDLE_REQ(loop, handle, req);
-    SET_REQ_ERROR(req, WSAGetLastError());
-    uv_insert_pending_req(loop, (uv_req_t*) req);
-  }
-
-  return 0;
-}
-
-
-int uv__tcp_try_write(uv_tcp_t* handle,
-                     const uv_buf_t bufs[],
-                     unsigned int nbufs) {
-  int result;
-  DWORD bytes;
-
-  if (handle->stream.conn.write_reqs_pending > 0)
-    return UV_EAGAIN;
-
-  result = WSASend(handle->socket,
-                   (WSABUF*) bufs,
-                   nbufs,
-                   &bytes,
-                   0,
-                   NULL,
-                   NULL);
-
-  if (result == SOCKET_ERROR)
-    return uv_translate_sys_error(WSAGetLastError());
-  else
-    return bytes;
-}
-
-
-void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle,
-    uv_req_t* req) {
-  DWORD bytes, flags, err;
-  uv_buf_t buf;
-  int count;
-
-  assert(handle->type == UV_TCP);
-
-  handle->flags &= ~UV_HANDLE_READ_PENDING;
-
-  if (!REQ_SUCCESS(req)) {
-    /* An error occurred doing the read. */
-    if ((handle->flags & UV_HANDLE_READING) ||
-        !(handle->flags & UV_HANDLE_ZERO_READ)) {
-      handle->flags &= ~UV_HANDLE_READING;
-      DECREASE_ACTIVE_COUNT(loop, handle);
-      buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
-            uv_buf_init(NULL, 0) : handle->tcp.conn.read_buffer;
-
-      err = GET_REQ_SOCK_ERROR(req);
-
-      if (err == WSAECONNABORTED) {
-        /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix.
-         */
-        err = WSAECONNRESET;
-      }
-
-      handle->read_cb((uv_stream_t*)handle,
-                      uv_translate_sys_error(err),
-                      &buf);
-    }
-  } else {
-    if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
-      /* The read was done with a non-zero buffer length. */
-      if (req->u.io.overlapped.InternalHigh > 0) {
-        /* Successful read */
-        handle->read_cb((uv_stream_t*)handle,
-                        req->u.io.overlapped.InternalHigh,
-                        &handle->tcp.conn.read_buffer);
-        /* Read again only if bytes == buf.len */
-        if (req->u.io.overlapped.InternalHigh < handle->tcp.conn.read_buffer.len) {
-          goto done;
-        }
-      } else {
-        /* Connection closed */
-        if (handle->flags & UV_HANDLE_READING) {
-          handle->flags &= ~UV_HANDLE_READING;
-          DECREASE_ACTIVE_COUNT(loop, handle);
-        }
-        handle->flags &= ~UV_HANDLE_READABLE;
-
-        buf.base = 0;
-        buf.len = 0;
-        handle->read_cb((uv_stream_t*)handle, UV_EOF, &handle->tcp.conn.read_buffer);
-        goto done;
-      }
-    }
-
-    /* Do nonblocking reads until the buffer is empty */
-    count = 32;
-    while ((handle->flags & UV_HANDLE_READING) && (count-- > 0)) {
-      buf = uv_buf_init(NULL, 0);
-      handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
-      if (buf.base == NULL || buf.len == 0) {
-        handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
-        break;
-      }
-      assert(buf.base != NULL);
-
-      flags = 0;
-      if (WSARecv(handle->socket,
-                  (WSABUF*)&buf,
-                  1,
-                  &bytes,
-                  &flags,
-                  NULL,
-                  NULL) != SOCKET_ERROR) {
-        if (bytes > 0) {
-          /* Successful read */
-          handle->read_cb((uv_stream_t*)handle, bytes, &buf);
-          /* Read again only if bytes == buf.len */
-          if (bytes < buf.len) {
-            break;
-          }
-        } else {
-          /* Connection closed */
-          handle->flags &= ~(UV_HANDLE_READING | UV_HANDLE_READABLE);
-          DECREASE_ACTIVE_COUNT(loop, handle);
-
-          handle->read_cb((uv_stream_t*)handle, UV_EOF, &buf);
-          break;
-        }
-      } else {
-        err = WSAGetLastError();
-        if (err == WSAEWOULDBLOCK) {
-          /* Read buffer was completely empty, report a 0-byte read. */
-          handle->read_cb((uv_stream_t*)handle, 0, &buf);
-        } else {
-          /* Ouch! serious error. */
-          handle->flags &= ~UV_HANDLE_READING;
-          DECREASE_ACTIVE_COUNT(loop, handle);
-
-          if (err == WSAECONNABORTED) {
-            /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with
-             * Unix. */
-            err = WSAECONNRESET;
-          }
-
-          handle->read_cb((uv_stream_t*)handle,
-                          uv_translate_sys_error(err),
-                          &buf);
-        }
-        break;
-      }
-    }
-
-done:
-    /* Post another read if still reading and not closing. */
-    if ((handle->flags & UV_HANDLE_READING) &&
-        !(handle->flags & UV_HANDLE_READ_PENDING)) {
-      uv_tcp_queue_read(loop, handle);
-    }
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
-    uv_write_t* req) {
-  int err;
-
-  assert(handle->type == UV_TCP);
-
-  assert(handle->write_queue_size >= req->u.io.queued_bytes);
-  handle->write_queue_size -= req->u.io.queued_bytes;
-
-  UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
-    if (req->wait_handle != INVALID_HANDLE_VALUE) {
-      UnregisterWait(req->wait_handle);
-      req->wait_handle = INVALID_HANDLE_VALUE;
-    }
-    if (req->event_handle) {
-      CloseHandle(req->event_handle);
-      req->event_handle = NULL;
-    }
-  }
-
-  if (req->cb) {
-    err = uv_translate_sys_error(GET_REQ_SOCK_ERROR(req));
-    if (err == UV_ECONNABORTED) {
-      /* use UV_ECANCELED for consistency with Unix */
-      err = UV_ECANCELED;
-    }
-    req->cb(req, err);
-  }
-
-  handle->stream.conn.write_reqs_pending--;
-  if (handle->stream.conn.shutdown_req != NULL &&
-      handle->stream.conn.write_reqs_pending == 0) {
-    uv_want_endgame(loop, (uv_handle_t*)handle);
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle,
-    uv_req_t* raw_req) {
-  uv_tcp_accept_t* req = (uv_tcp_accept_t*) raw_req;
-  int err;
-
-  assert(handle->type == UV_TCP);
-
-  /* If handle->accepted_socket is not a valid socket, then uv_queue_accept
-   * must have failed. This is a serious error. We stop accepting connections
-   * and report this error to the connection callback. */
-  if (req->accept_socket == INVALID_SOCKET) {
-    if (handle->flags & UV_HANDLE_LISTENING) {
-      handle->flags &= ~UV_HANDLE_LISTENING;
-      DECREASE_ACTIVE_COUNT(loop, handle);
-      if (handle->stream.serv.connection_cb) {
-        err = GET_REQ_SOCK_ERROR(req);
-        handle->stream.serv.connection_cb((uv_stream_t*)handle,
-                                      uv_translate_sys_error(err));
-      }
-    }
-  } else if (REQ_SUCCESS(req) &&
-      setsockopt(req->accept_socket,
-                  SOL_SOCKET,
-                  SO_UPDATE_ACCEPT_CONTEXT,
-                  (char*)&handle->socket,
-                  sizeof(handle->socket)) == 0) {
-    req->next_pending = handle->tcp.serv.pending_accepts;
-    handle->tcp.serv.pending_accepts = req;
-
-    /* Accept and SO_UPDATE_ACCEPT_CONTEXT were successful. */
-    if (handle->stream.serv.connection_cb) {
-      handle->stream.serv.connection_cb((uv_stream_t*)handle, 0);
-    }
-  } else {
-    /* Error related to accepted socket is ignored because the server socket
-     * may still be healthy. If the server socket is broken uv_queue_accept
-     * will detect it. */
-    closesocket(req->accept_socket);
-    req->accept_socket = INVALID_SOCKET;
-    if (handle->flags & UV_HANDLE_LISTENING) {
-      uv_tcp_queue_accept(handle, req);
-    }
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
-    uv_connect_t* req) {
-  int err;
-
-  assert(handle->type == UV_TCP);
-
-  UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-  err = 0;
-  if (REQ_SUCCESS(req)) {
-    if (handle->flags & UV_HANDLE_CLOSING) {
-      /* use UV_ECANCELED for consistency with Unix */
-      err = ERROR_OPERATION_ABORTED;
-    } else if (setsockopt(handle->socket,
-                          SOL_SOCKET,
-                          SO_UPDATE_CONNECT_CONTEXT,
-                          NULL,
-                          0) == 0) {
-      uv_connection_init((uv_stream_t*)handle);
-      handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
-      loop->active_tcp_streams++;
-    } else {
-      err = WSAGetLastError();
-    }
-  } else {
-    err = GET_REQ_SOCK_ERROR(req);
-  }
-  req->cb(req, uv_translate_sys_error(err));
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-int uv__tcp_xfer_export(uv_tcp_t* handle,
-                        int target_pid,
-                        uv__ipc_socket_xfer_type_t* xfer_type,
-                        uv__ipc_socket_xfer_info_t* xfer_info) {
-  if (handle->flags & UV_HANDLE_CONNECTION) {
-    *xfer_type = UV__IPC_SOCKET_XFER_TCP_CONNECTION;
-  } else {
-    *xfer_type = UV__IPC_SOCKET_XFER_TCP_SERVER;
-    /* We're about to share the socket with another process. Because this is a
-     * listening socket, we assume that the other process will be accepting
-     * connections on it. Thus, before sharing the socket with another process,
-     * we call listen here in the parent process. */
-    if (!(handle->flags & UV_HANDLE_LISTENING)) {
-      if (!(handle->flags & UV_HANDLE_BOUND)) {
-        return ERROR_NOT_SUPPORTED;
-      }
-      if (handle->delayed_error == 0 &&
-          listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
-        handle->delayed_error = WSAGetLastError();
-      }
-    }
-  }
-
-  if (WSADuplicateSocketW(handle->socket, target_pid, &xfer_info->socket_info))
-    return WSAGetLastError();
-  xfer_info->delayed_error = handle->delayed_error;
-
-  /* Mark the local copy of the handle as 'shared' so we behave in a way that's
-   * friendly to the process(es) that we share the socket with. */
-  handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET;
-
-  return 0;
-}
-
-
-int uv__tcp_xfer_import(uv_tcp_t* tcp,
-                        uv__ipc_socket_xfer_type_t xfer_type,
-                        uv__ipc_socket_xfer_info_t* xfer_info) {
-  int err;
-  SOCKET socket;
-
-  assert(xfer_type == UV__IPC_SOCKET_XFER_TCP_SERVER ||
-         xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION);
-
-  socket = WSASocketW(FROM_PROTOCOL_INFO,
-                      FROM_PROTOCOL_INFO,
-                      FROM_PROTOCOL_INFO,
-                      &xfer_info->socket_info,
-                      0,
-                      WSA_FLAG_OVERLAPPED);
-
-  if (socket == INVALID_SOCKET) {
-    return WSAGetLastError();
-  }
-
-  err = uv_tcp_set_socket(
-      tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1);
-  if (err) {
-    closesocket(socket);
-    return err;
-  }
-
-  tcp->delayed_error = xfer_info->delayed_error;
-  tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET;
-
-  if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) {
-    uv_connection_init((uv_stream_t*)tcp);
-    tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
-  }
-
-  tcp->loop->active_tcp_streams++;
-  return 0;
-}
-
-
-int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {
-  int err;
-
-  if (handle->socket != INVALID_SOCKET) {
-    err = uv__tcp_nodelay(handle, handle->socket, enable);
-    if (err)
-      return err;
-  }
-
-  if (enable) {
-    handle->flags |= UV_HANDLE_TCP_NODELAY;
-  } else {
-    handle->flags &= ~UV_HANDLE_TCP_NODELAY;
-  }
-
-  return 0;
-}
-
-
-int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
-  int err;
-
-  if (handle->socket != INVALID_SOCKET) {
-    err = uv__tcp_keepalive(handle, handle->socket, enable, delay);
-    if (err)
-      return err;
-  }
-
-  if (enable) {
-    handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
-  } else {
-    handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
-  }
-
-  /* TODO: Store delay if handle->socket isn't created yet. */
-
-  return 0;
-}
-
-
-int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) {
-  if (handle->flags & UV_HANDLE_CONNECTION) {
-    return UV_EINVAL;
-  }
-
-  /* Check if we're already in the desired mode. */
-  if ((enable && !(handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) ||
-      (!enable && handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {
-    return 0;
-  }
-
-  /* Don't allow switching from single pending accept to many. */
-  if (enable) {
-    return UV_ENOTSUP;
-  }
-
-  /* Check if we're in a middle of changing the number of pending accepts. */
-  if (handle->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING) {
-    return 0;
-  }
-
-  handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
-
-  /* Flip the changing flag if we have already queued multiple accepts. */
-  if (handle->flags & UV_HANDLE_LISTENING) {
-    handle->flags |= UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
-  }
-
-  return 0;
-}
-
-
-static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) {
-  SOCKET socket = tcp->socket;
-  int non_ifs_lsp;
-
-  /* Check if we have any non-IFS LSPs stacked on top of TCP */
-  non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
-                                                uv_tcp_non_ifs_lsp_ipv4;
-
-  /* If there are non-ifs LSPs then try to obtain a base handle for the socket.
-   * This will always fail on Windows XP/3k. */
-  if (non_ifs_lsp) {
-    DWORD bytes;
-    if (WSAIoctl(socket,
-                 SIO_BASE_HANDLE,
-                 NULL,
-                 0,
-                 &socket,
-                 sizeof socket,
-                 &bytes,
-                 NULL,
-                 NULL) != 0) {
-      /* Failed. We can't do CancelIo. */
-      return -1;
-    }
-  }
-
-  assert(socket != 0 && socket != INVALID_SOCKET);
-
-  if (!CancelIo((HANDLE) socket)) {
-    return GetLastError();
-  }
-
-  /* It worked. */
-  return 0;
-}
-
-
-void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) {
-  int close_socket = 1;
-
-  if (tcp->flags & UV_HANDLE_READ_PENDING) {
-    /* In order for winsock to do a graceful close there must not be any any
-     * pending reads, or the socket must be shut down for writing */
-    if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) {
-      /* Just do shutdown on non-shared sockets, which ensures graceful close. */
-      shutdown(tcp->socket, SD_SEND);
-
-    } else if (uv_tcp_try_cancel_io(tcp) == 0) {
-      /* In case of a shared socket, we try to cancel all outstanding I/O,. If
-       * that works, don't close the socket yet - wait for the read req to
-       * return and close the socket in uv_tcp_endgame. */
-      close_socket = 0;
-
-    } else {
-      /* When cancelling isn't possible - which could happen when an LSP is
-       * present on an old Windows version, we will have to close the socket
-       * with a read pending. That is not nice because trailing sent bytes may
-       * not make it to the other side. */
-    }
-
-  } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) &&
-             tcp->tcp.serv.accept_reqs != NULL) {
-    /* Under normal circumstances closesocket() will ensure that all pending
-     * accept reqs are canceled. However, when the socket is shared the
-     * presence of another reference to the socket in another process will keep
-     * the accept reqs going, so we have to ensure that these are canceled. */
-    if (uv_tcp_try_cancel_io(tcp) != 0) {
-      /* When cancellation is not possible, there is another option: we can
-       * close the incoming sockets, which will also cancel the accept
-       * operations. However this is not cool because we might inadvertently
-       * close a socket that just accepted a new connection, which will cause
-       * the connection to be aborted. */
-      unsigned int i;
-      for (i = 0; i < uv_simultaneous_server_accepts; i++) {
-        uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i];
-        if (req->accept_socket != INVALID_SOCKET &&
-            !HasOverlappedIoCompleted(&req->u.io.overlapped)) {
-          closesocket(req->accept_socket);
-          req->accept_socket = INVALID_SOCKET;
-        }
-      }
-    }
-  }
-
-  if (tcp->flags & UV_HANDLE_READING) {
-    tcp->flags &= ~UV_HANDLE_READING;
-    DECREASE_ACTIVE_COUNT(loop, tcp);
-  }
-
-  if (tcp->flags & UV_HANDLE_LISTENING) {
-    tcp->flags &= ~UV_HANDLE_LISTENING;
-    DECREASE_ACTIVE_COUNT(loop, tcp);
-  }
-
-  if (close_socket) {
-    closesocket(tcp->socket);
-    tcp->socket = INVALID_SOCKET;
-    tcp->flags |= UV_HANDLE_TCP_SOCKET_CLOSED;
-  }
-
-  tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
-  uv__handle_closing(tcp);
-
-  if (tcp->reqs_pending == 0) {
-    uv_want_endgame(tcp->loop, (uv_handle_t*)tcp);
-  }
-}
-
-
-int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
-  WSAPROTOCOL_INFOW protocol_info;
-  int opt_len;
-  int err;
-  struct sockaddr_storage saddr;
-  int saddr_len;
-
-  /* Detect the address family of the socket. */
-  opt_len = (int) sizeof protocol_info;
-  if (getsockopt(sock,
-                 SOL_SOCKET,
-                 SO_PROTOCOL_INFOW,
-                 (char*) &protocol_info,
-                 &opt_len) == SOCKET_ERROR) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  err = uv_tcp_set_socket(handle->loop,
-                          handle,
-                          sock,
-                          protocol_info.iAddressFamily,
-                          1);
-  if (err) {
-    return uv_translate_sys_error(err);
-  }
-
-  /* Support already active socket. */
-  saddr_len = sizeof(saddr);
-  if (!uv_tcp_getsockname(handle, (struct sockaddr*) &saddr, &saddr_len)) {
-    /* Socket is already bound. */
-    handle->flags |= UV_HANDLE_BOUND;
-    saddr_len = sizeof(saddr);
-    if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) {
-      /* Socket is already connected. */
-      uv_connection_init((uv_stream_t*) handle);
-      handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
-    }
-  }
-
-  return 0;
-}
-
-
-/* This function is an egress point, i.e. it returns libuv errors rather than
- * system errors.
- */
-int uv__tcp_bind(uv_tcp_t* handle,
-                 const struct sockaddr* addr,
-                 unsigned int addrlen,
-                 unsigned int flags) {
-  int err;
-
-  err = uv_tcp_try_bind(handle, addr, addrlen, flags);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  return 0;
-}
-
-
-/* This function is an egress point, i.e. it returns libuv errors rather than
- * system errors.
- */
-int uv__tcp_connect(uv_connect_t* req,
-                    uv_tcp_t* handle,
-                    const struct sockaddr* addr,
-                    unsigned int addrlen,
-                    uv_connect_cb cb) {
-  int err;
-
-  err = uv_tcp_try_connect(req, handle, addr, addrlen, cb);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/thread.cpp b/wpiutil/src/main/native/libuv/src/win/thread.cpp
deleted file mode 100644
index 72af03c..0000000
--- a/wpiutil/src/main/native/libuv/src/win/thread.cpp
+++ /dev/null
@@ -1,520 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <limits.h>
-#include <stdlib.h>
-
-#if defined(__MINGW64_VERSION_MAJOR)
-/* MemoryBarrier expands to __mm_mfence in some cases (x86+sse2), which may
- * require this header in some versions of mingw64. */
-#include <intrin.h>
-#endif
-
-#include "uv.h"
-#include "internal.h"
-
-static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
-  DWORD result;
-  HANDLE existing_event, created_event;
-
-  created_event = CreateEvent(NULL, 1, 0, NULL);
-  if (created_event == 0) {
-    /* Could fail in a low-memory situation? */
-    uv_fatal_error(GetLastError(), "CreateEvent");
-  }
-
-  existing_event = InterlockedCompareExchangePointer(&guard->event,
-                                                     created_event,
-                                                     NULL);
-
-  if (existing_event == NULL) {
-    /* We won the race */
-    callback();
-
-    result = SetEvent(created_event);
-    assert(result);
-    guard->ran = 1;
-
-  } else {
-    /* We lost the race. Destroy the event we created and wait for the existing
-     * one to become signaled. */
-    CloseHandle(created_event);
-    result = WaitForSingleObject(existing_event, INFINITE);
-    assert(result == WAIT_OBJECT_0);
-  }
-}
-
-
-void uv_once(uv_once_t* guard, void (*callback)(void)) {
-  /* Fast case - avoid WaitForSingleObject. */
-  if (guard->ran) {
-    return;
-  }
-
-  uv__once_inner(guard, callback);
-}
-
-
-/* Verify that uv_thread_t can be stored in a TLS slot. */
-STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*));
-
-static uv_key_t uv__current_thread_key;
-static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT;
-
-
-static void uv__init_current_thread_key(void) {
-  if (uv_key_create(&uv__current_thread_key))
-    abort();
-}
-
-
-struct thread_ctx {
-  void (*entry)(void* arg);
-  void* arg;
-  uv_thread_t self;
-};
-
-
-static UINT __stdcall uv__thread_start(void* arg) {
-  struct thread_ctx *ctx_p;
-  struct thread_ctx ctx;
-
-  ctx_p = (struct thread_ctx*)arg;
-  ctx = *ctx_p;
-  uv__free(ctx_p);
-
-  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
-  uv_key_set(&uv__current_thread_key, (void*) ctx.self);
-
-  ctx.entry(ctx.arg);
-
-  return 0;
-}
-
-
-int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
-  uv_thread_options_t params;
-  params.flags = UV_THREAD_NO_FLAGS;
-  return uv_thread_create_ex(tid, &params, entry, arg);
-}
-
-int uv_thread_create_ex(uv_thread_t* tid,
-                        const uv_thread_options_t* params,
-                        void (*entry)(void *arg),
-                        void *arg) {
-  struct thread_ctx* ctx;
-  int err;
-  HANDLE thread;
-  SYSTEM_INFO sysinfo;
-  size_t stack_size;
-  size_t pagesize;
-
-  stack_size =
-      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
-
-  if (stack_size != 0) {
-    GetNativeSystemInfo(&sysinfo);
-    pagesize = (size_t)sysinfo.dwPageSize;
-    /* Round up to the nearest page boundary. */
-    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
-
-    if ((unsigned)stack_size != stack_size)
-      return UV_EINVAL;
-  }
-
-  ctx = (struct thread_ctx*)uv__malloc(sizeof(*ctx));
-  if (ctx == NULL)
-    return UV_ENOMEM;
-
-  ctx->entry = entry;
-  ctx->arg = arg;
-
-  /* Create the thread in suspended state so we have a chance to pass
-   * its own creation handle to it */
-  thread = (HANDLE) _beginthreadex(NULL,
-                                   (unsigned)stack_size,
-                                   uv__thread_start,
-                                   ctx,
-                                   CREATE_SUSPENDED,
-                                   NULL);
-  if (thread == NULL) {
-    err = errno;
-    uv__free(ctx);
-  } else {
-    err = 0;
-    *tid = thread;
-    ctx->self = thread;
-    ResumeThread(thread);
-  }
-
-  switch (err) {
-    case 0:
-      return 0;
-    case EACCES:
-      return UV_EACCES;
-    case EAGAIN:
-      return UV_EAGAIN;
-    case EINVAL:
-      return UV_EINVAL;
-  }
-
-  return UV_EIO;
-}
-
-
-uv_thread_t uv_thread_self(void) {
-  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);
-  return (uv_thread_t) uv_key_get(&uv__current_thread_key);
-}
-
-
-int uv_thread_join(uv_thread_t *tid) {
-  if (WaitForSingleObject(*tid, INFINITE))
-    return uv_translate_sys_error(GetLastError());
-  else {
-    CloseHandle(*tid);
-    *tid = 0;
-    MemoryBarrier();  /* For feature parity with pthread_join(). */
-    return 0;
-  }
-}
-
-
-int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
-  return *t1 == *t2;
-}
-
-
-int uv_mutex_init(uv_mutex_t* mutex) {
-  InitializeCriticalSection(mutex);
-  return 0;
-}
-
-
-int uv_mutex_init_recursive(uv_mutex_t* mutex) {
-  return uv_mutex_init(mutex);
-}
-
-
-void uv_mutex_destroy(uv_mutex_t* mutex) {
-  DeleteCriticalSection(mutex);
-}
-
-
-void uv_mutex_lock(uv_mutex_t* mutex) {
-  EnterCriticalSection(mutex);
-}
-
-
-int uv_mutex_trylock(uv_mutex_t* mutex) {
-  if (TryEnterCriticalSection(mutex))
-    return 0;
-  else
-    return UV_EBUSY;
-}
-
-
-void uv_mutex_unlock(uv_mutex_t* mutex) {
-  LeaveCriticalSection(mutex);
-}
-
-
-int uv_rwlock_init(uv_rwlock_t* rwlock) {
-  /* Initialize the semaphore that acts as the write lock. */
-  HANDLE handle = CreateSemaphoreW(NULL, 1, 1, NULL);
-  if (handle == NULL)
-    return uv_translate_sys_error(GetLastError());
-  rwlock->state_.write_semaphore_ = handle;
-
-  /* Initialize the critical section protecting the reader count. */
-  InitializeCriticalSection(&rwlock->state_.num_readers_lock_);
-
-  /* Initialize the reader count. */
-  rwlock->state_.num_readers_ = 0;
-
-  return 0;
-}
-
-
-void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
-  DeleteCriticalSection(&rwlock->state_.num_readers_lock_);
-  CloseHandle(rwlock->state_.write_semaphore_);
-}
-
-
-void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
-  /* Acquire the lock that protects the reader count. */
-  EnterCriticalSection(&rwlock->state_.num_readers_lock_);
-
-  /* Increase the reader count, and lock for write if this is the first
-   * reader.
-   */
-  if (++rwlock->state_.num_readers_ == 1) {
-    DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE);
-    if (r != WAIT_OBJECT_0)
-      uv_fatal_error(GetLastError(), "WaitForSingleObject");
-  }
-
-  /* Release the lock that protects the reader count. */
-  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
-}
-
-
-int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
-  int err;
-
-  if (!TryEnterCriticalSection(&rwlock->state_.num_readers_lock_))
-    return UV_EBUSY;
-
-  err = 0;
-
-  if (rwlock->state_.num_readers_ == 0) {
-    /* Currently there are no other readers, which means that the write lock
-     * needs to be acquired.
-     */
-    DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0);
-    if (r == WAIT_OBJECT_0)
-      rwlock->state_.num_readers_++;
-    else if (r == WAIT_TIMEOUT)
-      err = UV_EBUSY;
-    else if (r == WAIT_FAILED)
-      uv_fatal_error(GetLastError(), "WaitForSingleObject");
-
-  } else {
-    /* The write lock has already been acquired because there are other
-     * active readers.
-     */
-    rwlock->state_.num_readers_++;
-  }
-
-  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
-  return err;
-}
-
-
-void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
-  EnterCriticalSection(&rwlock->state_.num_readers_lock_);
-
-  if (--rwlock->state_.num_readers_ == 0) {
-    if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL))
-      uv_fatal_error(GetLastError(), "ReleaseSemaphore");
-  }
-
-  LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
-}
-
-
-void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
-  DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE);
-  if (r != WAIT_OBJECT_0)
-    uv_fatal_error(GetLastError(), "WaitForSingleObject");
-}
-
-
-int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
-  DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0);
-  if (r == WAIT_OBJECT_0)
-    return 0;
-  else if (r == WAIT_TIMEOUT)
-    return UV_EBUSY;
-  else
-    uv_fatal_error(GetLastError(), "WaitForSingleObject");
-}
-
-
-void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
-  if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL))
-    uv_fatal_error(GetLastError(), "ReleaseSemaphore");
-}
-
-
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
-  *sem = CreateSemaphore(NULL, value, INT_MAX, NULL);
-  if (*sem == NULL)
-    return uv_translate_sys_error(GetLastError());
-  else
-    return 0;
-}
-
-
-void uv_sem_destroy(uv_sem_t* sem) {
-  if (!CloseHandle(*sem))
-    abort();
-}
-
-
-void uv_sem_post(uv_sem_t* sem) {
-  if (!ReleaseSemaphore(*sem, 1, NULL))
-    abort();
-}
-
-
-void uv_sem_wait(uv_sem_t* sem) {
-  if (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0)
-    abort();
-}
-
-
-int uv_sem_trywait(uv_sem_t* sem) {
-  DWORD r = WaitForSingleObject(*sem, 0);
-
-  if (r == WAIT_OBJECT_0)
-    return 0;
-
-  if (r == WAIT_TIMEOUT)
-    return UV_EAGAIN;
-
-  abort();
-  return -1; /* Satisfy the compiler. */
-}
-
-
-int uv_cond_init(uv_cond_t* cond) {
-  InitializeConditionVariable(&cond->cond_var);
-  return 0;
-}
-
-
-void uv_cond_destroy(uv_cond_t* cond) {
-  /* nothing to do */
-  (void) &cond;
-}
-
-
-void uv_cond_signal(uv_cond_t* cond) {
-  WakeConditionVariable(&cond->cond_var);
-}
-
-
-void uv_cond_broadcast(uv_cond_t* cond) {
-  WakeAllConditionVariable(&cond->cond_var);
-}
-
-
-void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
-  if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
-    abort();
-}
-
-int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
-  if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
-    return 0;
-  if (GetLastError() != ERROR_TIMEOUT)
-    abort();
-  return UV_ETIMEDOUT;
-}
-
-
-int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
-  int err;
-
-  barrier->n = count;
-  barrier->count = 0;
-
-  err = uv_mutex_init(&barrier->mutex);
-  if (err)
-    return err;
-
-  err = uv_sem_init(&barrier->turnstile1, 0);
-  if (err)
-    goto error2;
-
-  err = uv_sem_init(&barrier->turnstile2, 1);
-  if (err)
-    goto error;
-
-  return 0;
-
-error:
-  uv_sem_destroy(&barrier->turnstile1);
-error2:
-  uv_mutex_destroy(&barrier->mutex);
-  return err;
-
-}
-
-
-void uv_barrier_destroy(uv_barrier_t* barrier) {
-  uv_sem_destroy(&barrier->turnstile2);
-  uv_sem_destroy(&barrier->turnstile1);
-  uv_mutex_destroy(&barrier->mutex);
-}
-
-
-int uv_barrier_wait(uv_barrier_t* barrier) {
-  int serial_thread;
-
-  uv_mutex_lock(&barrier->mutex);
-  if (++barrier->count == barrier->n) {
-    uv_sem_wait(&barrier->turnstile2);
-    uv_sem_post(&barrier->turnstile1);
-  }
-  uv_mutex_unlock(&barrier->mutex);
-
-  uv_sem_wait(&barrier->turnstile1);
-  uv_sem_post(&barrier->turnstile1);
-
-  uv_mutex_lock(&barrier->mutex);
-  serial_thread = (--barrier->count == 0);
-  if (serial_thread) {
-    uv_sem_wait(&barrier->turnstile1);
-    uv_sem_post(&barrier->turnstile2);
-  }
-  uv_mutex_unlock(&barrier->mutex);
-
-  uv_sem_wait(&barrier->turnstile2);
-  uv_sem_post(&barrier->turnstile2);
-  return serial_thread;
-}
-
-
-int uv_key_create(uv_key_t* key) {
-  key->tls_index = TlsAlloc();
-  if (key->tls_index == TLS_OUT_OF_INDEXES)
-    return UV_ENOMEM;
-  return 0;
-}
-
-
-void uv_key_delete(uv_key_t* key) {
-  if (TlsFree(key->tls_index) == FALSE)
-    abort();
-  key->tls_index = TLS_OUT_OF_INDEXES;
-}
-
-
-void* uv_key_get(uv_key_t* key) {
-  void* value;
-
-  value = TlsGetValue(key->tls_index);
-  if (value == NULL)
-    if (GetLastError() != ERROR_SUCCESS)
-      abort();
-
-  return value;
-}
-
-
-void uv_key_set(uv_key_t* key, void* value) {
-  if (TlsSetValue(key->tls_index, value) == FALSE)
-    abort();
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/tty.cpp b/wpiutil/src/main/native/libuv/src/win/tty.cpp
deleted file mode 100644
index e4d7ac9..0000000
--- a/wpiutil/src/main/native/libuv/src/win/tty.cpp
+++ /dev/null
@@ -1,2335 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#define _CRT_NONSTDC_NO_WARNINGS
-
-#include <assert.h>
-#include <io.h>
-#include <string.h>
-#include <stdlib.h>
-
-#if defined(_MSC_VER) && _MSC_VER < 1600
-# include "uv/stdint-msvc2008.h"
-#else
-# include <stdint.h>
-#endif
-
-#ifndef COMMON_LVB_REVERSE_VIDEO
-# define COMMON_LVB_REVERSE_VIDEO 0x4000
-#endif
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "stream-inl.h"
-#include "req-inl.h"
-
-#pragma comment(lib, "User32.lib")
-
-#ifndef InterlockedOr
-# define InterlockedOr _InterlockedOr
-#endif
-
-#define UNICODE_REPLACEMENT_CHARACTER (0xfffd)
-
-#define ANSI_NORMAL           0x00
-#define ANSI_ESCAPE_SEEN      0x02
-#define ANSI_CSI              0x04
-#define ANSI_ST_CONTROL       0x08
-#define ANSI_IGNORE           0x10
-#define ANSI_IN_ARG           0x20
-#define ANSI_IN_STRING        0x40
-#define ANSI_BACKSLASH_SEEN   0x80
-
-#define MAX_INPUT_BUFFER_LENGTH 8192
-#define MAX_CONSOLE_CHAR 8192
-
-#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
-#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
-#endif
-
-static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info);
-static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info);
-static int uv__cancel_read_console(uv_tty_t* handle);
-
-
-/* Null uv_buf_t */
-static const uv_buf_t uv_null_buf_ = { 0, NULL };
-
-enum uv__read_console_status_e {
-  NOT_STARTED,
-  IN_PROGRESS,
-  TRAP_REQUESTED,
-  COMPLETED
-};
-
-static volatile LONG uv__read_console_status = NOT_STARTED;
-static volatile LONG uv__restore_screen_state;
-static CONSOLE_SCREEN_BUFFER_INFO uv__saved_screen_state;
-
-
-/*
- * The console virtual window.
- *
- * Normally cursor movement in windows is relative to the console screen buffer,
- * e.g. the application is allowed to overwrite the 'history'. This is very
- * inconvenient, it makes absolute cursor movement pretty useless. There is
- * also the concept of 'client rect' which is defined by the actual size of
- * the console window and the scroll position of the screen buffer, but it's
- * very volatile because it changes when the user scrolls.
- *
- * To make cursor movement behave sensibly we define a virtual window to which
- * cursor movement is confined. The virtual window is always as wide as the
- * console screen buffer, but it's height is defined by the size of the
- * console window. The top of the virtual window aligns with the position
- * of the caret when the first stdout/err handle is created, unless that would
- * mean that it would extend beyond the bottom of the screen buffer -  in that
- * that case it's located as far down as possible.
- *
- * When the user writes a long text or many newlines, such that the output
- * reaches beyond the bottom of the virtual window, the virtual window is
- * shifted downwards, but not resized.
- *
- * Since all tty i/o happens on the same console, this window is shared
- * between all stdout/stderr handles.
- */
-
-static int uv_tty_virtual_offset = -1;
-static int uv_tty_virtual_height = -1;
-static int uv_tty_virtual_width = -1;
-
-/* The console window size
- * We keep this separate from uv_tty_virtual_*. We use those values to only
- * handle signalling SIGWINCH
- */
-
-static HANDLE uv__tty_console_handle = INVALID_HANDLE_VALUE;
-static int uv__tty_console_height = -1;
-static int uv__tty_console_width = -1;
-
-static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param);
-static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook,
-                                                  DWORD event,
-                                                  HWND hwnd,
-                                                  LONG idObject,
-                                                  LONG idChild,
-                                                  DWORD dwEventThread,
-                                                  DWORD dwmsEventTime);
-
-/* We use a semaphore rather than a mutex or critical section because in some
-   cases (uv__cancel_read_console) we need take the lock in the main thread and
-   release it in another thread. Using a semaphore ensures that in such
-   scenario the main thread will still block when trying to acquire the lock. */
-static uv_sem_t uv_tty_output_lock;
-
-static WORD uv_tty_default_text_attributes =
-    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
-
-static char uv_tty_default_fg_color = 7;
-static char uv_tty_default_bg_color = 0;
-static char uv_tty_default_fg_bright = 0;
-static char uv_tty_default_bg_bright = 0;
-static char uv_tty_default_inverse = 0;
-
-typedef enum {
-  UV_SUPPORTED,
-  UV_UNCHECKED,
-  UV_UNSUPPORTED
-} uv_vtermstate_t;
-/* Determine whether or not ANSI support is enabled. */
-static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED;
-static void uv__determine_vterm_state(HANDLE handle);
-
-void uv_console_init(void) {
-  if (uv_sem_init(&uv_tty_output_lock, 1))
-    abort();
-  uv__tty_console_handle = CreateFileW(L"CONOUT$",
-                                       GENERIC_READ | GENERIC_WRITE,
-                                       FILE_SHARE_WRITE,
-                                       0,
-                                       OPEN_EXISTING,
-                                       0,
-                                       0);
-  if (uv__tty_console_handle != INVALID_HANDLE_VALUE) {
-    QueueUserWorkItem(uv__tty_console_resize_message_loop_thread,
-                      NULL,
-                      WT_EXECUTELONGFUNCTION);
-  }
-}
-
-
-int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
-  BOOL readable;
-  DWORD NumberOfEvents;
-  HANDLE handle;
-  CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
-  (void)unused;
-
-  uv__once_init();
-  handle = (HANDLE) uv__get_osfhandle(fd);
-  if (handle == INVALID_HANDLE_VALUE)
-    return UV_EBADF;
-
-  if (fd <= 2) {
-    /* In order to avoid closing a stdio file descriptor 0-2, duplicate the
-     * underlying OS handle and forget about the original fd.
-     * We could also opt to use the original OS handle and just never close it,
-     * but then there would be no reliable way to cancel pending read operations
-     * upon close.
-     */
-    if (!DuplicateHandle(INVALID_HANDLE_VALUE,
-                         handle,
-                         INVALID_HANDLE_VALUE,
-                         &handle,
-                         0,
-                         FALSE,
-                         DUPLICATE_SAME_ACCESS))
-      return uv_translate_sys_error(GetLastError());
-    fd = -1;
-  }
-
-  readable = GetNumberOfConsoleInputEvents(handle, &NumberOfEvents);
-  if (!readable) {
-    /* Obtain the screen buffer info with the output handle. */
-    if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) {
-      return uv_translate_sys_error(GetLastError());
-    }
-
-    /* Obtain the tty_output_lock because the virtual window state is shared
-     * between all uv_tty_t handles. */
-    uv_sem_wait(&uv_tty_output_lock);
-
-    if (uv__vterm_state == UV_UNCHECKED)
-      uv__determine_vterm_state(handle);
-
-    /* Remember the original console text attributes. */
-    uv_tty_capture_initial_style(&screen_buffer_info);
-
-    uv_tty_update_virtual_window(&screen_buffer_info);
-
-    uv_sem_post(&uv_tty_output_lock);
-  }
-
-
-  uv_stream_init(loop, (uv_stream_t*) tty, UV_TTY);
-  uv_connection_init((uv_stream_t*) tty);
-
-  tty->handle = handle;
-  tty->u.fd = fd;
-  tty->reqs_pending = 0;
-  tty->flags |= UV_HANDLE_BOUND;
-
-  if (readable) {
-    /* Initialize TTY input specific fields. */
-    tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE;
-    /* TODO: remove me in v2.x. */
-    tty->tty.rd.unused_ = NULL;
-    tty->tty.rd.read_line_buffer = uv_null_buf_;
-    tty->tty.rd.read_raw_wait = NULL;
-
-    /* Init keycode-to-vt100 mapper state. */
-    tty->tty.rd.last_key_len = 0;
-    tty->tty.rd.last_key_offset = 0;
-    tty->tty.rd.last_utf16_high_surrogate = 0;
-    memset(&tty->tty.rd.last_input_record, 0, sizeof tty->tty.rd.last_input_record);
-  } else {
-    /* TTY output specific fields. */
-    tty->flags |= UV_HANDLE_WRITABLE;
-
-    /* Init utf8-to-utf16 conversion state. */
-    tty->tty.wr.utf8_bytes_left = 0;
-    tty->tty.wr.utf8_codepoint = 0;
-
-    /* Initialize eol conversion state */
-    tty->tty.wr.previous_eol = 0;
-
-    /* Init ANSI parser state. */
-    tty->tty.wr.ansi_parser_state = ANSI_NORMAL;
-  }
-
-  return 0;
-}
-
-
-/* Set the default console text attributes based on how the console was
- * configured when libuv started.
- */
-static void uv_tty_capture_initial_style(CONSOLE_SCREEN_BUFFER_INFO* info) {
-  static int style_captured = 0;
-
-  /* Only do this once.
-     Assumption: Caller has acquired uv_tty_output_lock. */
-  if (style_captured)
-    return;
-
-  /* Save raw win32 attributes. */
-  uv_tty_default_text_attributes = info->wAttributes;
-
-  /* Convert black text on black background to use white text. */
-  if (uv_tty_default_text_attributes == 0)
-    uv_tty_default_text_attributes = 7;
-
-  /* Convert Win32 attributes to ANSI colors. */
-  uv_tty_default_fg_color = 0;
-  uv_tty_default_bg_color = 0;
-  uv_tty_default_fg_bright = 0;
-  uv_tty_default_bg_bright = 0;
-  uv_tty_default_inverse = 0;
-
-  if (uv_tty_default_text_attributes & FOREGROUND_RED)
-    uv_tty_default_fg_color |= 1;
-
-  if (uv_tty_default_text_attributes & FOREGROUND_GREEN)
-    uv_tty_default_fg_color |= 2;
-
-  if (uv_tty_default_text_attributes & FOREGROUND_BLUE)
-    uv_tty_default_fg_color |= 4;
-
-  if (uv_tty_default_text_attributes & BACKGROUND_RED)
-    uv_tty_default_bg_color |= 1;
-
-  if (uv_tty_default_text_attributes & BACKGROUND_GREEN)
-    uv_tty_default_bg_color |= 2;
-
-  if (uv_tty_default_text_attributes & BACKGROUND_BLUE)
-    uv_tty_default_bg_color |= 4;
-
-  if (uv_tty_default_text_attributes & FOREGROUND_INTENSITY)
-    uv_tty_default_fg_bright = 1;
-
-  if (uv_tty_default_text_attributes & BACKGROUND_INTENSITY)
-    uv_tty_default_bg_bright = 1;
-
-  if (uv_tty_default_text_attributes & COMMON_LVB_REVERSE_VIDEO)
-    uv_tty_default_inverse = 1;
-
-  style_captured = 1;
-}
-
-
-int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
-  DWORD flags;
-  unsigned char was_reading;
-  uv_alloc_cb alloc_cb;
-  uv_read_cb read_cb;
-  int err;
-
-  if (!(tty->flags & UV_HANDLE_TTY_READABLE)) {
-    return UV_EINVAL;
-  }
-
-  if (!!mode == !!(tty->flags & UV_HANDLE_TTY_RAW)) {
-    return 0;
-  }
-
-  switch (mode) {
-    case UV_TTY_MODE_NORMAL:
-      flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
-      break;
-    case UV_TTY_MODE_RAW:
-      flags = ENABLE_WINDOW_INPUT;
-      break;
-    case UV_TTY_MODE_IO:
-      return UV_ENOTSUP;
-    default:
-      return UV_EINVAL;
-  }
-
-  /* If currently reading, stop, and restart reading. */
-  if (tty->flags & UV_HANDLE_READING) {
-    was_reading = 1;
-    alloc_cb = tty->alloc_cb;
-    read_cb = tty->read_cb;
-    err = uv_tty_read_stop(tty);
-    if (err) {
-      return uv_translate_sys_error(err);
-    }
-  } else {
-    was_reading = 0;
-    alloc_cb = NULL;
-    read_cb = NULL;
-  }
-
-  uv_sem_wait(&uv_tty_output_lock);
-  if (!SetConsoleMode(tty->handle, flags)) {
-    err = uv_translate_sys_error(GetLastError());
-    uv_sem_post(&uv_tty_output_lock);
-    return err;
-  }
-  uv_sem_post(&uv_tty_output_lock);
-
-  /* Update flag. */
-  tty->flags &= ~UV_HANDLE_TTY_RAW;
-  tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0;
-
-  /* If we just stopped reading, restart. */
-  if (was_reading) {
-    err = uv_tty_read_start(tty, alloc_cb, read_cb);
-    if (err) {
-      return uv_translate_sys_error(err);
-    }
-  }
-
-  return 0;
-}
-
-
-int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
-  CONSOLE_SCREEN_BUFFER_INFO info;
-
-  if (!GetConsoleScreenBufferInfo(tty->handle, &info)) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  uv_sem_wait(&uv_tty_output_lock);
-  uv_tty_update_virtual_window(&info);
-  uv_sem_post(&uv_tty_output_lock);
-
-  *width = uv_tty_virtual_width;
-  *height = uv_tty_virtual_height;
-
-  return 0;
-}
-
-
-static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) {
-  uv_loop_t* loop;
-  uv_tty_t* handle;
-  uv_req_t* req;
-
-  assert(data);
-  assert(!didTimeout);
-
-  req = (uv_req_t*) data;
-  handle = (uv_tty_t*) req->data;
-  loop = handle->loop;
-
-  UnregisterWait(handle->tty.rd.read_raw_wait);
-  handle->tty.rd.read_raw_wait = NULL;
-
-  SET_REQ_SUCCESS(req);
-  POST_COMPLETION_FOR_REQ(loop, req);
-}
-
-
-static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) {
-  uv_read_t* req;
-  BOOL r;
-
-  assert(handle->flags & UV_HANDLE_READING);
-  assert(!(handle->flags & UV_HANDLE_READ_PENDING));
-
-  assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE);
-
-  handle->tty.rd.read_line_buffer = uv_null_buf_;
-
-  req = &handle->read_req;
-  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-
-  r = RegisterWaitForSingleObject(&handle->tty.rd.read_raw_wait,
-                                  handle->handle,
-                                  uv_tty_post_raw_read,
-                                  (void*) req,
-                                  INFINITE,
-                                  WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
-  if (!r) {
-    handle->tty.rd.read_raw_wait = NULL;
-    SET_REQ_ERROR(req, GetLastError());
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-  }
-
-  handle->flags |= UV_HANDLE_READ_PENDING;
-  handle->reqs_pending++;
-}
-
-
-static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
-  uv_loop_t* loop;
-  uv_tty_t* handle;
-  uv_req_t* req;
-  DWORD bytes, read_bytes;
-  WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3];
-  DWORD chars, read_chars;
-  LONG status;
-  COORD pos;
-  BOOL read_console_success;
-
-  assert(data);
-
-  req = (uv_req_t*) data;
-  handle = (uv_tty_t*) req->data;
-  loop = handle->loop;
-
-  assert(handle->tty.rd.read_line_buffer.base != NULL);
-  assert(handle->tty.rd.read_line_buffer.len > 0);
-
-  /* ReadConsole can't handle big buffers. */
-  if (handle->tty.rd.read_line_buffer.len < MAX_INPUT_BUFFER_LENGTH) {
-    bytes = handle->tty.rd.read_line_buffer.len;
-  } else {
-    bytes = MAX_INPUT_BUFFER_LENGTH;
-  }
-
-  /* At last, unicode! One utf-16 codeunit never takes more than 3 utf-8
-   * codeunits to encode. */
-  chars = bytes / 3;
-
-  status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS);
-  if (status == TRAP_REQUESTED) {
-    SET_REQ_SUCCESS(req);
-    req->u.io.overlapped.InternalHigh = 0;
-    POST_COMPLETION_FOR_REQ(loop, req);
-    return 0;
-  }
-
-  read_console_success = ReadConsoleW(handle->handle,
-                                      (void*) utf16,
-                                      chars,
-                                      &read_chars,
-                                      NULL);
-
-  if (read_console_success) {
-    read_bytes = WideCharToMultiByte(CP_UTF8,
-                                     0,
-                                     utf16,
-                                     read_chars,
-                                     handle->tty.rd.read_line_buffer.base,
-                                     bytes,
-                                     NULL,
-                                     NULL);
-    SET_REQ_SUCCESS(req);
-    req->u.io.overlapped.InternalHigh = read_bytes;
-  } else {
-    SET_REQ_ERROR(req, GetLastError());
-  }
-
-  status = InterlockedExchange(&uv__read_console_status, COMPLETED);
-
-  if (status ==  TRAP_REQUESTED) {
-    /* If we canceled the read by sending a VK_RETURN event, restore the
-       screen state to undo the visual effect of the VK_RETURN */
-    if (read_console_success && InterlockedOr(&uv__restore_screen_state, 0)) {
-      HANDLE active_screen_buffer;
-      active_screen_buffer = CreateFileA("conout$",
-                                         GENERIC_READ | GENERIC_WRITE,
-                                         FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                         NULL,
-                                         OPEN_EXISTING,
-                                         FILE_ATTRIBUTE_NORMAL,
-                                         NULL);
-      if (active_screen_buffer != INVALID_HANDLE_VALUE) {
-        pos = uv__saved_screen_state.dwCursorPosition;
-
-        /* If the cursor was at the bottom line of the screen buffer, the
-           VK_RETURN would have caused the buffer contents to scroll up by one
-           line. The right position to reset the cursor to is therefore one line
-           higher */
-        if (pos.Y == uv__saved_screen_state.dwSize.Y - 1)
-          pos.Y--;
-
-        SetConsoleCursorPosition(active_screen_buffer, pos);
-        CloseHandle(active_screen_buffer);
-      }
-    }
-    uv_sem_post(&uv_tty_output_lock);
-  }
-  POST_COMPLETION_FOR_REQ(loop, req);
-  return 0;
-}
-
-
-static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
-  uv_read_t* req;
-  BOOL r;
-
-  assert(handle->flags & UV_HANDLE_READING);
-  assert(!(handle->flags & UV_HANDLE_READ_PENDING));
-  assert(handle->handle && handle->handle != INVALID_HANDLE_VALUE);
-
-  req = &handle->read_req;
-  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-
-  handle->tty.rd.read_line_buffer = uv_buf_init(NULL, 0);
-  handle->alloc_cb((uv_handle_t*) handle, 8192, &handle->tty.rd.read_line_buffer);
-  if (handle->tty.rd.read_line_buffer.base == NULL ||
-      handle->tty.rd.read_line_buffer.len == 0) {
-    handle->read_cb((uv_stream_t*) handle,
-                    UV_ENOBUFS,
-                    &handle->tty.rd.read_line_buffer);
-    return;
-  }
-  assert(handle->tty.rd.read_line_buffer.base != NULL);
-
-  /* Reset flags  No locking is required since there cannot be a line read
-     in progress. We are also relying on the memory barrier provided by
-     QueueUserWorkItem*/
-  uv__restore_screen_state = FALSE;
-  uv__read_console_status = NOT_STARTED;
-  r = QueueUserWorkItem(uv_tty_line_read_thread,
-                        (void*) req,
-                        WT_EXECUTELONGFUNCTION);
-  if (!r) {
-    SET_REQ_ERROR(req, GetLastError());
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-  }
-
-  handle->flags |= UV_HANDLE_READ_PENDING;
-  handle->reqs_pending++;
-}
-
-
-static void uv_tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) {
-  if (handle->flags & UV_HANDLE_TTY_RAW) {
-    uv_tty_queue_read_raw(loop, handle);
-  } else {
-    uv_tty_queue_read_line(loop, handle);
-  }
-}
-
-
-static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl,
-    size_t* len) {
-#define VK_CASE(vk, normal_str, shift_str, ctrl_str, shift_ctrl_str)          \
-    case (vk):                                                                \
-      if (shift && ctrl) {                                                    \
-        *len = sizeof shift_ctrl_str;                                         \
-        return "\033" shift_ctrl_str;                                         \
-      } else if (shift) {                                                     \
-        *len = sizeof shift_str ;                                             \
-        return "\033" shift_str;                                              \
-      } else if (ctrl) {                                                      \
-        *len = sizeof ctrl_str;                                               \
-        return "\033" ctrl_str;                                               \
-      } else {                                                                \
-        *len = sizeof normal_str;                                             \
-        return "\033" normal_str;                                             \
-      }
-
-  switch (code) {
-    /* These mappings are the same as Cygwin's. Unmodified and alt-modified
-     * keypad keys comply with linux console, modifiers comply with xterm
-     * modifier usage. F1. f12 and shift-f1. f10 comply with linux console, f6.
-     * f12 with and without modifiers comply with rxvt. */
-    VK_CASE(VK_INSERT,  "[2~",  "[2;2~", "[2;5~", "[2;6~")
-    VK_CASE(VK_END,     "[4~",  "[4;2~", "[4;5~", "[4;6~")
-    VK_CASE(VK_DOWN,    "[B",   "[1;2B", "[1;5B", "[1;6B")
-    VK_CASE(VK_NEXT,    "[6~",  "[6;2~", "[6;5~", "[6;6~")
-    VK_CASE(VK_LEFT,    "[D",   "[1;2D", "[1;5D", "[1;6D")
-    VK_CASE(VK_CLEAR,   "[G",   "[1;2G", "[1;5G", "[1;6G")
-    VK_CASE(VK_RIGHT,   "[C",   "[1;2C", "[1;5C", "[1;6C")
-    VK_CASE(VK_UP,      "[A",   "[1;2A", "[1;5A", "[1;6A")
-    VK_CASE(VK_HOME,    "[1~",  "[1;2~", "[1;5~", "[1;6~")
-    VK_CASE(VK_PRIOR,   "[5~",  "[5;2~", "[5;5~", "[5;6~")
-    VK_CASE(VK_DELETE,  "[3~",  "[3;2~", "[3;5~", "[3;6~")
-    VK_CASE(VK_NUMPAD0, "[2~",  "[2;2~", "[2;5~", "[2;6~")
-    VK_CASE(VK_NUMPAD1, "[4~",  "[4;2~", "[4;5~", "[4;6~")
-    VK_CASE(VK_NUMPAD2, "[B",   "[1;2B", "[1;5B", "[1;6B")
-    VK_CASE(VK_NUMPAD3, "[6~",  "[6;2~", "[6;5~", "[6;6~")
-    VK_CASE(VK_NUMPAD4, "[D",   "[1;2D", "[1;5D", "[1;6D")
-    VK_CASE(VK_NUMPAD5, "[G",   "[1;2G", "[1;5G", "[1;6G")
-    VK_CASE(VK_NUMPAD6, "[C",   "[1;2C", "[1;5C", "[1;6C")
-    VK_CASE(VK_NUMPAD7, "[A",   "[1;2A", "[1;5A", "[1;6A")
-    VK_CASE(VK_NUMPAD8, "[1~",  "[1;2~", "[1;5~", "[1;6~")
-    VK_CASE(VK_NUMPAD9, "[5~",  "[5;2~", "[5;5~", "[5;6~")
-    VK_CASE(VK_DECIMAL, "[3~",  "[3;2~", "[3;5~", "[3;6~")
-    VK_CASE(VK_F1,      "[[A",  "[23~",  "[11^",  "[23^" )
-    VK_CASE(VK_F2,      "[[B",  "[24~",  "[12^",  "[24^" )
-    VK_CASE(VK_F3,      "[[C",  "[25~",  "[13^",  "[25^" )
-    VK_CASE(VK_F4,      "[[D",  "[26~",  "[14^",  "[26^" )
-    VK_CASE(VK_F5,      "[[E",  "[28~",  "[15^",  "[28^" )
-    VK_CASE(VK_F6,      "[17~", "[29~",  "[17^",  "[29^" )
-    VK_CASE(VK_F7,      "[18~", "[31~",  "[18^",  "[31^" )
-    VK_CASE(VK_F8,      "[19~", "[32~",  "[19^",  "[32^" )
-    VK_CASE(VK_F9,      "[20~", "[33~",  "[20^",  "[33^" )
-    VK_CASE(VK_F10,     "[21~", "[34~",  "[21^",  "[34^" )
-    VK_CASE(VK_F11,     "[23~", "[23$",  "[23^",  "[23@" )
-    VK_CASE(VK_F12,     "[24~", "[24$",  "[24^",  "[24@" )
-
-    default:
-      *len = 0;
-      return NULL;
-  }
-#undef VK_CASE
-}
-
-
-void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_req_t* req) {
-  /* Shortcut for handle->tty.rd.last_input_record.Event.KeyEvent. */
-#define KEV handle->tty.rd.last_input_record.Event.KeyEvent
-
-  DWORD records_left, records_read;
-  uv_buf_t buf;
-  off_t buf_used;
-
-  assert(handle->type == UV_TTY);
-  assert(handle->flags & UV_HANDLE_TTY_READABLE);
-  handle->flags &= ~UV_HANDLE_READ_PENDING;
-
-  if (!(handle->flags & UV_HANDLE_READING) ||
-      !(handle->flags & UV_HANDLE_TTY_RAW)) {
-    goto out;
-  }
-
-  if (!REQ_SUCCESS(req)) {
-    /* An error occurred while waiting for the event. */
-    if ((handle->flags & UV_HANDLE_READING)) {
-      handle->flags &= ~UV_HANDLE_READING;
-      handle->read_cb((uv_stream_t*)handle,
-                      uv_translate_sys_error(GET_REQ_ERROR(req)),
-                      &uv_null_buf_);
-    }
-    goto out;
-  }
-
-  /* Fetch the number of events  */
-  if (!GetNumberOfConsoleInputEvents(handle->handle, &records_left)) {
-    handle->flags &= ~UV_HANDLE_READING;
-    DECREASE_ACTIVE_COUNT(loop, handle);
-    handle->read_cb((uv_stream_t*)handle,
-                    uv_translate_sys_error(GetLastError()),
-                    &uv_null_buf_);
-    goto out;
-  }
-
-  /* Windows sends a lot of events that we're not interested in, so buf will be
-   * allocated on demand, when there's actually something to emit. */
-  buf = uv_null_buf_;
-  buf_used = 0;
-
-  while ((records_left > 0 || handle->tty.rd.last_key_len > 0) &&
-         (handle->flags & UV_HANDLE_READING)) {
-    if (handle->tty.rd.last_key_len == 0) {
-      /* Read the next input record */
-      if (!ReadConsoleInputW(handle->handle,
-                             &handle->tty.rd.last_input_record,
-                             1,
-                             &records_read)) {
-        handle->flags &= ~UV_HANDLE_READING;
-        DECREASE_ACTIVE_COUNT(loop, handle);
-        handle->read_cb((uv_stream_t*) handle,
-                        uv_translate_sys_error(GetLastError()),
-                        &buf);
-        goto out;
-      }
-      records_left--;
-
-      /* Ignore other events that are not key events. */
-      if (handle->tty.rd.last_input_record.EventType != KEY_EVENT) {
-        continue;
-      }
-
-      /* Ignore keyup events, unless the left alt key was held and a valid
-       * unicode character was emitted. */
-      if (!KEV.bKeyDown &&
-          (KEV.wVirtualKeyCode != VK_MENU ||
-           KEV.uChar.UnicodeChar == 0)) {
-        continue;
-      }
-
-      /* Ignore keypresses to numpad number keys if the left alt is held
-       * because the user is composing a character, or windows simulating this.
-       */
-      if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) &&
-          !(KEV.dwControlKeyState & ENHANCED_KEY) &&
-          (KEV.wVirtualKeyCode == VK_INSERT ||
-          KEV.wVirtualKeyCode == VK_END ||
-          KEV.wVirtualKeyCode == VK_DOWN ||
-          KEV.wVirtualKeyCode == VK_NEXT ||
-          KEV.wVirtualKeyCode == VK_LEFT ||
-          KEV.wVirtualKeyCode == VK_CLEAR ||
-          KEV.wVirtualKeyCode == VK_RIGHT ||
-          KEV.wVirtualKeyCode == VK_HOME ||
-          KEV.wVirtualKeyCode == VK_UP ||
-          KEV.wVirtualKeyCode == VK_PRIOR ||
-          KEV.wVirtualKeyCode == VK_NUMPAD0 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD1 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD2 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD3 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD4 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD5 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD6 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD7 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD8 ||
-          KEV.wVirtualKeyCode == VK_NUMPAD9)) {
-        continue;
-      }
-
-      if (KEV.uChar.UnicodeChar != 0) {
-        int prefix_len, char_len;
-
-        /* Character key pressed */
-        if (KEV.uChar.UnicodeChar >= 0xD800 &&
-            KEV.uChar.UnicodeChar < 0xDC00) {
-          /* UTF-16 high surrogate */
-          handle->tty.rd.last_utf16_high_surrogate = KEV.uChar.UnicodeChar;
-          continue;
-        }
-
-        /* Prefix with \u033 if alt was held, but alt was not used as part a
-         * compose sequence. */
-        if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
-            && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED |
-            RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) {
-          handle->tty.rd.last_key[0] = '\033';
-          prefix_len = 1;
-        } else {
-          prefix_len = 0;
-        }
-
-        if (KEV.uChar.UnicodeChar >= 0xDC00 &&
-            KEV.uChar.UnicodeChar < 0xE000) {
-          /* UTF-16 surrogate pair */
-          WCHAR utf16_buffer[2];
-          utf16_buffer[0] = handle->tty.rd.last_utf16_high_surrogate;
-          utf16_buffer[1] = KEV.uChar.UnicodeChar;
-          char_len = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         utf16_buffer,
-                                         2,
-                                         &handle->tty.rd.last_key[prefix_len],
-                                         sizeof handle->tty.rd.last_key,
-                                         NULL,
-                                         NULL);
-        } else {
-          /* Single UTF-16 character */
-          char_len = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         &KEV.uChar.UnicodeChar,
-                                         1,
-                                         &handle->tty.rd.last_key[prefix_len],
-                                         sizeof handle->tty.rd.last_key,
-                                         NULL,
-                                         NULL);
-        }
-
-        /* Whatever happened, the last character wasn't a high surrogate. */
-        handle->tty.rd.last_utf16_high_surrogate = 0;
-
-        /* If the utf16 character(s) couldn't be converted something must be
-         * wrong. */
-        if (!char_len) {
-          handle->flags &= ~UV_HANDLE_READING;
-          DECREASE_ACTIVE_COUNT(loop, handle);
-          handle->read_cb((uv_stream_t*) handle,
-                          uv_translate_sys_error(GetLastError()),
-                          &buf);
-          goto out;
-        }
-
-        handle->tty.rd.last_key_len = (unsigned char) (prefix_len + char_len);
-        handle->tty.rd.last_key_offset = 0;
-        continue;
-
-      } else {
-        /* Function key pressed */
-        const char* vt100;
-        size_t prefix_len, vt100_len;
-
-        vt100 = get_vt100_fn_key(KEV.wVirtualKeyCode,
-                                  !!(KEV.dwControlKeyState & SHIFT_PRESSED),
-                                  !!(KEV.dwControlKeyState & (
-                                    LEFT_CTRL_PRESSED |
-                                    RIGHT_CTRL_PRESSED)),
-                                  &vt100_len);
-
-        /* If we were unable to map to a vt100 sequence, just ignore. */
-        if (!vt100) {
-          continue;
-        }
-
-        /* Prefix with \x033 when the alt key was held. */
-        if (KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
-          handle->tty.rd.last_key[0] = '\033';
-          prefix_len = 1;
-        } else {
-          prefix_len = 0;
-        }
-
-        /* Copy the vt100 sequence to the handle buffer. */
-        assert(prefix_len + vt100_len < sizeof handle->tty.rd.last_key);
-        memcpy(&handle->tty.rd.last_key[prefix_len], vt100, vt100_len);
-
-        handle->tty.rd.last_key_len = (unsigned char) (prefix_len + vt100_len);
-        handle->tty.rd.last_key_offset = 0;
-        continue;
-      }
-    } else {
-      /* Copy any bytes left from the last keypress to the user buffer. */
-      if (handle->tty.rd.last_key_offset < handle->tty.rd.last_key_len) {
-        /* Allocate a buffer if needed */
-        if (buf_used == 0) {
-          buf = uv_buf_init(NULL, 0);
-          handle->alloc_cb((uv_handle_t*) handle, 1024, &buf);
-          if (buf.base == NULL || buf.len == 0) {
-            handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf);
-            goto out;
-          }
-          assert(buf.base != NULL);
-        }
-
-        buf.base[buf_used++] = handle->tty.rd.last_key[handle->tty.rd.last_key_offset++];
-
-        /* If the buffer is full, emit it */
-        if ((size_t) buf_used == buf.len) {
-          handle->read_cb((uv_stream_t*) handle, buf_used, &buf);
-          buf = uv_null_buf_;
-          buf_used = 0;
-        }
-
-        continue;
-      }
-
-      /* Apply dwRepeat from the last input record. */
-      if (--KEV.wRepeatCount > 0) {
-        handle->tty.rd.last_key_offset = 0;
-        continue;
-      }
-
-      handle->tty.rd.last_key_len = 0;
-      continue;
-    }
-  }
-
-  /* Send the buffer back to the user */
-  if (buf_used > 0) {
-    handle->read_cb((uv_stream_t*) handle, buf_used, &buf);
-  }
-
- out:
-  /* Wait for more input events. */
-  if ((handle->flags & UV_HANDLE_READING) &&
-      !(handle->flags & UV_HANDLE_READ_PENDING)) {
-    uv_tty_queue_read(loop, handle);
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-
-#undef KEV
-}
-
-
-
-void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_req_t* req) {
-  uv_buf_t buf;
-
-  assert(handle->type == UV_TTY);
-  assert(handle->flags & UV_HANDLE_TTY_READABLE);
-
-  buf = handle->tty.rd.read_line_buffer;
-
-  handle->flags &= ~UV_HANDLE_READ_PENDING;
-  handle->tty.rd.read_line_buffer = uv_null_buf_;
-
-  if (!REQ_SUCCESS(req)) {
-    /* Read was not successful */
-    if (handle->flags & UV_HANDLE_READING) {
-      /* Real error */
-      handle->flags &= ~UV_HANDLE_READING;
-      DECREASE_ACTIVE_COUNT(loop, handle);
-      handle->read_cb((uv_stream_t*) handle,
-                      uv_translate_sys_error(GET_REQ_ERROR(req)),
-                      &buf);
-    }
-  } else {
-    if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING) &&
-        req->u.io.overlapped.InternalHigh != 0) {
-      /* Read successful. TODO: read unicode, convert to utf-8 */
-      DWORD bytes = req->u.io.overlapped.InternalHigh;
-      handle->read_cb((uv_stream_t*) handle, bytes, &buf);
-    }
-    handle->flags &= ~UV_HANDLE_CANCELLATION_PENDING;
-  }
-
-  /* Wait for more input events. */
-  if ((handle->flags & UV_HANDLE_READING) &&
-      !(handle->flags & UV_HANDLE_READ_PENDING)) {
-    uv_tty_queue_read(loop, handle);
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_req_t* req) {
-  assert(handle->type == UV_TTY);
-  assert(handle->flags & UV_HANDLE_TTY_READABLE);
-
-  /* If the read_line_buffer member is zero, it must have been an raw read.
-   * Otherwise it was a line-buffered read. FIXME: This is quite obscure. Use a
-   * flag or something. */
-  if (handle->tty.rd.read_line_buffer.len == 0) {
-    uv_process_tty_read_raw_req(loop, handle, req);
-  } else {
-    uv_process_tty_read_line_req(loop, handle, req);
-  }
-}
-
-
-int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
-    uv_read_cb read_cb) {
-  uv_loop_t* loop = handle->loop;
-
-  if (!(handle->flags & UV_HANDLE_TTY_READABLE)) {
-    return ERROR_INVALID_PARAMETER;
-  }
-
-  handle->flags |= UV_HANDLE_READING;
-  INCREASE_ACTIVE_COUNT(loop, handle);
-  handle->read_cb = read_cb;
-  handle->alloc_cb = alloc_cb;
-
-  /* If reading was stopped and then started again, there could still be a read
-   * request pending. */
-  if (handle->flags & UV_HANDLE_READ_PENDING) {
-    return 0;
-  }
-
-  /* Maybe the user stopped reading half-way while processing key events.
-   * Short-circuit if this could be the case. */
-  if (handle->tty.rd.last_key_len > 0) {
-    SET_REQ_SUCCESS(&handle->read_req);
-    uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
-    /* Make sure no attempt is made to insert it again until it's handled. */
-    handle->flags |= UV_HANDLE_READ_PENDING;
-    handle->reqs_pending++;
-    return 0;
-  }
-
-  uv_tty_queue_read(loop, handle);
-
-  return 0;
-}
-
-
-int uv_tty_read_stop(uv_tty_t* handle) {
-  INPUT_RECORD record;
-  DWORD written, err;
-
-  handle->flags &= ~UV_HANDLE_READING;
-  DECREASE_ACTIVE_COUNT(handle->loop, handle);
-
-  if (!(handle->flags & UV_HANDLE_READ_PENDING))
-    return 0;
-
-  if (handle->flags & UV_HANDLE_TTY_RAW) {
-    /* Cancel raw read. Write some bullshit event to force the console wait to
-     * return. */
-    memset(&record, 0, sizeof record);
-    record.EventType = FOCUS_EVENT;
-    if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) {
-      return GetLastError();
-    }
-  } else if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) {
-    /* Cancel line-buffered read if not already pending */
-    err = uv__cancel_read_console(handle);
-    if (err)
-      return err;
-
-    handle->flags |= UV_HANDLE_CANCELLATION_PENDING;
-  }
-
-  return 0;
-}
-
-static int uv__cancel_read_console(uv_tty_t* handle) {
-  HANDLE active_screen_buffer = INVALID_HANDLE_VALUE;
-  INPUT_RECORD record;
-  DWORD written;
-  DWORD err = 0;
-  LONG status;
-
-  assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING));
-
-  /* Hold the output lock during the cancellation, to ensure that further
-     writes don't interfere with the screen state. It will be the ReadConsole
-     thread's responsibility to release the lock. */
-  uv_sem_wait(&uv_tty_output_lock);
-  status = InterlockedExchange(&uv__read_console_status, TRAP_REQUESTED);
-  if (status != IN_PROGRESS) {
-    /* Either we have managed to set a trap for the other thread before
-       ReadConsole is called, or ReadConsole has returned because the user
-       has pressed ENTER. In either case, there is nothing else to do. */
-    uv_sem_post(&uv_tty_output_lock);
-    return 0;
-  }
-
-  /* Save screen state before sending the VK_RETURN event */
-  active_screen_buffer = CreateFileA("conout$",
-                                     GENERIC_READ | GENERIC_WRITE,
-                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                     NULL,
-                                     OPEN_EXISTING,
-                                     FILE_ATTRIBUTE_NORMAL,
-                                     NULL);
-
-  if (active_screen_buffer != INVALID_HANDLE_VALUE &&
-      GetConsoleScreenBufferInfo(active_screen_buffer,
-                                 &uv__saved_screen_state)) {
-    InterlockedOr(&uv__restore_screen_state, 1);
-  }
-
-  /* Write enter key event to force the console wait to return. */
-  record.EventType = KEY_EVENT;
-  record.Event.KeyEvent.bKeyDown = TRUE;
-  record.Event.KeyEvent.wRepeatCount = 1;
-  record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
-  record.Event.KeyEvent.wVirtualScanCode =
-    MapVirtualKeyW(VK_RETURN, MAPVK_VK_TO_VSC);
-  record.Event.KeyEvent.uChar.UnicodeChar = L'\r';
-  record.Event.KeyEvent.dwControlKeyState = 0;
-  if (!WriteConsoleInputW(handle->handle, &record, 1, &written))
-    err = GetLastError();
-
-  if (active_screen_buffer != INVALID_HANDLE_VALUE)
-    CloseHandle(active_screen_buffer);
-
-  return err;
-}
-
-
-static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
-  uv_tty_virtual_width = info->dwSize.X;
-  uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1;
-
-  /* Recompute virtual window offset row. */
-  if (uv_tty_virtual_offset == -1) {
-    uv_tty_virtual_offset = info->dwCursorPosition.Y;
-  } else if (uv_tty_virtual_offset < info->dwCursorPosition.Y -
-             uv_tty_virtual_height + 1) {
-    /* If suddenly find the cursor outside of the virtual window, it must have
-     * somehow scrolled. Update the virtual window offset. */
-    uv_tty_virtual_offset = info->dwCursorPosition.Y -
-                            uv_tty_virtual_height + 1;
-  }
-  if (uv_tty_virtual_offset + uv_tty_virtual_height > info->dwSize.Y) {
-    uv_tty_virtual_offset = info->dwSize.Y - uv_tty_virtual_height;
-  }
-  if (uv_tty_virtual_offset < 0) {
-    uv_tty_virtual_offset = 0;
-  }
-}
-
-
-static COORD uv_tty_make_real_coord(uv_tty_t* handle,
-    CONSOLE_SCREEN_BUFFER_INFO* info, int x, unsigned char x_relative, int y,
-    unsigned char y_relative) {
-  COORD result;
-
-  uv_tty_update_virtual_window(info);
-
-  /* Adjust y position */
-  if (y_relative) {
-    y = info->dwCursorPosition.Y + y;
-  } else {
-    y = uv_tty_virtual_offset + y;
-  }
-  /* Clip y to virtual client rectangle */
-  if (y < uv_tty_virtual_offset) {
-    y = uv_tty_virtual_offset;
-  } else if (y >= uv_tty_virtual_offset + uv_tty_virtual_height) {
-    y = uv_tty_virtual_offset + uv_tty_virtual_height - 1;
-  }
-
-  /* Adjust x */
-  if (x_relative) {
-    x = info->dwCursorPosition.X + x;
-  }
-  /* Clip x */
-  if (x < 0) {
-    x = 0;
-  } else if (x >= uv_tty_virtual_width) {
-    x = uv_tty_virtual_width - 1;
-  }
-
-  result.X = (unsigned short) x;
-  result.Y = (unsigned short) y;
-  return result;
-}
-
-
-static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length,
-    DWORD* error) {
-  DWORD written;
-
-  if (*error != ERROR_SUCCESS) {
-    return -1;
-  }
-
-  if (!WriteConsoleW(handle->handle,
-                     (void*) buffer,
-                     length,
-                     &written,
-                     NULL)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  return 0;
-}
-
-
-static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative,
-    int y, unsigned char y_relative, DWORD* error) {
-  CONSOLE_SCREEN_BUFFER_INFO info;
-  COORD pos;
-
-  if (*error != ERROR_SUCCESS) {
-    return -1;
-  }
-
- retry:
-  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
-    *error = GetLastError();
-  }
-
-  pos = uv_tty_make_real_coord(handle, &info, x, x_relative, y, y_relative);
-
-  if (!SetConsoleCursorPosition(handle->handle, pos)) {
-    if (GetLastError() == ERROR_INVALID_PARAMETER) {
-      /* The console may be resized - retry */
-      goto retry;
-    } else {
-      *error = GetLastError();
-      return -1;
-    }
-  }
-
-  return 0;
-}
-
-
-static int uv_tty_reset(uv_tty_t* handle, DWORD* error) {
-  const COORD origin = {0, 0};
-  const WORD char_attrs = uv_tty_default_text_attributes;
-  CONSOLE_SCREEN_BUFFER_INFO info;
-  DWORD count, written;
-
-  if (*error != ERROR_SUCCESS) {
-    return -1;
-  }
-
-  /* Reset original text attributes. */
-  if (!SetConsoleTextAttribute(handle->handle, char_attrs)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  /* Move the cursor position to (0, 0). */
-  if (!SetConsoleCursorPosition(handle->handle, origin)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  /* Clear the screen buffer. */
- retry:
-  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  count = info.dwSize.X * info.dwSize.Y;
-
-  if (!(FillConsoleOutputCharacterW(handle->handle,
-                                    L'\x20',
-                                    count,
-                                    origin,
-                                    &written) &&
-        FillConsoleOutputAttribute(handle->handle,
-                                   char_attrs,
-                                   written,
-                                   origin,
-                                   &written))) {
-    if (GetLastError() == ERROR_INVALID_PARAMETER) {
-      /* The console may be resized - retry */
-      goto retry;
-    } else {
-      *error = GetLastError();
-      return -1;
-    }
-  }
-
-  /* Move the virtual window up to the top. */
-  uv_tty_virtual_offset = 0;
-  uv_tty_update_virtual_window(&info);
-
-  return 0;
-}
-
-
-static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen,
-    DWORD* error) {
-  CONSOLE_SCREEN_BUFFER_INFO info;
-  COORD start, end;
-  DWORD count, written;
-
-  int x1, x2, y1, y2;
-  int x1r, x2r, y1r, y2r;
-
-  if (*error != ERROR_SUCCESS) {
-    return -1;
-  }
-
-  if (dir == 0) {
-    /* Clear from current position */
-    x1 = 0;
-    x1r = 1;
-  } else {
-    /* Clear from column 0 */
-    x1 = 0;
-    x1r = 0;
-  }
-
-  if (dir == 1) {
-    /* Clear to current position */
-    x2 = 0;
-    x2r = 1;
-  } else {
-    /* Clear to end of row. We pretend the console is 65536 characters wide,
-     * uv_tty_make_real_coord will clip it to the actual console width. */
-    x2 = 0xffff;
-    x2r = 0;
-  }
-
-  if (!entire_screen) {
-    /* Stay on our own row */
-    y1 = y2 = 0;
-    y1r = y2r = 1;
-  } else {
-    /* Apply columns direction to row */
-    y1 = x1;
-    y1r = x1r;
-    y2 = x2;
-    y2r = x2r;
-  }
-
- retry:
-  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  start = uv_tty_make_real_coord(handle, &info, x1, x1r, y1, y1r);
-  end = uv_tty_make_real_coord(handle, &info, x2, x2r, y2, y2r);
-  count = (end.Y * info.dwSize.X + end.X) -
-          (start.Y * info.dwSize.X + start.X) + 1;
-
-  if (!(FillConsoleOutputCharacterW(handle->handle,
-                              L'\x20',
-                              count,
-                              start,
-                              &written) &&
-        FillConsoleOutputAttribute(handle->handle,
-                                   info.wAttributes,
-                                   written,
-                                   start,
-                                   &written))) {
-    if (GetLastError() == ERROR_INVALID_PARAMETER) {
-      /* The console may be resized - retry */
-      goto retry;
-    } else {
-      *error = GetLastError();
-      return -1;
-    }
-  }
-
-  return 0;
-}
-
-#define FLIP_FGBG                                                             \
-    do {                                                                      \
-      WORD fg = info.wAttributes & 0xF;                                       \
-      WORD bg = info.wAttributes & 0xF0;                                      \
-      info.wAttributes &= 0xFF00;                                             \
-      info.wAttributes |= fg << 4;                                            \
-      info.wAttributes |= bg >> 4;                                            \
-    } while (0)
-
-static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) {
-  unsigned short argc = handle->tty.wr.ansi_csi_argc;
-  unsigned short* argv = handle->tty.wr.ansi_csi_argv;
-  int i;
-  CONSOLE_SCREEN_BUFFER_INFO info;
-
-  char fg_color = -1, bg_color = -1;
-  char fg_bright = -1, bg_bright = -1;
-  char inverse = -1;
-
-  if (argc == 0) {
-    /* Reset mode */
-    fg_color = uv_tty_default_fg_color;
-    bg_color = uv_tty_default_bg_color;
-    fg_bright = uv_tty_default_fg_bright;
-    bg_bright = uv_tty_default_bg_bright;
-    inverse = uv_tty_default_inverse;
-  }
-
-  for (i = 0; i < argc; i++) {
-    short arg = argv[i];
-
-    if (arg == 0) {
-      /* Reset mode */
-      fg_color = uv_tty_default_fg_color;
-      bg_color = uv_tty_default_bg_color;
-      fg_bright = uv_tty_default_fg_bright;
-      bg_bright = uv_tty_default_bg_bright;
-      inverse = uv_tty_default_inverse;
-
-    } else if (arg == 1) {
-      /* Foreground bright on */
-      fg_bright = 1;
-
-    } else if (arg == 2) {
-      /* Both bright off */
-      fg_bright = 0;
-      bg_bright = 0;
-
-    } else if (arg == 5) {
-      /* Background bright on */
-      bg_bright = 1;
-
-    } else if (arg == 7) {
-      /* Inverse: on */
-      inverse = 1;
-
-    } else if (arg == 21 || arg == 22) {
-      /* Foreground bright off */
-      fg_bright = 0;
-
-    } else if (arg == 25) {
-      /* Background bright off */
-      bg_bright = 0;
-
-    } else if (arg == 27) {
-      /* Inverse: off */
-      inverse = 0;
-
-    } else if (arg >= 30 && arg <= 37) {
-      /* Set foreground color */
-      fg_color = arg - 30;
-
-    } else if (arg == 39) {
-      /* Default text color */
-      fg_color = uv_tty_default_fg_color;
-      fg_bright = uv_tty_default_fg_bright;
-
-    } else if (arg >= 40 && arg <= 47) {
-      /* Set background color */
-      bg_color = arg - 40;
-
-    } else if (arg ==  49) {
-      /* Default background color */
-      bg_color = uv_tty_default_bg_color;
-      bg_bright = uv_tty_default_bg_bright;
-
-    } else if (arg >= 90 && arg <= 97) {
-      /* Set bold foreground color */
-      fg_bright = 1;
-      fg_color = arg - 90;
-
-    } else if (arg >= 100 && arg <= 107) {
-      /* Set bold background color */
-      bg_bright = 1;
-      bg_color = arg - 100;
-
-    }
-  }
-
-  if (fg_color == -1 && bg_color == -1 && fg_bright == -1 &&
-      bg_bright == -1 && inverse == -1) {
-    /* Nothing changed */
-    return 0;
-  }
-
-  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) {
-    FLIP_FGBG;
-  }
-
-  if (fg_color != -1) {
-    info.wAttributes &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
-    if (fg_color & 1) info.wAttributes |= FOREGROUND_RED;
-    if (fg_color & 2) info.wAttributes |= FOREGROUND_GREEN;
-    if (fg_color & 4) info.wAttributes |= FOREGROUND_BLUE;
-  }
-
-  if (fg_bright != -1) {
-    if (fg_bright) {
-      info.wAttributes |= FOREGROUND_INTENSITY;
-    } else {
-      info.wAttributes &= ~FOREGROUND_INTENSITY;
-    }
-  }
-
-  if (bg_color != -1) {
-    info.wAttributes &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
-    if (bg_color & 1) info.wAttributes |= BACKGROUND_RED;
-    if (bg_color & 2) info.wAttributes |= BACKGROUND_GREEN;
-    if (bg_color & 4) info.wAttributes |= BACKGROUND_BLUE;
-  }
-
-  if (bg_bright != -1) {
-    if (bg_bright) {
-      info.wAttributes |= BACKGROUND_INTENSITY;
-    } else {
-      info.wAttributes &= ~BACKGROUND_INTENSITY;
-    }
-  }
-
-  if (inverse != -1) {
-    if (inverse) {
-      info.wAttributes |= COMMON_LVB_REVERSE_VIDEO;
-    } else {
-      info.wAttributes &= ~COMMON_LVB_REVERSE_VIDEO;
-    }
-  }
-
-  if ((info.wAttributes & COMMON_LVB_REVERSE_VIDEO) > 0) {
-    FLIP_FGBG;
-  }
-
-  if (!SetConsoleTextAttribute(handle->handle, info.wAttributes)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  return 0;
-}
-
-
-static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes,
-    DWORD* error) {
-  CONSOLE_SCREEN_BUFFER_INFO info;
-
-  if (*error != ERROR_SUCCESS) {
-    return -1;
-  }
-
-  if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  uv_tty_update_virtual_window(&info);
-
-  handle->tty.wr.saved_position.X = info.dwCursorPosition.X;
-  handle->tty.wr.saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset;
-  handle->flags |= UV_HANDLE_TTY_SAVED_POSITION;
-
-  if (save_attributes) {
-    handle->tty.wr.saved_attributes = info.wAttributes &
-        (FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
-    handle->flags |= UV_HANDLE_TTY_SAVED_ATTRIBUTES;
-  }
-
-  return 0;
-}
-
-
-static int uv_tty_restore_state(uv_tty_t* handle,
-    unsigned char restore_attributes, DWORD* error) {
-  CONSOLE_SCREEN_BUFFER_INFO info;
-  WORD new_attributes;
-
-  if (*error != ERROR_SUCCESS) {
-    return -1;
-  }
-
-  if (handle->flags & UV_HANDLE_TTY_SAVED_POSITION) {
-    if (uv_tty_move_caret(handle,
-                          handle->tty.wr.saved_position.X,
-                          0,
-                          handle->tty.wr.saved_position.Y,
-                          0,
-                          error) != 0) {
-      return -1;
-    }
-  }
-
-  if (restore_attributes &&
-      (handle->flags & UV_HANDLE_TTY_SAVED_ATTRIBUTES)) {
-    if (!GetConsoleScreenBufferInfo(handle->handle, &info)) {
-      *error = GetLastError();
-      return -1;
-    }
-
-    new_attributes = info.wAttributes;
-    new_attributes &= ~(FOREGROUND_INTENSITY | BACKGROUND_INTENSITY);
-    new_attributes |= handle->tty.wr.saved_attributes;
-
-    if (!SetConsoleTextAttribute(handle->handle, new_attributes)) {
-      *error = GetLastError();
-      return -1;
-    }
-  }
-
-  return 0;
-}
-
-static int uv_tty_set_cursor_visibility(uv_tty_t* handle,
-                                        BOOL visible,
-                                        DWORD* error) {
-  CONSOLE_CURSOR_INFO cursor_info;
-
-  if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  cursor_info.bVisible = visible;
-
-  if (!SetConsoleCursorInfo(handle->handle, &cursor_info)) {
-    *error = GetLastError();
-    return -1;
-  }
-
-  return 0;
-}
-
-static int uv_tty_write_bufs(uv_tty_t* handle,
-                             const uv_buf_t bufs[],
-                             unsigned int nbufs,
-                             DWORD* error) {
-  /* We can only write 8k characters at a time. Windows can't handle much more
-   * characters in a single console write anyway. */
-  WCHAR utf16_buf[MAX_CONSOLE_CHAR];
-  WCHAR* utf16_buffer;
-  DWORD utf16_buf_used = 0;
-  unsigned int i, len, max_len, pos;
-  int allocate = 0;
-
-#define FLUSH_TEXT()                                                 \
-  do {                                                               \
-    pos = 0;                                                         \
-    do {                                                             \
-      len = utf16_buf_used - pos;                                    \
-      if (len > MAX_CONSOLE_CHAR)                                    \
-        len = MAX_CONSOLE_CHAR;                                      \
-      uv_tty_emit_text(handle, &utf16_buffer[pos], len, error);      \
-      pos += len;                                                    \
-    } while (pos < utf16_buf_used);                                  \
-    if (allocate) {                                                  \
-      uv__free(utf16_buffer);                                        \
-      allocate = 0;                                                  \
-      utf16_buffer = utf16_buf;                                      \
-    }                                                                \
-    utf16_buf_used = 0;                                              \
- } while (0)
-
-#define ENSURE_BUFFER_SPACE(wchars_needed)                          \
-  if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) {     \
-    FLUSH_TEXT();                                                   \
-  }
-
-  /* Cache for fast access */
-  unsigned char utf8_bytes_left = handle->tty.wr.utf8_bytes_left;
-  unsigned int utf8_codepoint = handle->tty.wr.utf8_codepoint;
-  unsigned char previous_eol = handle->tty.wr.previous_eol;
-  unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state;
-
-  /* Store the error here. If we encounter an error, stop trying to do i/o but
-   * keep parsing the buffer so we leave the parser in a consistent state. */
-  *error = ERROR_SUCCESS;
-
-  utf16_buffer = utf16_buf;
-
-  uv_sem_wait(&uv_tty_output_lock);
-
-  for (i = 0; i < nbufs; i++) {
-    uv_buf_t buf = bufs[i];
-    unsigned int j;
-
-    if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) {
-      utf16_buf_used = MultiByteToWideChar(CP_UTF8,
-                                           0,
-                                           buf.base,
-                                           buf.len,
-                                           NULL,
-                                           0);
-
-      if (utf16_buf_used == 0) {
-        *error = GetLastError();
-        break;
-      }
-
-      max_len = (utf16_buf_used + 1) * sizeof(WCHAR);
-      allocate = max_len > MAX_CONSOLE_CHAR;
-      if (allocate)
-        utf16_buffer = (WCHAR*)uv__malloc(max_len);
-      if (!MultiByteToWideChar(CP_UTF8,
-                               0,
-                               buf.base,
-                               buf.len,
-                               utf16_buffer,
-                               utf16_buf_used)) {
-        if (allocate)
-          uv__free(utf16_buffer);
-        *error = GetLastError();
-        break;
-      }
-
-      FLUSH_TEXT();
-
-      continue;
-    }
-
-    for (j = 0; j < buf.len; j++) {
-      unsigned char c = buf.base[j];
-
-      /* Run the character through the utf8 decoder We happily accept non
-       * shortest form encodings and invalid code points - there's no real harm
-       * that can be done. */
-      if (utf8_bytes_left == 0) {
-        /* Read utf-8 start byte */
-        DWORD first_zero_bit;
-        unsigned char not_c = ~c;
-#ifdef _MSC_VER /* msvc */
-        if (_BitScanReverse(&first_zero_bit, not_c)) {
-#else /* assume gcc */
-        if (c != 0) {
-          first_zero_bit = (sizeof(int) * 8) - 1 - __builtin_clz(not_c);
-#endif
-          if (first_zero_bit == 7) {
-            /* Ascii - pass right through */
-            utf8_codepoint = (unsigned int) c;
-
-          } else if (first_zero_bit <= 5) {
-            /* Multibyte sequence */
-            utf8_codepoint = (0xff >> (8 - first_zero_bit)) & c;
-            utf8_bytes_left = (char) (6 - first_zero_bit);
-
-          } else {
-            /* Invalid continuation */
-            utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
-          }
-
-        } else {
-          /* 0xff -- invalid */
-          utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
-        }
-
-      } else if ((c & 0xc0) == 0x80) {
-        /* Valid continuation of utf-8 multibyte sequence */
-        utf8_bytes_left--;
-        utf8_codepoint <<= 6;
-        utf8_codepoint |= ((unsigned int) c & 0x3f);
-
-      } else {
-        /* Start byte where continuation was expected. */
-        utf8_bytes_left = 0;
-        utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
-        /* Patch buf offset so this character will be parsed again as a start
-         * byte. */
-        j--;
-      }
-
-      /* Maybe we need to parse more bytes to find a character. */
-      if (utf8_bytes_left != 0) {
-        continue;
-      }
-
-      /* Parse vt100/ansi escape codes */
-      if (ansi_parser_state == ANSI_NORMAL) {
-        switch (utf8_codepoint) {
-          case '\033':
-            ansi_parser_state = ANSI_ESCAPE_SEEN;
-            continue;
-
-          case 0233:
-            ansi_parser_state = ANSI_CSI;
-            handle->tty.wr.ansi_csi_argc = 0;
-            continue;
-        }
-
-      } else if (ansi_parser_state == ANSI_ESCAPE_SEEN) {
-        switch (utf8_codepoint) {
-          case '[':
-            ansi_parser_state = ANSI_CSI;
-            handle->tty.wr.ansi_csi_argc = 0;
-            continue;
-
-          case '^':
-          case '_':
-          case 'P':
-          case ']':
-            /* Not supported, but we'll have to parse until we see a stop code,
-             * e. g. ESC \ or BEL. */
-            ansi_parser_state = ANSI_ST_CONTROL;
-            continue;
-
-          case '\033':
-            /* Ignore double escape. */
-            continue;
-
-          case 'c':
-            /* Full console reset. */
-            FLUSH_TEXT();
-            uv_tty_reset(handle, error);
-            ansi_parser_state = ANSI_NORMAL;
-            continue;
-
-          case '7':
-            /* Save the cursor position and text attributes. */
-            FLUSH_TEXT();
-            uv_tty_save_state(handle, 1, error);
-            ansi_parser_state = ANSI_NORMAL;
-            continue;
-
-           case '8':
-            /* Restore the cursor position and text attributes */
-            FLUSH_TEXT();
-            uv_tty_restore_state(handle, 1, error);
-            ansi_parser_state = ANSI_NORMAL;
-            continue;
-
-          default:
-            if (utf8_codepoint >= '@' && utf8_codepoint <= '_') {
-              /* Single-char control. */
-              ansi_parser_state = ANSI_NORMAL;
-              continue;
-            } else {
-              /* Invalid - proceed as normal, */
-              ansi_parser_state = ANSI_NORMAL;
-            }
-        }
-
-      } else if (ansi_parser_state & ANSI_CSI) {
-        if (!(ansi_parser_state & ANSI_IGNORE)) {
-          if (utf8_codepoint >= '0' && utf8_codepoint <= '9') {
-            /* Parsing a numerical argument */
-
-            if (!(ansi_parser_state & ANSI_IN_ARG)) {
-              /* We were not currently parsing a number */
-
-              /* Check for too many arguments */
-              if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {
-                ansi_parser_state |= ANSI_IGNORE;
-                continue;
-              }
-
-              ansi_parser_state |= ANSI_IN_ARG;
-              handle->tty.wr.ansi_csi_argc++;
-              handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] =
-                  (unsigned short) utf8_codepoint - '0';
-              continue;
-            } else {
-              /* We were already parsing a number. Parse next digit. */
-              uint32_t value = 10 *
-                  handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1];
-
-              /* Check for overflow. */
-              if (value > UINT16_MAX) {
-                ansi_parser_state |= ANSI_IGNORE;
-                continue;
-              }
-
-               handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] =
-                   (unsigned short) value + (utf8_codepoint - '0');
-               continue;
-            }
-
-          } else if (utf8_codepoint == ';') {
-            /* Denotes the end of an argument. */
-            if (ansi_parser_state & ANSI_IN_ARG) {
-              ansi_parser_state &= ~ANSI_IN_ARG;
-              continue;
-
-            } else {
-              /* If ANSI_IN_ARG is not set, add another argument and default it
-               * to 0. */
-
-              /* Check for too many arguments */
-              if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) {
-                ansi_parser_state |= ANSI_IGNORE;
-                continue;
-              }
-
-              handle->tty.wr.ansi_csi_argc++;
-              handle->tty.wr.ansi_csi_argv[handle->tty.wr.ansi_csi_argc - 1] = 0;
-              continue;
-            }
-
-          } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) &&
-                     handle->tty.wr.ansi_csi_argc == 0) {
-            /* Ignores '?' if it is the first character after CSI[. This is an
-             * extension character from the VT100 codeset that is supported and
-             * used by most ANSI terminals today. */
-            continue;
-
-          } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' &&
-                     (handle->tty.wr.ansi_csi_argc > 0 || utf8_codepoint != '[')) {
-            int x, y, d;
-
-            /* Command byte */
-            switch (utf8_codepoint) {
-              case 'A':
-                /* cursor up */
-                FLUSH_TEXT();
-                y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);
-                uv_tty_move_caret(handle, 0, 1, y, 1, error);
-                break;
-
-              case 'B':
-                /* cursor down */
-                FLUSH_TEXT();
-                y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;
-                uv_tty_move_caret(handle, 0, 1, y, 1, error);
-                break;
-
-              case 'C':
-                /* cursor forward */
-                FLUSH_TEXT();
-                x = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;
-                uv_tty_move_caret(handle, x, 1, 0, 1, error);
-                break;
-
-              case 'D':
-                /* cursor back */
-                FLUSH_TEXT();
-                x = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);
-                uv_tty_move_caret(handle, x, 1, 0, 1, error);
-                break;
-
-              case 'E':
-                /* cursor next line */
-                FLUSH_TEXT();
-                y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1;
-                uv_tty_move_caret(handle, 0, 0, y, 1, error);
-                break;
-
-              case 'F':
-                /* cursor previous line */
-                FLUSH_TEXT();
-                y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1);
-                uv_tty_move_caret(handle, 0, 0, y, 1, error);
-                break;
-
-              case 'G':
-                /* cursor horizontal move absolute */
-                FLUSH_TEXT();
-                x = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0])
-                  ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0;
-                uv_tty_move_caret(handle, x, 0, 0, 1, error);
-                break;
-
-              case 'H':
-              case 'f':
-                /* cursor move absolute */
-                FLUSH_TEXT();
-                y = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0])
-                  ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0;
-                x = (handle->tty.wr.ansi_csi_argc >= 2 && handle->tty.wr.ansi_csi_argv[1])
-                  ? handle->tty.wr.ansi_csi_argv[1] - 1 : 0;
-                uv_tty_move_caret(handle, x, 0, y, 0, error);
-                break;
-
-              case 'J':
-                /* Erase screen */
-                FLUSH_TEXT();
-                d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0;
-                if (d >= 0 && d <= 2) {
-                  uv_tty_clear(handle, d, 1, error);
-                }
-                break;
-
-              case 'K':
-                /* Erase line */
-                FLUSH_TEXT();
-                d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0;
-                if (d >= 0 && d <= 2) {
-                  uv_tty_clear(handle, d, 0, error);
-                }
-                break;
-
-              case 'm':
-                /* Set style */
-                FLUSH_TEXT();
-                uv_tty_set_style(handle, error);
-                break;
-
-              case 's':
-                /* Save the cursor position. */
-                FLUSH_TEXT();
-                uv_tty_save_state(handle, 0, error);
-                break;
-
-              case 'u':
-                /* Restore the cursor position */
-                FLUSH_TEXT();
-                uv_tty_restore_state(handle, 0, error);
-                break;
-
-              case 'l':
-                /* Hide the cursor */
-                if (handle->tty.wr.ansi_csi_argc == 1 &&
-                    handle->tty.wr.ansi_csi_argv[0] == 25) {
-                  FLUSH_TEXT();
-                  uv_tty_set_cursor_visibility(handle, 0, error);
-                }
-                break;
-
-              case 'h':
-                /* Show the cursor */
-                if (handle->tty.wr.ansi_csi_argc == 1 &&
-                    handle->tty.wr.ansi_csi_argv[0] == 25) {
-                  FLUSH_TEXT();
-                  uv_tty_set_cursor_visibility(handle, 1, error);
-                }
-                break;
-            }
-
-            /* Sequence ended - go back to normal state. */
-            ansi_parser_state = ANSI_NORMAL;
-            continue;
-
-          } else {
-            /* We don't support commands that use private mode characters or
-             * intermediaries. Ignore the rest of the sequence. */
-            ansi_parser_state |= ANSI_IGNORE;
-            continue;
-          }
-        } else {
-          /* We're ignoring this command. Stop only on command character. */
-          if (utf8_codepoint >= '@' && utf8_codepoint <= '~') {
-            ansi_parser_state = ANSI_NORMAL;
-          }
-          continue;
-        }
-
-      } else if (ansi_parser_state & ANSI_ST_CONTROL) {
-        /* Unsupported control code.
-         * Ignore everything until we see `BEL` or `ESC \`. */
-        if (ansi_parser_state & ANSI_IN_STRING) {
-          if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) {
-            if (utf8_codepoint == '"') {
-              ansi_parser_state &= ~ANSI_IN_STRING;
-            } else if (utf8_codepoint == '\\') {
-              ansi_parser_state |= ANSI_BACKSLASH_SEEN;
-            }
-          } else {
-            ansi_parser_state &= ~ANSI_BACKSLASH_SEEN;
-          }
-        } else {
-          if (utf8_codepoint == '\007' || (utf8_codepoint == '\\' &&
-              (ansi_parser_state & ANSI_ESCAPE_SEEN))) {
-            /* End of sequence */
-            ansi_parser_state = ANSI_NORMAL;
-          } else if (utf8_codepoint == '\033') {
-            /* Escape character */
-            ansi_parser_state |= ANSI_ESCAPE_SEEN;
-          } else if (utf8_codepoint == '"') {
-             /* String starting */
-            ansi_parser_state |= ANSI_IN_STRING;
-            ansi_parser_state &= ~ANSI_ESCAPE_SEEN;
-            ansi_parser_state &= ~ANSI_BACKSLASH_SEEN;
-          } else {
-            ansi_parser_state &= ~ANSI_ESCAPE_SEEN;
-          }
-        }
-        continue;
-      } else {
-        /* Inconsistent state */
-        abort();
-      }
-
-      /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the windows
-       * console doesn't really support UTF-16, so just emit the replacement
-       * character. */
-      if (utf8_codepoint > 0xffff) {
-        utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER;
-      }
-
-      if (utf8_codepoint == 0x0a || utf8_codepoint == 0x0d) {
-        /* EOL conversion - emit \r\n when we see \n. */
-
-        if (utf8_codepoint == 0x0a && previous_eol != 0x0d) {
-          /* \n was not preceded by \r; print \r\n. */
-          ENSURE_BUFFER_SPACE(2);
-          utf16_buf[utf16_buf_used++] = L'\r';
-          utf16_buf[utf16_buf_used++] = L'\n';
-        } else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) {
-          /* \n was followed by \r; do not print the \r, since the source was
-           * either \r\n\r (so the second \r is redundant) or was \n\r (so the
-           * \n was processed by the last case and an \r automatically
-           * inserted). */
-        } else {
-          /* \r without \n; print \r as-is. */
-          ENSURE_BUFFER_SPACE(1);
-          utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint;
-        }
-
-        previous_eol = (char) utf8_codepoint;
-
-      } else if (utf8_codepoint <= 0xffff) {
-        /* Encode character into utf-16 buffer. */
-        ENSURE_BUFFER_SPACE(1);
-        utf16_buf[utf16_buf_used++] = (WCHAR) utf8_codepoint;
-        previous_eol = 0;
-      }
-    }
-  }
-
-  /* Flush remaining characters */
-  FLUSH_TEXT();
-
-  /* Copy cached values back to struct. */
-  handle->tty.wr.utf8_bytes_left = utf8_bytes_left;
-  handle->tty.wr.utf8_codepoint = utf8_codepoint;
-  handle->tty.wr.previous_eol = previous_eol;
-  handle->tty.wr.ansi_parser_state = ansi_parser_state;
-
-  uv_sem_post(&uv_tty_output_lock);
-
-  if (*error == STATUS_SUCCESS) {
-    return 0;
-  } else {
-    return -1;
-  }
-
-#undef FLUSH_TEXT
-}
-
-
-int uv_tty_write(uv_loop_t* loop,
-                 uv_write_t* req,
-                 uv_tty_t* handle,
-                 const uv_buf_t bufs[],
-                 unsigned int nbufs,
-                 uv_write_cb cb) {
-  DWORD error;
-
-  UV_REQ_INIT(req, UV_WRITE);
-  req->handle = (uv_stream_t*) handle;
-  req->cb = cb;
-
-  handle->reqs_pending++;
-  handle->stream.conn.write_reqs_pending++;
-  REGISTER_HANDLE_REQ(loop, handle, req);
-
-  req->u.io.queued_bytes = 0;
-
-  if (!uv_tty_write_bufs(handle, bufs, nbufs, &error)) {
-    SET_REQ_SUCCESS(req);
-  } else {
-    SET_REQ_ERROR(req, error);
-  }
-
-  uv_insert_pending_req(loop, (uv_req_t*) req);
-
-  return 0;
-}
-
-
-int uv__tty_try_write(uv_tty_t* handle,
-                      const uv_buf_t bufs[],
-                      unsigned int nbufs) {
-  DWORD error;
-
-  if (handle->stream.conn.write_reqs_pending > 0)
-    return UV_EAGAIN;
-
-  if (uv_tty_write_bufs(handle, bufs, nbufs, &error))
-    return uv_translate_sys_error(error);
-
-  return uv__count_bufs(bufs, nbufs);
-}
-
-
-void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
-  uv_write_t* req) {
-  int err;
-
-  handle->write_queue_size -= req->u.io.queued_bytes;
-  UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-  if (req->cb) {
-    err = GET_REQ_ERROR(req);
-    req->cb(req, uv_translate_sys_error(err));
-  }
-
-  handle->stream.conn.write_reqs_pending--;
-  if (handle->stream.conn.shutdown_req != NULL &&
-      handle->stream.conn.write_reqs_pending == 0) {
-    uv_want_endgame(loop, (uv_handle_t*)handle);
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_tty_close(uv_tty_t* handle) {
-  assert(handle->u.fd == -1 || handle->u.fd > 2);
-  if (handle->flags & UV_HANDLE_READING)
-    uv_tty_read_stop(handle);
-
-  if (handle->u.fd == -1)
-    CloseHandle(handle->handle);
-  else
-    close(handle->u.fd);
-
-  handle->u.fd = -1;
-  handle->handle = INVALID_HANDLE_VALUE;
-  handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
-  uv__handle_closing(handle);
-
-  if (handle->reqs_pending == 0) {
-    uv_want_endgame(handle->loop, (uv_handle_t*) handle);
-  }
-}
-
-
-void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
-  if (!(handle->flags & UV_HANDLE_TTY_READABLE) &&
-      handle->stream.conn.shutdown_req != NULL &&
-      handle->stream.conn.write_reqs_pending == 0) {
-    UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req);
-
-    /* TTY shutdown is really just a no-op */
-    if (handle->stream.conn.shutdown_req->cb) {
-      if (handle->flags & UV_HANDLE_CLOSING) {
-        handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED);
-      } else {
-        handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0);
-      }
-    }
-
-    handle->stream.conn.shutdown_req = NULL;
-
-    DECREASE_PENDING_REQ_COUNT(handle);
-    return;
-  }
-
-  if (handle->flags & UV_HANDLE_CLOSING &&
-      handle->reqs_pending == 0) {
-    /* The wait handle used for raw reading should be unregistered when the
-     * wait callback runs. */
-    assert(!(handle->flags & UV_HANDLE_TTY_READABLE) ||
-           handle->tty.rd.read_raw_wait == NULL);
-
-    assert(!(handle->flags & UV_HANDLE_CLOSED));
-    uv__handle_close(handle);
-  }
-}
-
-
-/*
- * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
- * TODO: find a way to remove it
- */
-void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_req_t* raw_req) {
-  abort();
-}
-
-
-/*
- * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
- * TODO: find a way to remove it
- */
-void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
-    uv_connect_t* req) {
-  abort();
-}
-
-
-int uv_tty_reset_mode(void) {
-  /* Not necessary to do anything. */
-  return 0;
-}
-
-/* Determine whether or not this version of windows supports
- * proper ANSI color codes. Should be supported as of windows
- * 10 version 1511, build number 10.0.10586.
- */
-static void uv__determine_vterm_state(HANDLE handle) {
-  DWORD dwMode = 0;
-
-  if (!GetConsoleMode(handle, &dwMode)) {
-    uv__vterm_state = UV_UNSUPPORTED;
-    return;
-  }
-
-  dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
-  if (!SetConsoleMode(handle, dwMode)) {
-    uv__vterm_state = UV_UNSUPPORTED;
-    return;
-  }
-
-  uv__vterm_state = UV_SUPPORTED;
-}
-
-static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) {
-  CONSOLE_SCREEN_BUFFER_INFO sb_info;
-  MSG msg;
-
-  if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
-    return 0;
-
-  uv__tty_console_width = sb_info.dwSize.X;
-  uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
-
-  if (pSetWinEventHook == NULL)
-    return 0;
-
-  if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT,
-                        EVENT_CONSOLE_LAYOUT,
-                        NULL,
-                        uv__tty_console_resize_event,
-                        0,
-                        0,
-                        WINEVENT_OUTOFCONTEXT))
-    return 0;
-
-  while (GetMessage(&msg, NULL, 0, 0)) {
-    TranslateMessage(&msg);
-    DispatchMessage(&msg);
-  }
-  return 0;
-}
-
-static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook,
-                                                  DWORD event,
-                                                  HWND hwnd,
-                                                  LONG idObject,
-                                                  LONG idChild,
-                                                  DWORD dwEventThread,
-                                                  DWORD dwmsEventTime) {
-  CONSOLE_SCREEN_BUFFER_INFO sb_info;
-  int width, height;
-
-  if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
-    return;
-
-  width = sb_info.dwSize.X;
-  height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
-
-  if (width != uv__tty_console_width || height != uv__tty_console_height) {
-    uv__tty_console_width = width;
-    uv__tty_console_height = height;
-    uv__signal_dispatch(SIGWINCH);
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/udp.cpp b/wpiutil/src/main/native/libuv/src/win/udp.cpp
deleted file mode 100644
index 8aeeab3..0000000
--- a/wpiutil/src/main/native/libuv/src/win/udp.cpp
+++ /dev/null
@@ -1,1035 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "uv.h"
-#include "internal.h"
-#include "handle-inl.h"
-#include "stream-inl.h"
-#include "req-inl.h"
-
-
-/*
- * Threshold of active udp streams for which to preallocate udp read buffers.
- */
-const unsigned int uv_active_udp_streams_threshold = 0;
-
-/* A zero-size buffer for use by uv_udp_read */
-static char uv_zero_[] = "";
-int uv_udp_getpeername(const uv_udp_t* handle,
-                       struct sockaddr* name,
-                       int* namelen) {
-
-  return uv__getsockpeername((const uv_handle_t*) handle,
-                             getpeername,
-                             name,
-                             namelen,
-                             0);
-}
-
-
-int uv_udp_getsockname(const uv_udp_t* handle,
-                       struct sockaddr* name,
-                       int* namelen) {
-
-  return uv__getsockpeername((const uv_handle_t*) handle,
-                             getsockname,
-                             name,
-                             namelen,
-                             0);
-}
-
-
-static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket,
-    int family) {
-  DWORD yes = 1;
-  WSAPROTOCOL_INFOW info;
-  int opt_len;
-
-  if (handle->socket != INVALID_SOCKET)
-    return UV_EBUSY;
-
-  /* Set the socket to nonblocking mode */
-  if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
-    return WSAGetLastError();
-  }
-
-  /* Make the socket non-inheritable */
-  if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
-    return GetLastError();
-  }
-
-  /* Associate it with the I/O completion port. Use uv_handle_t pointer as
-   * completion key. */
-  if (CreateIoCompletionPort((HANDLE)socket,
-                             loop->iocp,
-                             (ULONG_PTR)socket,
-                             0) == NULL) {
-    return GetLastError();
-  }
-
-  /* All known Windows that support SetFileCompletionNotificationModes have a
-   * bug that makes it impossible to use this function in conjunction with
-   * datagram sockets. We can work around that but only if the user is using
-   * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here
-   * we check whether that is the case. */
-  opt_len = (int) sizeof info;
-  if (getsockopt(
-          socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) ==
-      SOCKET_ERROR) {
-    return GetLastError();
-  }
-
-  if (info.ProtocolChain.ChainLen == 1) {
-    if (SetFileCompletionNotificationModes(
-            (HANDLE) socket,
-            FILE_SKIP_SET_EVENT_ON_HANDLE |
-                FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
-      handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
-      handle->func_wsarecv = uv_wsarecv_workaround;
-      handle->func_wsarecvfrom = uv_wsarecvfrom_workaround;
-    } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
-      return GetLastError();
-    }
-  }
-
-  handle->socket = socket;
-
-  if (family == AF_INET6) {
-    handle->flags |= UV_HANDLE_IPV6;
-  } else {
-    assert(!(handle->flags & UV_HANDLE_IPV6));
-  }
-
-  return 0;
-}
-
-
-int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
-  int domain;
-
-  /* Use the lower 8 bits for the domain */
-  domain = flags & 0xFF;
-  if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
-    return UV_EINVAL;
-
-  if (flags & ~0xFF)
-    return UV_EINVAL;
-
-  uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP);
-  handle->socket = INVALID_SOCKET;
-  handle->reqs_pending = 0;
-  handle->activecnt = 0;
-  handle->func_wsarecv = WSARecv;
-  handle->func_wsarecvfrom = WSARecvFrom;
-  handle->send_queue_size = 0;
-  handle->send_queue_count = 0;
-  UV_REQ_INIT(&handle->recv_req, UV_UDP_RECV);
-  handle->recv_req.data = handle;
-
-  /* If anything fails beyond this point we need to remove the handle from
-   * the handle queue, since it was added by uv__handle_init.
-   */
-
-  if (domain != AF_UNSPEC) {
-    SOCKET sock;
-    DWORD err;
-
-    sock = socket(domain, SOCK_DGRAM, 0);
-    if (sock == INVALID_SOCKET) {
-      err = WSAGetLastError();
-      QUEUE_REMOVE(&handle->handle_queue);
-      return uv_translate_sys_error(err);
-    }
-
-    err = uv_udp_set_socket(handle->loop, handle, sock, domain);
-    if (err) {
-      closesocket(sock);
-      QUEUE_REMOVE(&handle->handle_queue);
-      return uv_translate_sys_error(err);
-    }
-  }
-
-  return 0;
-}
-
-
-int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) {
-  return uv_udp_init_ex(loop, handle, AF_UNSPEC);
-}
-
-
-void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) {
-  uv_udp_recv_stop(handle);
-  closesocket(handle->socket);
-  handle->socket = INVALID_SOCKET;
-
-  uv__handle_closing(handle);
-
-  if (handle->reqs_pending == 0) {
-    uv_want_endgame(loop, (uv_handle_t*) handle);
-  }
-}
-
-
-void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) {
-  if (handle->flags & UV_HANDLE_CLOSING &&
-      handle->reqs_pending == 0) {
-    assert(!(handle->flags & UV_HANDLE_CLOSED));
-    uv__handle_close(handle);
-  }
-}
-
-
-static int uv_udp_maybe_bind(uv_udp_t* handle,
-                             const struct sockaddr* addr,
-                             unsigned int addrlen,
-                             unsigned int flags) {
-  int r;
-  int err;
-  DWORD no = 0;
-
-  if (handle->flags & UV_HANDLE_BOUND)
-    return 0;
-
-  if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6) {
-    /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */
-    return ERROR_INVALID_PARAMETER;
-  }
-
-  if (handle->socket == INVALID_SOCKET) {
-    SOCKET sock = socket(addr->sa_family, SOCK_DGRAM, 0);
-    if (sock == INVALID_SOCKET) {
-      return WSAGetLastError();
-    }
-
-    err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family);
-    if (err) {
-      closesocket(sock);
-      return err;
-    }
-  }
-
-  if (flags & UV_UDP_REUSEADDR) {
-    DWORD yes = 1;
-    /* Set SO_REUSEADDR on the socket. */
-    if (setsockopt(handle->socket,
-                   SOL_SOCKET,
-                   SO_REUSEADDR,
-                   (char*) &yes,
-                   sizeof yes) == SOCKET_ERROR) {
-      err = WSAGetLastError();
-      return err;
-    }
-  }
-
-  if (addr->sa_family == AF_INET6)
-    handle->flags |= UV_HANDLE_IPV6;
-
-  if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) {
-    /* On windows IPV6ONLY is on by default. If the user doesn't specify it
-     * libuv turns it off. */
-
-    /* TODO: how to handle errors? This may fail if there is no ipv4 stack
-     * available, or when run on XP/2003 which have no support for dualstack
-     * sockets. For now we're silently ignoring the error. */
-    setsockopt(handle->socket,
-               IPPROTO_IPV6,
-               IPV6_V6ONLY,
-               (char*) &no,
-               sizeof no);
-  }
-
-  r = bind(handle->socket, addr, addrlen);
-  if (r == SOCKET_ERROR) {
-    return WSAGetLastError();
-  }
-
-  handle->flags |= UV_HANDLE_BOUND;
-
-  return 0;
-}
-
-
-static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) {
-  uv_req_t* req;
-  uv_buf_t buf;
-  DWORD bytes, flags;
-  int result;
-
-  assert(handle->flags & UV_HANDLE_READING);
-  assert(!(handle->flags & UV_HANDLE_READ_PENDING));
-
-  req = &handle->recv_req;
-  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-
-  /*
-   * Preallocate a read buffer if the number of active streams is below
-   * the threshold.
-  */
-  if (loop->active_udp_streams < uv_active_udp_streams_threshold) {
-    handle->flags &= ~UV_HANDLE_ZERO_READ;
-
-    handle->recv_buffer = uv_buf_init(NULL, 0);
-    handle->alloc_cb((uv_handle_t*) handle, 65536, &handle->recv_buffer);
-    if (handle->recv_buffer.base == NULL || handle->recv_buffer.len == 0) {
-      handle->recv_cb(handle, UV_ENOBUFS, &handle->recv_buffer, NULL, 0);
-      return;
-    }
-    assert(handle->recv_buffer.base != NULL);
-
-    buf = handle->recv_buffer;
-    memset(&handle->recv_from, 0, sizeof handle->recv_from);
-    handle->recv_from_len = sizeof handle->recv_from;
-    flags = 0;
-
-    result = handle->func_wsarecvfrom(handle->socket,
-                                      (WSABUF*) &buf,
-                                      1,
-                                      &bytes,
-                                      &flags,
-                                      (struct sockaddr*) &handle->recv_from,
-                                      &handle->recv_from_len,
-                                      &req->u.io.overlapped,
-                                      NULL);
-
-    if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
-      /* Process the req without IOCP. */
-      handle->flags |= UV_HANDLE_READ_PENDING;
-      req->u.io.overlapped.InternalHigh = bytes;
-      handle->reqs_pending++;
-      uv_insert_pending_req(loop, req);
-    } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
-      /* The req will be processed with IOCP. */
-      handle->flags |= UV_HANDLE_READ_PENDING;
-      handle->reqs_pending++;
-    } else {
-      /* Make this req pending reporting an error. */
-      SET_REQ_ERROR(req, WSAGetLastError());
-      uv_insert_pending_req(loop, req);
-      handle->reqs_pending++;
-    }
-
-  } else {
-    handle->flags |= UV_HANDLE_ZERO_READ;
-
-    buf.base = (char*) uv_zero_;
-    buf.len = 0;
-    flags = MSG_PEEK;
-
-    result = handle->func_wsarecv(handle->socket,
-                                  (WSABUF*) &buf,
-                                  1,
-                                  &bytes,
-                                  &flags,
-                                  &req->u.io.overlapped,
-                                  NULL);
-
-    if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
-      /* Process the req without IOCP. */
-      handle->flags |= UV_HANDLE_READ_PENDING;
-      req->u.io.overlapped.InternalHigh = bytes;
-      handle->reqs_pending++;
-      uv_insert_pending_req(loop, req);
-    } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
-      /* The req will be processed with IOCP. */
-      handle->flags |= UV_HANDLE_READ_PENDING;
-      handle->reqs_pending++;
-    } else {
-      /* Make this req pending reporting an error. */
-      SET_REQ_ERROR(req, WSAGetLastError());
-      uv_insert_pending_req(loop, req);
-      handle->reqs_pending++;
-    }
-  }
-}
-
-
-int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
-    uv_udp_recv_cb recv_cb) {
-  uv_loop_t* loop = handle->loop;
-  int err;
-
-  if (handle->flags & UV_HANDLE_READING) {
-    return UV_EALREADY;
-  }
-
-  err = uv_udp_maybe_bind(handle,
-                          (const struct sockaddr*) &uv_addr_ip4_any_,
-                          sizeof(uv_addr_ip4_any_),
-                          0);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  handle->flags |= UV_HANDLE_READING;
-  INCREASE_ACTIVE_COUNT(loop, handle);
-  loop->active_udp_streams++;
-
-  handle->recv_cb = recv_cb;
-  handle->alloc_cb = alloc_cb;
-
-  /* If reading was stopped and then started again, there could still be a recv
-   * request pending. */
-  if (!(handle->flags & UV_HANDLE_READ_PENDING))
-    uv_udp_queue_recv(loop, handle);
-
-  return 0;
-}
-
-
-int uv__udp_recv_stop(uv_udp_t* handle) {
-  if (handle->flags & UV_HANDLE_READING) {
-    handle->flags &= ~UV_HANDLE_READING;
-    handle->loop->active_udp_streams--;
-    DECREASE_ACTIVE_COUNT(loop, handle);
-  }
-
-  return 0;
-}
-
-
-static int uv__send(uv_udp_send_t* req,
-                    uv_udp_t* handle,
-                    const uv_buf_t bufs[],
-                    unsigned int nbufs,
-                    const struct sockaddr* addr,
-                    unsigned int addrlen,
-                    uv_udp_send_cb cb) {
-  uv_loop_t* loop = handle->loop;
-  DWORD result, bytes;
-
-  UV_REQ_INIT(req, UV_UDP_SEND);
-  req->handle = handle;
-  req->cb = cb;
-  memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
-
-  result = WSASendTo(handle->socket,
-                     (WSABUF*)bufs,
-                     nbufs,
-                     &bytes,
-                     0,
-                     addr,
-                     addrlen,
-                     &req->u.io.overlapped,
-                     NULL);
-
-  if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) {
-    /* Request completed immediately. */
-    req->u.io.queued_bytes = 0;
-    handle->reqs_pending++;
-    handle->send_queue_size += req->u.io.queued_bytes;
-    handle->send_queue_count++;
-    REGISTER_HANDLE_REQ(loop, handle, req);
-    uv_insert_pending_req(loop, (uv_req_t*)req);
-  } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
-    /* Request queued by the kernel. */
-    req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs);
-    handle->reqs_pending++;
-    handle->send_queue_size += req->u.io.queued_bytes;
-    handle->send_queue_count++;
-    REGISTER_HANDLE_REQ(loop, handle, req);
-  } else {
-    /* Send failed due to an error. */
-    return WSAGetLastError();
-  }
-
-  return 0;
-}
-
-
-void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
-    uv_req_t* req) {
-  uv_buf_t buf;
-  int partial;
-
-  assert(handle->type == UV_UDP);
-
-  handle->flags &= ~UV_HANDLE_READ_PENDING;
-
-  if (!REQ_SUCCESS(req)) {
-    DWORD err = GET_REQ_SOCK_ERROR(req);
-    if (err == WSAEMSGSIZE) {
-      /* Not a real error, it just indicates that the received packet was
-       * bigger than the receive buffer. */
-    } else if (err == WSAECONNRESET || err == WSAENETRESET) {
-      /* A previous sendto operation failed; ignore this error. If zero-reading
-       * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to
-       * clear out the error queue. For nonzero reads, immediately queue a new
-       * receive. */
-      if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
-        goto done;
-      }
-    } else {
-      /* A real error occurred. Report the error to the user only if we're
-       * currently reading. */
-      if (handle->flags & UV_HANDLE_READING) {
-        uv_udp_recv_stop(handle);
-        buf = (handle->flags & UV_HANDLE_ZERO_READ) ?
-              uv_buf_init(NULL, 0) : handle->recv_buffer;
-        handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
-      }
-      goto done;
-    }
-  }
-
-  if (!(handle->flags & UV_HANDLE_ZERO_READ)) {
-    /* Successful read */
-    partial = !REQ_SUCCESS(req);
-    handle->recv_cb(handle,
-                    req->u.io.overlapped.InternalHigh,
-                    &handle->recv_buffer,
-                    (const struct sockaddr*) &handle->recv_from,
-                    partial ? UV_UDP_PARTIAL : 0);
-  } else if (handle->flags & UV_HANDLE_READING) {
-    DWORD bytes, err, flags;
-    struct sockaddr_storage from;
-    int from_len;
-
-    /* Do a nonblocking receive.
-     * TODO: try to read multiple datagrams at once. FIONREAD maybe? */
-    buf = uv_buf_init(NULL, 0);
-    handle->alloc_cb((uv_handle_t*) handle, 65536, &buf);
-    if (buf.base == NULL || buf.len == 0) {
-      handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
-      goto done;
-    }
-    assert(buf.base != NULL);
-
-    memset(&from, 0, sizeof from);
-    from_len = sizeof from;
-
-    flags = 0;
-
-    if (WSARecvFrom(handle->socket,
-                    (WSABUF*)&buf,
-                    1,
-                    &bytes,
-                    &flags,
-                    (struct sockaddr*) &from,
-                    &from_len,
-                    NULL,
-                    NULL) != SOCKET_ERROR) {
-
-      /* Message received */
-      handle->recv_cb(handle, bytes, &buf, (const struct sockaddr*) &from, 0);
-    } else {
-      err = WSAGetLastError();
-      if (err == WSAEMSGSIZE) {
-        /* Message truncated */
-        handle->recv_cb(handle,
-                        bytes,
-                        &buf,
-                        (const struct sockaddr*) &from,
-                        UV_UDP_PARTIAL);
-      } else if (err == WSAEWOULDBLOCK) {
-        /* Kernel buffer empty */
-        handle->recv_cb(handle, 0, &buf, NULL, 0);
-      } else if (err == WSAECONNRESET || err == WSAENETRESET) {
-        /* WSAECONNRESET/WSANETRESET is ignored because this just indicates
-         * that a previous sendto operation failed.
-         */
-        handle->recv_cb(handle, 0, &buf, NULL, 0);
-      } else {
-        /* Any other error that we want to report back to the user. */
-        uv_udp_recv_stop(handle);
-        handle->recv_cb(handle, uv_translate_sys_error(err), &buf, NULL, 0);
-      }
-    }
-  }
-
-done:
-  /* Post another read if still reading and not closing. */
-  if ((handle->flags & UV_HANDLE_READING) &&
-      !(handle->flags & UV_HANDLE_READ_PENDING)) {
-    uv_udp_queue_recv(loop, handle);
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle,
-    uv_udp_send_t* req) {
-  int err;
-
-  assert(handle->type == UV_UDP);
-
-  assert(handle->send_queue_size >= req->u.io.queued_bytes);
-  assert(handle->send_queue_count >= 1);
-  handle->send_queue_size -= req->u.io.queued_bytes;
-  handle->send_queue_count--;
-
-  UNREGISTER_HANDLE_REQ(loop, handle, req);
-
-  if (req->cb) {
-    err = 0;
-    if (!REQ_SUCCESS(req)) {
-      err = GET_REQ_SOCK_ERROR(req);
-    }
-    req->cb(req, uv_translate_sys_error(err));
-  }
-
-  DECREASE_PENDING_REQ_COUNT(handle);
-}
-
-
-static int uv__udp_set_membership4(uv_udp_t* handle,
-                                   const struct sockaddr_in* multicast_addr,
-                                   const char* interface_addr,
-                                   uv_membership membership) {
-  int err;
-  int optname;
-  struct ip_mreq mreq;
-
-  if (handle->flags & UV_HANDLE_IPV6)
-    return UV_EINVAL;
-
-  /* If the socket is unbound, bind to inaddr_any. */
-  err = uv_udp_maybe_bind(handle,
-                          (const struct sockaddr*) &uv_addr_ip4_any_,
-                          sizeof(uv_addr_ip4_any_),
-                          UV_UDP_REUSEADDR);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  memset(&mreq, 0, sizeof mreq);
-
-  if (interface_addr) {
-    err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
-    if (err)
-      return err;
-  } else {
-    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
-  }
-
-  mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
-
-  switch (membership) {
-    case UV_JOIN_GROUP:
-      optname = IP_ADD_MEMBERSHIP;
-      break;
-    case UV_LEAVE_GROUP:
-      optname = IP_DROP_MEMBERSHIP;
-      break;
-    default:
-      return UV_EINVAL;
-  }
-
-  if (setsockopt(handle->socket,
-                 IPPROTO_IP,
-                 optname,
-                 (char*) &mreq,
-                 sizeof mreq) == SOCKET_ERROR) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
-
-  return 0;
-}
-
-
-int uv__udp_set_membership6(uv_udp_t* handle,
-                            const struct sockaddr_in6* multicast_addr,
-                            const char* interface_addr,
-                            uv_membership membership) {
-  int optname;
-  int err;
-  struct ipv6_mreq mreq;
-  struct sockaddr_in6 addr6;
-
-  if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6))
-    return UV_EINVAL;
-
-  err = uv_udp_maybe_bind(handle,
-                          (const struct sockaddr*) &uv_addr_ip6_any_,
-                          sizeof(uv_addr_ip6_any_),
-                          UV_UDP_REUSEADDR);
-
-  if (err)
-    return uv_translate_sys_error(err);
-
-  memset(&mreq, 0, sizeof(mreq));
-
-  if (interface_addr) {
-    if (uv_ip6_addr(interface_addr, 0, &addr6))
-      return UV_EINVAL;
-    mreq.ipv6mr_interface = addr6.sin6_scope_id;
-  } else {
-    mreq.ipv6mr_interface = 0;
-  }
-
-  mreq.ipv6mr_multiaddr = multicast_addr->sin6_addr;
-
-  switch (membership) {
-  case UV_JOIN_GROUP:
-    optname = IPV6_ADD_MEMBERSHIP;
-    break;
-  case UV_LEAVE_GROUP:
-    optname = IPV6_DROP_MEMBERSHIP;
-    break;
-  default:
-    return UV_EINVAL;
-  }
-
-  if (setsockopt(handle->socket,
-                 IPPROTO_IPV6,
-                 optname,
-                 (char*) &mreq,
-                 sizeof mreq) == SOCKET_ERROR) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
-
-  return 0;
-}
-
-
-int uv_udp_set_membership(uv_udp_t* handle,
-                          const char* multicast_addr,
-                          const char* interface_addr,
-                          uv_membership membership) {
-  struct sockaddr_in addr4;
-  struct sockaddr_in6 addr6;
-
-  if (uv_ip4_addr(multicast_addr, 0, &addr4) == 0)
-    return uv__udp_set_membership4(handle, &addr4, interface_addr, membership);
-  else if (uv_ip6_addr(multicast_addr, 0, &addr6) == 0)
-    return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
-  else
-    return UV_EINVAL;
-}
-
-
-int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
-  struct sockaddr_storage addr_st;
-  struct sockaddr_in* addr4;
-  struct sockaddr_in6* addr6;
-
-  addr4 = (struct sockaddr_in*) &addr_st;
-  addr6 = (struct sockaddr_in6*) &addr_st;
-
-  if (!interface_addr) {
-    memset(&addr_st, 0, sizeof addr_st);
-    if (handle->flags & UV_HANDLE_IPV6) {
-      addr_st.ss_family = AF_INET6;
-      addr6->sin6_scope_id = 0;
-    } else {
-      addr_st.ss_family = AF_INET;
-      addr4->sin_addr.s_addr = htonl(INADDR_ANY);
-    }
-  } else if (uv_ip4_addr(interface_addr, 0, addr4) == 0) {
-    /* nothing, address was parsed */
-  } else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
-    /* nothing, address was parsed */
-  } else {
-    return UV_EINVAL;
-  }
-
-  if (handle->socket == INVALID_SOCKET)
-    return UV_EBADF;
-
-  if (addr_st.ss_family == AF_INET) {
-    if (setsockopt(handle->socket,
-                   IPPROTO_IP,
-                   IP_MULTICAST_IF,
-                   (char*) &addr4->sin_addr,
-                   sizeof(addr4->sin_addr)) == SOCKET_ERROR) {
-      return uv_translate_sys_error(WSAGetLastError());
-    }
-  } else if (addr_st.ss_family == AF_INET6) {
-    if (setsockopt(handle->socket,
-                   IPPROTO_IPV6,
-                   IPV6_MULTICAST_IF,
-                   (char*) &addr6->sin6_scope_id,
-                   sizeof(addr6->sin6_scope_id)) == SOCKET_ERROR) {
-      return uv_translate_sys_error(WSAGetLastError());
-    }
-  } else {
-    assert(0 && "unexpected address family");
-    abort();
-  }
-
-  return 0;
-}
-
-
-int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
-  BOOL optval = (BOOL) value;
-
-  if (handle->socket == INVALID_SOCKET)
-    return UV_EBADF;
-
-  if (setsockopt(handle->socket,
-                 SOL_SOCKET,
-                 SO_BROADCAST,
-                 (char*) &optval,
-                 sizeof optval)) {
-    return uv_translate_sys_error(WSAGetLastError());
-  }
-
-  return 0;
-}
-
-
-int uv__udp_is_bound(uv_udp_t* handle) {
-  struct sockaddr_storage addr;
-  int addrlen;
-
-  addrlen = sizeof(addr);
-  if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0)
-    return 0;
-
-  return addrlen > 0;
-}
-
-
-int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
-  WSAPROTOCOL_INFOW protocol_info;
-  int opt_len;
-  int err;
-
-  /* Detect the address family of the socket. */
-  opt_len = (int) sizeof protocol_info;
-  if (getsockopt(sock,
-                 SOL_SOCKET,
-                 SO_PROTOCOL_INFOW,
-                 (char*) &protocol_info,
-                 &opt_len) == SOCKET_ERROR) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  err = uv_udp_set_socket(handle->loop,
-                          handle,
-                          sock,
-                          protocol_info.iAddressFamily);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  if (uv__udp_is_bound(handle))
-    handle->flags |= UV_HANDLE_BOUND;
-
-  if (uv__udp_is_connected(handle))
-    handle->flags |= UV_HANDLE_UDP_CONNECTED;
-
-  return 0;
-}
-
-
-#define SOCKOPT_SETTER(name, option4, option6, validate)                      \
-  int uv_udp_set_##name(uv_udp_t* handle, int value) {                        \
-    DWORD optval = (DWORD) value;                                             \
-                                                                              \
-    if (!(validate(value))) {                                                 \
-      return UV_EINVAL;                                                       \
-    }                                                                         \
-                                                                              \
-    if (handle->socket == INVALID_SOCKET)                                     \
-      return UV_EBADF;                                                        \
-                                                                              \
-    if (!(handle->flags & UV_HANDLE_IPV6)) {                                  \
-      /* Set IPv4 socket option */                                            \
-      if (setsockopt(handle->socket,                                          \
-                     IPPROTO_IP,                                              \
-                     option4,                                                 \
-                     (char*) &optval,                                         \
-                     sizeof optval)) {                                        \
-        return uv_translate_sys_error(WSAGetLastError());                     \
-      }                                                                       \
-    } else {                                                                  \
-      /* Set IPv6 socket option */                                            \
-      if (setsockopt(handle->socket,                                          \
-                     IPPROTO_IPV6,                                            \
-                     option6,                                                 \
-                     (char*) &optval,                                         \
-                     sizeof optval)) {                                        \
-        return uv_translate_sys_error(WSAGetLastError());                     \
-      }                                                                       \
-    }                                                                         \
-    return 0;                                                                 \
-  }
-
-#define VALIDATE_TTL(value) ((value) >= 1 && (value) <= 255)
-#define VALIDATE_MULTICAST_TTL(value) ((value) >= -1 && (value) <= 255)
-#define VALIDATE_MULTICAST_LOOP(value) (1)
-
-SOCKOPT_SETTER(ttl,
-               IP_TTL,
-               IPV6_HOPLIMIT,
-               VALIDATE_TTL)
-SOCKOPT_SETTER(multicast_ttl,
-               IP_MULTICAST_TTL,
-               IPV6_MULTICAST_HOPS,
-               VALIDATE_MULTICAST_TTL)
-SOCKOPT_SETTER(multicast_loop,
-               IP_MULTICAST_LOOP,
-               IPV6_MULTICAST_LOOP,
-               VALIDATE_MULTICAST_LOOP)
-
-#undef SOCKOPT_SETTER
-#undef VALIDATE_TTL
-#undef VALIDATE_MULTICAST_TTL
-#undef VALIDATE_MULTICAST_LOOP
-
-
-/* This function is an egress point, i.e. it returns libuv errors rather than
- * system errors.
- */
-int uv__udp_bind(uv_udp_t* handle,
-                 const struct sockaddr* addr,
-                 unsigned int addrlen,
-                 unsigned int flags) {
-  int err;
-
-  err = uv_udp_maybe_bind(handle, addr, addrlen, flags);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  return 0;
-}
-
-
-int uv__udp_connect(uv_udp_t* handle,
-                    const struct sockaddr* addr,
-                    unsigned int addrlen) {
-  const struct sockaddr* bind_addr;
-  int err;
-
-  if (!(handle->flags & UV_HANDLE_BOUND)) {
-    if (addrlen == sizeof(uv_addr_ip4_any_))
-      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
-    else if (addrlen == sizeof(uv_addr_ip6_any_))
-      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
-    else
-      return UV_EINVAL;
-
-    err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
-    if (err)
-      return uv_translate_sys_error(err);
-  }
-
-  err = connect(handle->socket, addr, addrlen);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  handle->flags |= UV_HANDLE_UDP_CONNECTED;
-
-  return 0;
-}
-
-
-int uv__udp_disconnect(uv_udp_t* handle) {
-    int err;
-    struct sockaddr addr;
-
-    memset(&addr, 0, sizeof(addr));
-
-    err = connect(handle->socket, &addr, sizeof(addr));
-    if (err)
-      return uv_translate_sys_error(err);
-
-    handle->flags &= ~UV_HANDLE_UDP_CONNECTED;
-    return 0;
-}
-
-
-/* This function is an egress point, i.e. it returns libuv errors rather than
- * system errors.
- */
-int uv__udp_send(uv_udp_send_t* req,
-                 uv_udp_t* handle,
-                 const uv_buf_t bufs[],
-                 unsigned int nbufs,
-                 const struct sockaddr* addr,
-                 unsigned int addrlen,
-                 uv_udp_send_cb send_cb) {
-  const struct sockaddr* bind_addr;
-  int err;
-
-  if (!(handle->flags & UV_HANDLE_BOUND)) {
-    if (addrlen == sizeof(uv_addr_ip4_any_))
-      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
-    else if (addrlen == sizeof(uv_addr_ip6_any_))
-      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
-    else
-      return UV_EINVAL;
-
-    err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
-    if (err)
-      return uv_translate_sys_error(err);
-  }
-
-  err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
-  if (err)
-    return uv_translate_sys_error(err);
-
-  return 0;
-}
-
-
-int uv__udp_try_send(uv_udp_t* handle,
-                     const uv_buf_t bufs[],
-                     unsigned int nbufs,
-                     const struct sockaddr* addr,
-                     unsigned int addrlen) {
-  DWORD bytes;
-  const struct sockaddr* bind_addr;
-  struct sockaddr_storage converted;
-  int err;
-
-  assert(nbufs > 0);
-
-  if (addr != NULL) {
-    err = uv__convert_to_localhost_if_unspecified(addr, &converted);
-    if (err)
-      return err;
-  }
-
-  /* Already sending a message.*/
-  if (handle->send_queue_count != 0)
-    return UV_EAGAIN;
-
-  if (!(handle->flags & UV_HANDLE_BOUND)) {
-    if (addrlen == sizeof(uv_addr_ip4_any_))
-      bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
-    else if (addrlen == sizeof(uv_addr_ip6_any_))
-      bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
-    else
-      return UV_EINVAL;
-    err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
-    if (err)
-      return uv_translate_sys_error(err);
-  }
-
-  err = WSASendTo(handle->socket,
-                  (WSABUF*)bufs,
-                  nbufs,
-                  &bytes,
-                  0,
-                  (const struct sockaddr*) &converted,
-                  addrlen,
-                  NULL,
-                  NULL);
-
-  if (err)
-    return uv_translate_sys_error(WSAGetLastError());
-
-  return bytes;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/util.cpp b/wpiutil/src/main/native/libuv/src/win/util.cpp
deleted file mode 100644
index b5afb1d..0000000
--- a/wpiutil/src/main/native/libuv/src/win/util.cpp
+++ /dev/null
@@ -1,1811 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <direct.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <wchar.h>
-
-#include "uv.h"
-#include "internal.h"
-
-#include <winsock2.h>
-#include <winperf.h>
-#include <iphlpapi.h>
-#include <psapi.h>
-#include <tlhelp32.h>
-#include <windows.h>
-#include <userenv.h>
-#include <math.h>
-
-/*
- * Max title length; the only thing MSDN tells us about the maximum length
- * of the console title is that it is smaller than 64K. However in practice
- * it is much smaller, and there is no way to figure out what the exact length
- * of the title is or can be, at least not on XP. To make it even more
- * annoying, GetConsoleTitle fails when the buffer to be read into is bigger
- * than the actual maximum length. So we make a conservative guess here;
- * just don't put the novel you're writing in the title, unless the plot
- * survives truncation.
- */
-#define MAX_TITLE_LENGTH 8192
-
-/* The number of nanoseconds in one second. */
-#define UV__NANOSEC 1000000000
-
-/* Max user name length, from iphlpapi.h */
-#ifndef UNLEN
-# define UNLEN 256
-#endif
-
-
-/* Maximum environment variable size, including the terminating null */
-#define MAX_ENV_VAR_LENGTH 32767
-
-/* Cached copy of the process title, plus a mutex guarding it. */
-static char *process_title;
-static CRITICAL_SECTION process_title_lock;
-
-#pragma comment(lib, "Advapi32.lib")
-#pragma comment(lib, "IPHLPAPI.lib")
-#pragma comment(lib, "Psapi.lib")
-#pragma comment(lib, "Userenv.lib")
-#pragma comment(lib, "kernel32.lib")
-
-/* Interval (in seconds) of the high-resolution clock. */
-static double hrtime_interval_ = 0;
-
-
-/*
- * One-time initialization code for functionality defined in util.c.
- */
-void uv__util_init(void) {
-  LARGE_INTEGER perf_frequency;
-
-  /* Initialize process title access mutex. */
-  InitializeCriticalSection(&process_title_lock);
-
-  /* Retrieve high-resolution timer frequency
-   * and precompute its reciprocal.
-   */
-  if (QueryPerformanceFrequency(&perf_frequency)) {
-    hrtime_interval_ = 1.0 / perf_frequency.QuadPart;
-  } else {
-    hrtime_interval_= 0;
-  }
-}
-
-
-int uv_exepath(char* buffer, size_t* size_ptr) {
-  int utf8_len, utf16_buffer_len, utf16_len;
-  WCHAR* utf16_buffer;
-  int err;
-
-  if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) {
-    return UV_EINVAL;
-  }
-
-  if (*size_ptr > 32768) {
-    /* Windows paths can never be longer than this. */
-    utf16_buffer_len = 32768;
-  } else {
-    utf16_buffer_len = (int) *size_ptr;
-  }
-
-  utf16_buffer = (WCHAR*) uv__malloc(sizeof(WCHAR) * utf16_buffer_len);
-  if (!utf16_buffer) {
-    return UV_ENOMEM;
-  }
-
-  /* Get the path as UTF-16. */
-  utf16_len = GetModuleFileNameW(NULL, utf16_buffer, utf16_buffer_len);
-  if (utf16_len <= 0) {
-    err = GetLastError();
-    goto error;
-  }
-
-  /* utf16_len contains the length, *not* including the terminating null. */
-  utf16_buffer[utf16_len] = L'\0';
-
-  /* Convert to UTF-8 */
-  utf8_len = WideCharToMultiByte(CP_UTF8,
-                                 0,
-                                 utf16_buffer,
-                                 -1,
-                                 buffer,
-                                 (int) *size_ptr,
-                                 NULL,
-                                 NULL);
-  if (utf8_len == 0) {
-    err = GetLastError();
-    goto error;
-  }
-
-  uv__free(utf16_buffer);
-
-  /* utf8_len *does* include the terminating null at this point, but the
-   * returned size shouldn't. */
-  *size_ptr = utf8_len - 1;
-  return 0;
-
- error:
-  uv__free(utf16_buffer);
-  return uv_translate_sys_error(err);
-}
-
-
-int uv_cwd(char* buffer, size_t* size) {
-  DWORD utf16_len;
-  WCHAR utf16_buffer[MAX_PATH];
-  int r;
-
-  if (buffer == NULL || size == NULL) {
-    return UV_EINVAL;
-  }
-
-  utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
-  if (utf16_len == 0) {
-    return uv_translate_sys_error(GetLastError());
-  } else if (utf16_len > MAX_PATH) {
-    /* This should be impossible; however the CRT has a code path to deal with
-     * this scenario, so I added a check anyway. */
-    return UV_EIO;
-  }
-
-  /* utf16_len contains the length, *not* including the terminating null. */
-  utf16_buffer[utf16_len] = L'\0';
-
-  /* The returned directory should not have a trailing slash, unless it points
-   * at a drive root, like c:\. Remove it if needed. */
-  if (utf16_buffer[utf16_len - 1] == L'\\' &&
-      !(utf16_len == 3 && utf16_buffer[1] == L':')) {
-    utf16_len--;
-    utf16_buffer[utf16_len] = L'\0';
-  }
-
-  /* Check how much space we need */
-  r = WideCharToMultiByte(CP_UTF8,
-                          0,
-                          utf16_buffer,
-                          -1,
-                          NULL,
-                          0,
-                          NULL,
-                          NULL);
-  if (r == 0) {
-    return uv_translate_sys_error(GetLastError());
-  } else if (r > (int) *size) {
-    *size = r;
-    return UV_ENOBUFS;
-  }
-
-  /* Convert to UTF-8 */
-  r = WideCharToMultiByte(CP_UTF8,
-                          0,
-                          utf16_buffer,
-                          -1,
-                          buffer,
-                          *size > INT_MAX ? INT_MAX : (int) *size,
-                          NULL,
-                          NULL);
-  if (r == 0) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  *size = r - 1;
-  return 0;
-}
-
-
-int uv_chdir(const char* dir) {
-  WCHAR utf16_buffer[MAX_PATH];
-  size_t utf16_len;
-  WCHAR drive_letter, env_var[4];
-
-  if (dir == NULL) {
-    return UV_EINVAL;
-  }
-
-  if (MultiByteToWideChar(CP_UTF8,
-                          0,
-                          dir,
-                          -1,
-                          utf16_buffer,
-                          MAX_PATH) == 0) {
-    DWORD error = GetLastError();
-    /* The maximum length of the current working directory is 260 chars,
-     * including terminating null. If it doesn't fit, the path name must be too
-     * long. */
-    if (error == ERROR_INSUFFICIENT_BUFFER) {
-      return UV_ENAMETOOLONG;
-    } else {
-      return uv_translate_sys_error(error);
-    }
-  }
-
-  if (!SetCurrentDirectoryW(utf16_buffer)) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  /* Windows stores the drive-local path in an "hidden" environment variable,
-   * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update
-   * this, so we'll have to do it. */
-  utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
-  if (utf16_len == 0) {
-    return uv_translate_sys_error(GetLastError());
-  } else if (utf16_len > MAX_PATH) {
-    return UV_EIO;
-  }
-
-  /* The returned directory should not have a trailing slash, unless it points
-   * at a drive root, like c:\. Remove it if needed. */
-  if (utf16_buffer[utf16_len - 1] == L'\\' &&
-      !(utf16_len == 3 && utf16_buffer[1] == L':')) {
-    utf16_len--;
-    utf16_buffer[utf16_len] = L'\0';
-  }
-
-  if (utf16_len < 2 || utf16_buffer[1] != L':') {
-    /* Doesn't look like a drive letter could be there - probably an UNC path.
-     * TODO: Need to handle win32 namespaces like \\?\C:\ ? */
-    drive_letter = 0;
-  } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
-    drive_letter = utf16_buffer[0];
-  } else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {
-    /* Convert to uppercase. */
-    drive_letter = utf16_buffer[0] - L'a' + L'A';
-  } else {
-    /* Not valid. */
-    drive_letter = 0;
-  }
-
-  if (drive_letter != 0) {
-    /* Construct the environment variable name and set it. */
-    env_var[0] = L'=';
-    env_var[1] = drive_letter;
-    env_var[2] = L':';
-    env_var[3] = L'\0';
-
-    if (!SetEnvironmentVariableW(env_var, utf16_buffer)) {
-      return uv_translate_sys_error(GetLastError());
-    }
-  }
-
-  return 0;
-}
-
-
-void uv_loadavg(double avg[3]) {
-  /* Can't be implemented */
-  avg[0] = avg[1] = avg[2] = 0;
-}
-
-
-uint64_t uv_get_free_memory(void) {
-  MEMORYSTATUSEX memory_status;
-  memory_status.dwLength = sizeof(memory_status);
-
-  if (!GlobalMemoryStatusEx(&memory_status)) {
-     return -1;
-  }
-
-  return (uint64_t)memory_status.ullAvailPhys;
-}
-
-
-uint64_t uv_get_total_memory(void) {
-  MEMORYSTATUSEX memory_status;
-  memory_status.dwLength = sizeof(memory_status);
-
-  if (!GlobalMemoryStatusEx(&memory_status)) {
-    return -1;
-  }
-
-  return (uint64_t)memory_status.ullTotalPhys;
-}
-
-
-uint64_t uv_get_constrained_memory(void) {
-  return 0;  /* Memory constraints are unknown. */
-}
-
-
-uv_pid_t uv_os_getpid(void) {
-  return GetCurrentProcessId();
-}
-
-
-uv_pid_t uv_os_getppid(void) {
-  int parent_pid = -1;
-  HANDLE handle;
-  PROCESSENTRY32 pe;
-  DWORD current_pid = GetCurrentProcessId();
-
-  pe.dwSize = sizeof(PROCESSENTRY32);
-  handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
-
-  if (Process32First(handle, &pe)) {
-    do {
-      if (pe.th32ProcessID == current_pid) {
-        parent_pid = pe.th32ParentProcessID;
-        break;
-      }
-    } while( Process32Next(handle, &pe));
-  }
-
-  CloseHandle(handle);
-  return parent_pid;
-}
-
-
-char** uv_setup_args(int argc, char** argv) {
-  return argv;
-}
-
-
-int uv_set_process_title(const char* title) {
-  int err;
-  int length;
-  WCHAR* title_w = NULL;
-
-  uv__once_init();
-
-  /* Find out how big the buffer for the wide-char title must be */
-  length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
-  if (!length) {
-    err = GetLastError();
-    goto done;
-  }
-
-  /* Convert to wide-char string */
-  title_w = (WCHAR*)uv__malloc(sizeof(WCHAR) * length);
-  if (!title_w) {
-    uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
-  }
-
-  length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length);
-  if (!length) {
-    err = GetLastError();
-    goto done;
-  }
-
-  /* If the title must be truncated insert a \0 terminator there */
-  if (length > MAX_TITLE_LENGTH) {
-    title_w[MAX_TITLE_LENGTH - 1] = L'\0';
-  }
-
-  if (!SetConsoleTitleW(title_w)) {
-    err = GetLastError();
-    goto done;
-  }
-
-  EnterCriticalSection(&process_title_lock);
-  uv__free(process_title);
-  process_title = uv__strdup(title);
-  LeaveCriticalSection(&process_title_lock);
-
-  err = 0;
-
-done:
-  uv__free(title_w);
-  return uv_translate_sys_error(err);
-}
-
-
-static int uv__get_process_title(void) {
-  WCHAR title_w[MAX_TITLE_LENGTH];
-
-  if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
-    return -1;
-  }
-
-  if (uv__convert_utf16_to_utf8(title_w, -1, &process_title) != 0)
-    return -1;
-
-  return 0;
-}
-
-
-int uv_get_process_title(char* buffer, size_t size) {
-  size_t len;
-
-  if (buffer == NULL || size == 0)
-    return UV_EINVAL;
-
-  uv__once_init();
-
-  EnterCriticalSection(&process_title_lock);
-  /*
-   * If the process_title was never read before nor explicitly set,
-   * we must query it with getConsoleTitleW
-   */
-  if (!process_title && uv__get_process_title() == -1) {
-    LeaveCriticalSection(&process_title_lock);
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  assert(process_title);
-  len = strlen(process_title) + 1;
-
-  if (size < len) {
-    LeaveCriticalSection(&process_title_lock);
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, process_title, len);
-  LeaveCriticalSection(&process_title_lock);
-
-  return 0;
-}
-
-
-uint64_t uv_hrtime(void) {
-  uv__once_init();
-  return uv__hrtime(UV__NANOSEC);
-}
-
-uint64_t uv__hrtime(double scale) {
-  LARGE_INTEGER counter;
-
-  /* If the performance interval is zero, there's no support. */
-  if (hrtime_interval_ == 0) {
-    return 0;
-  }
-
-  if (!QueryPerformanceCounter(&counter)) {
-    return 0;
-  }
-
-  /* Because we have no guarantee about the order of magnitude of the
-   * performance counter interval, integer math could cause this computation
-   * to overflow. Therefore we resort to floating point math.
-   */
-  return (uint64_t) ((double) counter.QuadPart * hrtime_interval_ * scale);
-}
-
-
-int uv_resident_set_memory(size_t* rss) {
-  HANDLE current_process;
-  PROCESS_MEMORY_COUNTERS pmc;
-
-  current_process = GetCurrentProcess();
-
-  if (!GetProcessMemoryInfo(current_process, &pmc, sizeof(pmc))) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  *rss = pmc.WorkingSetSize;
-
-  return 0;
-}
-
-
-int uv_uptime(double* uptime) {
-  BYTE stack_buffer[4096];
-  BYTE* malloced_buffer = NULL;
-  BYTE* buffer = (BYTE*) stack_buffer;
-  size_t buffer_size = sizeof(stack_buffer);
-  DWORD data_size;
-
-  PERF_DATA_BLOCK* data_block;
-  PERF_OBJECT_TYPE* object_type;
-  PERF_COUNTER_DEFINITION* counter_definition;
-
-  DWORD i;
-
-  for (;;) {
-    LONG result;
-
-    data_size = (DWORD) buffer_size;
-    result = RegQueryValueExW(HKEY_PERFORMANCE_DATA,
-                              L"2",
-                              NULL,
-                              NULL,
-                              buffer,
-                              &data_size);
-    if (result == ERROR_SUCCESS) {
-      break;
-    } else if (result != ERROR_MORE_DATA) {
-      *uptime = 0;
-      return uv_translate_sys_error(result);
-    }
-
-    buffer_size *= 2;
-    /* Don't let the buffer grow infinitely. */
-    if (buffer_size > 1 << 20) {
-      goto internalError;
-    }
-
-    uv__free(malloced_buffer);
-
-    buffer = malloced_buffer = (BYTE*) uv__malloc(buffer_size);
-    if (malloced_buffer == NULL) {
-      *uptime = 0;
-      return UV_ENOMEM;
-    }
-  }
-
-  if (data_size < sizeof(*data_block))
-    goto internalError;
-
-  data_block = (PERF_DATA_BLOCK*) buffer;
-
-  if (wmemcmp(data_block->Signature, L"PERF", 4) != 0)
-    goto internalError;
-
-  if (data_size < data_block->HeaderLength + sizeof(*object_type))
-    goto internalError;
-
-  object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength);
-
-  if (object_type->NumInstances != PERF_NO_INSTANCES)
-    goto internalError;
-
-  counter_definition = (PERF_COUNTER_DEFINITION*) (buffer +
-      data_block->HeaderLength + object_type->HeaderLength);
-  for (i = 0; i < object_type->NumCounters; i++) {
-    if ((BYTE*) counter_definition + sizeof(*counter_definition) >
-        buffer + data_size) {
-      break;
-    }
-
-    if (counter_definition->CounterNameTitleIndex == 674 &&
-        counter_definition->CounterSize == sizeof(uint64_t)) {
-      if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size ||
-          !(counter_definition->CounterType & PERF_OBJECT_TIMER)) {
-        goto internalError;
-      } else {
-        BYTE* address = (BYTE*) object_type + object_type->DefinitionLength +
-                        counter_definition->CounterOffset;
-        uint64_t value = *((uint64_t*) address);
-        *uptime = floor((double) (object_type->PerfTime.QuadPart - value) /
-                        (double) object_type->PerfFreq.QuadPart);
-        uv__free(malloced_buffer);
-        return 0;
-      }
-    }
-
-    counter_definition = (PERF_COUNTER_DEFINITION*)
-        ((BYTE*) counter_definition + counter_definition->ByteLength);
-  }
-
-  /* If we get here, the uptime value was not found. */
-  uv__free(malloced_buffer);
-  *uptime = 0;
-  return UV_ENOSYS;
-
- internalError:
-  uv__free(malloced_buffer);
-  *uptime = 0;
-  return UV_EIO;
-}
-
-
-int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
-  uv_cpu_info_t* cpu_infos;
-  SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
-  DWORD sppi_size;
-  SYSTEM_INFO system_info;
-  DWORD cpu_count, i;
-  NTSTATUS status;
-  ULONG result_size;
-  int err;
-  uv_cpu_info_t* cpu_info;
-
-  cpu_infos = NULL;
-  cpu_count = 0;
-  sppi = NULL;
-
-  uv__once_init();
-
-  GetSystemInfo(&system_info);
-  cpu_count = system_info.dwNumberOfProcessors;
-
-  cpu_infos = (uv_cpu_info_t*)uv__calloc(cpu_count, sizeof *cpu_infos);
-  if (cpu_infos == NULL) {
-    err = ERROR_OUTOFMEMORY;
-    goto error;
-  }
-
-  sppi_size = cpu_count * sizeof(*sppi);
-  sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*)uv__malloc(sppi_size);
-  if (sppi == NULL) {
-    err = ERROR_OUTOFMEMORY;
-    goto error;
-  }
-
-  status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation,
-                                     sppi,
-                                     sppi_size,
-                                     &result_size);
-  if (!NT_SUCCESS(status)) {
-    err = pRtlNtStatusToDosError(status);
-    goto error;
-  }
-
-  assert(result_size == sppi_size);
-
-  for (i = 0; i < cpu_count; i++) {
-    WCHAR key_name[128];
-    HKEY processor_key;
-    DWORD cpu_speed;
-    DWORD cpu_speed_size = sizeof(cpu_speed);
-    WCHAR cpu_brand[256];
-    DWORD cpu_brand_size = sizeof(cpu_brand);
-    size_t len;
-
-    len = _snwprintf(key_name,
-                     ARRAY_SIZE(key_name),
-                     L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%d",
-                     i);
-
-    assert(len > 0 && len < ARRAY_SIZE(key_name));
-
-    err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-                        key_name,
-                        0,
-                        KEY_QUERY_VALUE,
-                        &processor_key);
-    if (err != ERROR_SUCCESS) {
-      goto error;
-    }
-
-    err = RegQueryValueExW(processor_key,
-                           L"~MHz",
-                           NULL,
-                           NULL,
-                           (BYTE*)&cpu_speed,
-                           &cpu_speed_size);
-    if (err != ERROR_SUCCESS) {
-      RegCloseKey(processor_key);
-      goto error;
-    }
-
-    err = RegQueryValueExW(processor_key,
-                           L"ProcessorNameString",
-                           NULL,
-                           NULL,
-                           (BYTE*)&cpu_brand,
-                           &cpu_brand_size);
-    RegCloseKey(processor_key);
-    if (err != ERROR_SUCCESS)
-      goto error;
-
-    cpu_info = &cpu_infos[i];
-    cpu_info->speed = cpu_speed;
-    cpu_info->cpu_times.user = sppi[i].UserTime.QuadPart / 10000;
-    cpu_info->cpu_times.sys = (sppi[i].KernelTime.QuadPart -
-        sppi[i].IdleTime.QuadPart) / 10000;
-    cpu_info->cpu_times.idle = sppi[i].IdleTime.QuadPart / 10000;
-    cpu_info->cpu_times.irq = sppi[i].InterruptTime.QuadPart / 10000;
-    cpu_info->cpu_times.nice = 0;
-
-    uv__convert_utf16_to_utf8(cpu_brand,
-                              cpu_brand_size / sizeof(WCHAR),
-                              &(cpu_info->model));
-  }
-
-  uv__free(sppi);
-
-  *cpu_count_ptr = cpu_count;
-  *cpu_infos_ptr = cpu_infos;
-
-  return 0;
-
- error:
-  if (cpu_infos != NULL) {
-    /* This is safe because the cpu_infos array is zeroed on allocation. */
-    for (i = 0; i < cpu_count; i++)
-      uv__free(cpu_infos[i].model);
-  }
-
-  uv__free(cpu_infos);
-  uv__free(sppi);
-
-  return uv_translate_sys_error(err);
-}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
-  int i;
-
-  for (i = 0; i < count; i++) {
-    uv__free(cpu_infos[i].model);
-  }
-
-  uv__free(cpu_infos);
-}
-
-
-static int is_windows_version_or_greater(DWORD os_major,
-                                         DWORD os_minor,
-                                         WORD service_pack_major,
-                                         WORD service_pack_minor) {
-  OSVERSIONINFOEX osvi;
-  DWORDLONG condition_mask = 0;
-  int op = VER_GREATER_EQUAL;
-
-  /* Initialize the OSVERSIONINFOEX structure. */
-  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
-  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-  osvi.dwMajorVersion = os_major;
-  osvi.dwMinorVersion = os_minor;
-  osvi.wServicePackMajor = service_pack_major;
-  osvi.wServicePackMinor = service_pack_minor;
-
-  /* Initialize the condition mask. */
-  VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op);
-  VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op);
-  VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op);
-  VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op);
-
-  /* Perform the test. */
-  return (int) VerifyVersionInfo(
-    &osvi,
-    VER_MAJORVERSION | VER_MINORVERSION |
-    VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
-    condition_mask);
-}
-
-
-static int address_prefix_match(int family,
-                                struct sockaddr* address,
-                                struct sockaddr* prefix_address,
-                                int prefix_len) {
-  uint8_t* address_data;
-  uint8_t* prefix_address_data;
-  int i;
-
-  assert(address->sa_family == family);
-  assert(prefix_address->sa_family == family);
-
-  if (family == AF_INET6) {
-    address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr);
-    prefix_address_data =
-      (uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr);
-  } else {
-    address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr);
-    prefix_address_data =
-      (uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr);
-  }
-
-  for (i = 0; i < prefix_len >> 3; i++) {
-    if (address_data[i] != prefix_address_data[i])
-      return 0;
-  }
-
-  if (prefix_len % 8)
-    return prefix_address_data[i] ==
-      (address_data[i] & (0xff << (8 - prefix_len % 8)));
-
-  return 1;
-}
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
-    int* count_ptr) {
-  IP_ADAPTER_ADDRESSES* win_address_buf;
-  ULONG win_address_buf_size;
-  IP_ADAPTER_ADDRESSES* adapter;
-
-  uv_interface_address_t* uv_address_buf;
-  char* name_buf;
-  size_t uv_address_buf_size;
-  uv_interface_address_t* uv_address;
-
-  int count;
-
-  int is_vista_or_greater;
-  ULONG flags;
-
-  *addresses_ptr = NULL;
-  *count_ptr = 0;
-
-  is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0);
-  if (is_vista_or_greater) {
-    flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
-      GAA_FLAG_SKIP_DNS_SERVER;
-  } else {
-    /* We need at least XP SP1. */
-    if (!is_windows_version_or_greater(5, 1, 1, 0))
-      return UV_ENOTSUP;
-
-    flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
-      GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX;
-  }
-
-
-  /* Fetch the size of the adapters reported by windows, and then get the list
-   * itself. */
-  win_address_buf_size = 0;
-  win_address_buf = NULL;
-
-  for (;;) {
-    ULONG r;
-
-    /* If win_address_buf is 0, then GetAdaptersAddresses will fail with.
-     * ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in
-     * win_address_buf_size. */
-    r = GetAdaptersAddresses(AF_UNSPEC,
-                             flags,
-                             NULL,
-                             win_address_buf,
-                             &win_address_buf_size);
-
-    if (r == ERROR_SUCCESS)
-      break;
-
-    uv__free(win_address_buf);
-
-    switch (r) {
-      case ERROR_BUFFER_OVERFLOW:
-        /* This happens when win_address_buf is NULL or too small to hold all
-         * adapters. */
-        win_address_buf =
-            (IP_ADAPTER_ADDRESSES*)uv__malloc(win_address_buf_size);
-        if (win_address_buf == NULL)
-          return UV_ENOMEM;
-
-        continue;
-
-      case ERROR_NO_DATA: {
-        /* No adapters were found. */
-        uv_address_buf = (uv_interface_address_t*)uv__malloc(1);
-        if (uv_address_buf == NULL)
-          return UV_ENOMEM;
-
-        *count_ptr = 0;
-        *addresses_ptr = uv_address_buf;
-
-        return 0;
-      }
-
-      case ERROR_ADDRESS_NOT_ASSOCIATED:
-        return UV_EAGAIN;
-
-      case ERROR_INVALID_PARAMETER:
-        /* MSDN says:
-         *   "This error is returned for any of the following conditions: the
-         *   SizePointer parameter is NULL, the Address parameter is not
-         *   AF_INET, AF_INET6, or AF_UNSPEC, or the address information for
-         *   the parameters requested is greater than ULONG_MAX."
-         * Since the first two conditions are not met, it must be that the
-         * adapter data is too big.
-         */
-        return UV_ENOBUFS;
-
-      default:
-        /* Other (unspecified) errors can happen, but we don't have any special
-         * meaning for them. */
-        assert(r != ERROR_SUCCESS);
-        return uv_translate_sys_error(r);
-    }
-  }
-
-  /* Count the number of enabled interfaces and compute how much space is
-   * needed to store their info. */
-  count = 0;
-  uv_address_buf_size = 0;
-
-  for (adapter = win_address_buf;
-       adapter != NULL;
-       adapter = adapter->Next) {
-    IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
-    int name_size;
-
-    /* Interfaces that are not 'up' should not be reported. Also skip
-     * interfaces that have no associated unicast address, as to avoid
-     * allocating space for the name for this interface. */
-    if (adapter->OperStatus != IfOperStatusUp ||
-        adapter->FirstUnicastAddress == NULL)
-      continue;
-
-    /* Compute the size of the interface name. */
-    name_size = WideCharToMultiByte(CP_UTF8,
-                                    0,
-                                    adapter->FriendlyName,
-                                    -1,
-                                    NULL,
-                                    0,
-                                    NULL,
-                                    FALSE);
-    if (name_size <= 0) {
-      uv__free(win_address_buf);
-      return uv_translate_sys_error(GetLastError());
-    }
-    uv_address_buf_size += name_size;
-
-    /* Count the number of addresses associated with this interface, and
-     * compute the size. */
-    for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
-                           adapter->FirstUnicastAddress;
-         unicast_address != NULL;
-         unicast_address = unicast_address->Next) {
-      count++;
-      uv_address_buf_size += sizeof(uv_interface_address_t);
-    }
-  }
-
-  /* Allocate space to store interface data plus adapter names. */
-  uv_address_buf = (uv_interface_address_t*)uv__malloc(uv_address_buf_size);
-  if (uv_address_buf == NULL) {
-    uv__free(win_address_buf);
-    return UV_ENOMEM;
-  }
-
-  /* Compute the start of the uv_interface_address_t array, and the place in
-   * the buffer where the interface names will be stored. */
-  uv_address = uv_address_buf;
-  name_buf = (char*) (uv_address_buf + count);
-
-  /* Fill out the output buffer. */
-  for (adapter = win_address_buf;
-       adapter != NULL;
-       adapter = adapter->Next) {
-    IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
-    int name_size;
-    size_t max_name_size;
-
-    if (adapter->OperStatus != IfOperStatusUp ||
-        adapter->FirstUnicastAddress == NULL)
-      continue;
-
-    /* Convert the interface name to UTF8. */
-    max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;
-    if (max_name_size > (size_t) INT_MAX)
-      max_name_size = INT_MAX;
-    name_size = WideCharToMultiByte(CP_UTF8,
-                                    0,
-                                    adapter->FriendlyName,
-                                    -1,
-                                    name_buf,
-                                    (int) max_name_size,
-                                    NULL,
-                                    FALSE);
-    if (name_size <= 0) {
-      uv__free(win_address_buf);
-      uv__free(uv_address_buf);
-      return uv_translate_sys_error(GetLastError());
-    }
-
-    /* Add an uv_interface_address_t element for every unicast address. */
-    for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
-                           adapter->FirstUnicastAddress;
-         unicast_address != NULL;
-         unicast_address = unicast_address->Next) {
-      struct sockaddr* sa;
-      ULONG prefix_len;
-
-      sa = unicast_address->Address.lpSockaddr;
-
-      /* XP has no OnLinkPrefixLength field. */
-      if (is_vista_or_greater) {
-        prefix_len =
-          ((IP_ADAPTER_UNICAST_ADDRESS_LH*) unicast_address)->OnLinkPrefixLength;
-      } else {
-        /* Prior to Windows Vista the FirstPrefix pointed to the list with
-         * single prefix for each IP address assigned to the adapter.
-         * Order of FirstPrefix does not match order of FirstUnicastAddress,
-         * so we need to find corresponding prefix.
-         */
-        IP_ADAPTER_PREFIX* prefix;
-        prefix_len = 0;
-
-        for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) {
-          /* We want the longest matching prefix. */
-          if (prefix->Address.lpSockaddr->sa_family != sa->sa_family ||
-              prefix->PrefixLength <= prefix_len)
-            continue;
-
-          if (address_prefix_match(sa->sa_family, sa,
-              prefix->Address.lpSockaddr, prefix->PrefixLength)) {
-            prefix_len = prefix->PrefixLength;
-          }
-        }
-
-        /* If there is no matching prefix information, return a single-host
-         * subnet mask (e.g. 255.255.255.255 for IPv4).
-         */
-        if (!prefix_len)
-          prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32;
-      }
-
-      memset(uv_address, 0, sizeof *uv_address);
-
-      uv_address->name = name_buf;
-
-      if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) {
-        memcpy(uv_address->phys_addr,
-               adapter->PhysicalAddress,
-               sizeof(uv_address->phys_addr));
-      }
-
-      uv_address->is_internal =
-          (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
-
-      if (sa->sa_family == AF_INET6) {
-        uv_address->address.address6 = *((struct sockaddr_in6 *) sa);
-
-        uv_address->netmask.netmask6.sin6_family = AF_INET6;
-        memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3);
-        /* This check ensures that we don't write past the size of the data. */
-        if (prefix_len % 8) {
-          uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] =
-              0xff << (8 - prefix_len % 8);
-        }
-
-      } else {
-        uv_address->address.address4 = *((struct sockaddr_in *) sa);
-
-        uv_address->netmask.netmask4.sin_family = AF_INET;
-        uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ?
-            htonl(0xffffffff << (32 - prefix_len)) : 0;
-      }
-
-      uv_address++;
-    }
-
-    name_buf += name_size;
-  }
-
-  uv__free(win_address_buf);
-
-  *addresses_ptr = uv_address_buf;
-  *count_ptr = count;
-
-  return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
-    int count) {
-  uv__free(addresses);
-}
-
-
-int uv_getrusage(uv_rusage_t *uv_rusage) {
-  FILETIME createTime, exitTime, kernelTime, userTime;
-  SYSTEMTIME kernelSystemTime, userSystemTime;
-  PROCESS_MEMORY_COUNTERS memCounters;
-  IO_COUNTERS ioCounters;
-  int ret;
-
-  ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
-  if (ret == 0) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime);
-  if (ret == 0) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  ret = FileTimeToSystemTime(&userTime, &userSystemTime);
-  if (ret == 0) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  ret = GetProcessMemoryInfo(GetCurrentProcess(),
-                             &memCounters,
-                             sizeof(memCounters));
-  if (ret == 0) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  ret = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
-  if (ret == 0) {
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  memset(uv_rusage, 0, sizeof(*uv_rusage));
-
-  uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 +
-                               userSystemTime.wMinute * 60 +
-                               userSystemTime.wSecond;
-  uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000;
-
-  uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 +
-                               kernelSystemTime.wMinute * 60 +
-                               kernelSystemTime.wSecond;
-  uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000;
-
-  uv_rusage->ru_majflt = (uint64_t) memCounters.PageFaultCount;
-  uv_rusage->ru_maxrss = (uint64_t) memCounters.PeakWorkingSetSize / 1024;
-
-  uv_rusage->ru_oublock = (uint64_t) ioCounters.WriteOperationCount;
-  uv_rusage->ru_inblock = (uint64_t) ioCounters.ReadOperationCount;
-
-  return 0;
-}
-
-
-int uv_os_homedir(char* buffer, size_t* size) {
-  uv_passwd_t pwd;
-  size_t len;
-  int r;
-
-  /* Check if the USERPROFILE environment variable is set first. The task of
-     performing input validation on buffer and size is taken care of by
-     uv_os_getenv(). */
-  r = uv_os_getenv("USERPROFILE", buffer, size);
-
-  /* Don't return an error if USERPROFILE was not found. */
-  if (r != UV_ENOENT)
-    return r;
-
-  /* USERPROFILE is not set, so call uv__getpwuid_r() */
-  r = uv__getpwuid_r(&pwd);
-
-  if (r != 0) {
-    return r;
-  }
-
-  len = strlen(pwd.homedir);
-
-  if (len >= *size) {
-    *size = len + 1;
-    uv_os_free_passwd(&pwd);
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, pwd.homedir, len + 1);
-  *size = len;
-  uv_os_free_passwd(&pwd);
-
-  return 0;
-}
-
-
-int uv_os_tmpdir(char* buffer, size_t* size) {
-  wchar_t path[MAX_PATH + 1];
-  DWORD bufsize;
-  size_t len;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  len = GetTempPathW(MAX_PATH + 1, path);
-
-  if (len == 0) {
-    return uv_translate_sys_error(GetLastError());
-  } else if (len > MAX_PATH + 1) {
-    /* This should not be possible */
-    return UV_EIO;
-  }
-
-  /* The returned directory should not have a trailing slash, unless it points
-   * at a drive root, like c:\. Remove it if needed. */
-  if (path[len - 1] == L'\\' &&
-      !(len == 3 && path[1] == L':')) {
-    len--;
-    path[len] = L'\0';
-  }
-
-  /* Check how much space we need */
-  bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
-
-  if (bufsize == 0) {
-    return uv_translate_sys_error(GetLastError());
-  } else if (bufsize > *size) {
-    *size = bufsize;
-    return UV_ENOBUFS;
-  }
-
-  /* Convert to UTF-8 */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                path,
-                                -1,
-                                buffer,
-                                *size,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  *size = bufsize - 1;
-  return 0;
-}
-
-
-void uv_os_free_passwd(uv_passwd_t* pwd) {
-  if (pwd == NULL)
-    return;
-
-  uv__free(pwd->username);
-  uv__free(pwd->homedir);
-  pwd->username = NULL;
-  pwd->homedir = NULL;
-}
-
-
-/*
- * Converts a UTF-16 string into a UTF-8 one. The resulting string is
- * null-terminated.
- *
- * If utf16 is null terminated, utf16len can be set to -1, otherwise it must
- * be specified.
- */
-int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {
-  DWORD bufsize;
-
-  if (utf16 == NULL)
-    return UV_EINVAL;
-
-  /* Check how much space we need */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                utf16,
-                                utf16len,
-                                NULL,
-                                0,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  /* Allocate the destination buffer adding an extra byte for the terminating
-   * NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so
-   * we do it ourselves always, just in case. */
-  *utf8 = (char*)uv__malloc(bufsize + 1);
-
-  if (*utf8 == NULL)
-    return UV_ENOMEM;
-
-  /* Convert to UTF-8 */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                utf16,
-                                utf16len,
-                                *utf8,
-                                bufsize,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0) {
-    uv__free(*utf8);
-    *utf8 = NULL;
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  (*utf8)[bufsize] = '\0';
-  return 0;
-}
-
-
-/*
- * Converts a UTF-8 string into a UTF-16 one. The resulting string is
- * null-terminated.
- *
- * If utf8 is null terminated, utf8len can be set to -1, otherwise it must
- * be specified.
- */
-int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {
-  int bufsize;
-
-  if (utf8 == NULL)
-    return UV_EINVAL;
-
-  /* Check how much space we need */
-  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0);
-
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  /* Allocate the destination buffer adding an extra byte for the terminating
-   * NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so
-   * we do it ourselves always, just in case. */
-  *utf16 = (WCHAR*)uv__malloc(sizeof(WCHAR) * (bufsize + 1));
-
-  if (*utf16 == NULL)
-    return UV_ENOMEM;
-
-  /* Convert to UTF-16 */
-  bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
-
-  if (bufsize == 0) {
-    uv__free(*utf16);
-    *utf16 = NULL;
-    return uv_translate_sys_error(GetLastError());
-  }
-
-  (*utf16)[bufsize] = '\0';
-  return 0;
-}
-
-
-int uv__getpwuid_r(uv_passwd_t* pwd) {
-  HANDLE token;
-  wchar_t username[UNLEN + 1];
-  wchar_t path[MAX_PATH];
-  DWORD bufsize;
-  int r;
-
-  if (pwd == NULL)
-    return UV_EINVAL;
-
-  /* Get the home directory using GetUserProfileDirectoryW() */
-  if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  bufsize = ARRAY_SIZE(path);
-  if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
-    r = GetLastError();
-    CloseHandle(token);
-
-    /* This should not be possible */
-    if (r == ERROR_INSUFFICIENT_BUFFER)
-      return UV_ENOMEM;
-
-    return uv_translate_sys_error(r);
-  }
-
-  CloseHandle(token);
-
-  /* Get the username using GetUserNameW() */
-  bufsize = ARRAY_SIZE(username);
-  if (!GetUserNameW(username, &bufsize)) {
-    r = GetLastError();
-
-    /* This should not be possible */
-    if (r == ERROR_INSUFFICIENT_BUFFER)
-      return UV_ENOMEM;
-
-    return uv_translate_sys_error(r);
-  }
-
-  pwd->homedir = NULL;
-  r = uv__convert_utf16_to_utf8(path, -1, &pwd->homedir);
-
-  if (r != 0)
-    return r;
-
-  pwd->username = NULL;
-  r = uv__convert_utf16_to_utf8(username, -1, &pwd->username);
-
-  if (r != 0) {
-    uv__free(pwd->homedir);
-    return r;
-  }
-
-  pwd->shell = NULL;
-  pwd->uid = -1;
-  pwd->gid = -1;
-
-  return 0;
-}
-
-
-int uv_os_get_passwd(uv_passwd_t* pwd) {
-  return uv__getpwuid_r(pwd);
-}
-
-
-int uv_os_getenv(const char* name, char* buffer, size_t* size) {
-  wchar_t var[MAX_ENV_VAR_LENGTH];
-  wchar_t* name_w;
-  DWORD bufsize;
-  size_t len;
-  int r;
-
-  if (name == NULL || buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
-
-  if (r != 0)
-    return r;
-
-  len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH);
-  uv__free(name_w);
-  assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */
-
-  if (len == 0) {
-    r = GetLastError();
-
-    if (r == ERROR_ENVVAR_NOT_FOUND)
-      return UV_ENOENT;
-
-    return uv_translate_sys_error(r);
-  }
-
-  /* Check how much space we need */
-  bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
-
-  if (bufsize == 0) {
-    return uv_translate_sys_error(GetLastError());
-  } else if (bufsize > *size) {
-    *size = bufsize;
-    return UV_ENOBUFS;
-  }
-
-  /* Convert to UTF-8 */
-  bufsize = WideCharToMultiByte(CP_UTF8,
-                                0,
-                                var,
-                                -1,
-                                buffer,
-                                *size,
-                                NULL,
-                                NULL);
-
-  if (bufsize == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  *size = bufsize - 1;
-  return 0;
-}
-
-
-int uv_os_setenv(const char* name, const char* value) {
-  wchar_t* name_w;
-  wchar_t* value_w;
-  int r;
-
-  if (name == NULL || value == NULL)
-    return UV_EINVAL;
-
-  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
-
-  if (r != 0)
-    return r;
-
-  r = uv__convert_utf8_to_utf16(value, -1, &value_w);
-
-  if (r != 0) {
-    uv__free(name_w);
-    return r;
-  }
-
-  r = SetEnvironmentVariableW(name_w, value_w);
-  uv__free(name_w);
-  uv__free(value_w);
-
-  if (r == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  return 0;
-}
-
-
-int uv_os_unsetenv(const char* name) {
-  wchar_t* name_w;
-  int r;
-
-  if (name == NULL)
-    return UV_EINVAL;
-
-  r = uv__convert_utf8_to_utf16(name, -1, &name_w);
-
-  if (r != 0)
-    return r;
-
-  r = SetEnvironmentVariableW(name_w, NULL);
-  uv__free(name_w);
-
-  if (r == 0)
-    return uv_translate_sys_error(GetLastError());
-
-  return 0;
-}
-
-
-int uv_os_gethostname(char* buffer, size_t* size) {
-  char buf[UV_MAXHOSTNAMESIZE];
-  size_t len;
-
-  if (buffer == NULL || size == NULL || *size == 0)
-    return UV_EINVAL;
-
-  uv__once_init(); /* Initialize winsock */
-
-  if (gethostname(buf, sizeof(buf)) != 0)
-    return uv_translate_sys_error(WSAGetLastError());
-
-  buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
-  len = strlen(buf);
-
-  if (len >= *size) {
-    *size = len + 1;
-    return UV_ENOBUFS;
-  }
-
-  memcpy(buffer, buf, len + 1);
-  *size = len;
-  return 0;
-}
-
-
-static int uv__get_handle(uv_pid_t pid, int access, HANDLE* handle) {
-  int r;
-
-  if (pid == 0)
-    *handle = GetCurrentProcess();
-  else
-    *handle = OpenProcess(access, FALSE, pid);
-
-  if (*handle == NULL) {
-    r = GetLastError();
-
-    if (r == ERROR_INVALID_PARAMETER)
-      return UV_ESRCH;
-    else
-      return uv_translate_sys_error(r);
-  }
-
-  return 0;
-}
-
-
-int uv_os_getpriority(uv_pid_t pid, int* priority) {
-  HANDLE handle;
-  int r;
-
-  if (priority == NULL)
-    return UV_EINVAL;
-
-  r = uv__get_handle(pid, PROCESS_QUERY_LIMITED_INFORMATION, &handle);
-
-  if (r != 0)
-    return r;
-
-  r = GetPriorityClass(handle);
-
-  if (r == 0) {
-    r = uv_translate_sys_error(GetLastError());
-  } else {
-    /* Map Windows priority classes to Unix nice values. */
-    if (r == REALTIME_PRIORITY_CLASS)
-      *priority = UV_PRIORITY_HIGHEST;
-    else if (r == HIGH_PRIORITY_CLASS)
-      *priority = UV_PRIORITY_HIGH;
-    else if (r == ABOVE_NORMAL_PRIORITY_CLASS)
-      *priority = UV_PRIORITY_ABOVE_NORMAL;
-    else if (r == NORMAL_PRIORITY_CLASS)
-      *priority = UV_PRIORITY_NORMAL;
-    else if (r == BELOW_NORMAL_PRIORITY_CLASS)
-      *priority = UV_PRIORITY_BELOW_NORMAL;
-    else  /* IDLE_PRIORITY_CLASS */
-      *priority = UV_PRIORITY_LOW;
-
-    r = 0;
-  }
-
-  CloseHandle(handle);
-  return r;
-}
-
-
-int uv_os_setpriority(uv_pid_t pid, int priority) {
-  HANDLE handle;
-  int priority_class;
-  int r;
-
-  /* Map Unix nice values to Windows priority classes. */
-  if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
-    return UV_EINVAL;
-  else if (priority < UV_PRIORITY_HIGH)
-    priority_class = REALTIME_PRIORITY_CLASS;
-  else if (priority < UV_PRIORITY_ABOVE_NORMAL)
-    priority_class = HIGH_PRIORITY_CLASS;
-  else if (priority < UV_PRIORITY_NORMAL)
-    priority_class = ABOVE_NORMAL_PRIORITY_CLASS;
-  else if (priority < UV_PRIORITY_BELOW_NORMAL)
-    priority_class = NORMAL_PRIORITY_CLASS;
-  else if (priority < UV_PRIORITY_LOW)
-    priority_class = BELOW_NORMAL_PRIORITY_CLASS;
-  else
-    priority_class = IDLE_PRIORITY_CLASS;
-
-  r = uv__get_handle(pid, PROCESS_SET_INFORMATION, &handle);
-
-  if (r != 0)
-    return r;
-
-  if (SetPriorityClass(handle, priority_class) == 0)
-    r = uv_translate_sys_error(GetLastError());
-
-  CloseHandle(handle);
-  return r;
-}
-
-
-int uv_os_uname(uv_utsname_t* buffer) {
-  /* Implementation loosely based on
-     https://github.com/gagern/gnulib/blob/master/lib/uname.c */
-  OSVERSIONINFOW os_info;
-  SYSTEM_INFO system_info;
-  HKEY registry_key;
-  WCHAR product_name_w[256];
-  DWORD product_name_w_size;
-  int version_size;
-  int processor_level;
-  int r;
-
-  if (buffer == NULL)
-    return UV_EINVAL;
-
-  uv__once_init();
-  os_info.dwOSVersionInfoSize = sizeof(os_info);
-  os_info.szCSDVersion[0] = L'\0';
-
-  /* Try calling RtlGetVersion(), and fall back to the deprecated GetVersionEx()
-     if RtlGetVersion() is not available. */
-  if (pRtlGetVersion) {
-    pRtlGetVersion(&os_info);
-  } else {
-    /* Silence GetVersionEx() deprecation warning. */
-    #pragma warning(suppress : 4996)
-    if (GetVersionExW(&os_info) == 0) {
-      r = uv_translate_sys_error(GetLastError());
-      goto error;
-    }
-  }
-
-  /* Populate the version field. */
-  version_size = 0;
-  r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-                    L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
-                    0,
-                    KEY_QUERY_VALUE,
-                    &registry_key);
-
-  if (r == ERROR_SUCCESS) {
-    product_name_w_size = sizeof(product_name_w);
-    r = RegGetValueW(registry_key,
-                     NULL,
-                     L"ProductName",
-                     RRF_RT_REG_SZ,
-                     NULL,
-                     (PVOID) product_name_w,
-                     &product_name_w_size);
-    RegCloseKey(registry_key);
-
-    if (r == ERROR_SUCCESS) {
-      version_size = WideCharToMultiByte(CP_UTF8,
-                                         0,
-                                         product_name_w,
-                                         -1,
-                                         buffer->version,
-                                         sizeof(buffer->version),
-                                         NULL,
-                                         NULL);
-      if (version_size == 0) {
-        r = uv_translate_sys_error(GetLastError());
-        goto error;
-      }
-    }
-  }
-
-  /* Append service pack information to the version if present. */
-  if (os_info.szCSDVersion[0] != L'\0') {
-    if (version_size > 0)
-      buffer->version[version_size - 1] = ' ';
-
-    if (WideCharToMultiByte(CP_UTF8,
-                            0,
-                            os_info.szCSDVersion,
-                            -1,
-                            buffer->version + version_size,
-                            sizeof(buffer->version) - version_size,
-                            NULL,
-                            NULL) == 0) {
-      r = uv_translate_sys_error(GetLastError());
-      goto error;
-    }
-  }
-
-  /* Populate the sysname field. */
-#ifdef __MINGW32__
-  r = snprintf(buffer->sysname,
-               sizeof(buffer->sysname),
-               "MINGW32_NT-%u.%u",
-               (unsigned int) os_info.dwMajorVersion,
-               (unsigned int) os_info.dwMinorVersion);
-  assert(r < sizeof(buffer->sysname));
-#else
-  uv__strscpy(buffer->sysname, "Windows_NT", sizeof(buffer->sysname));
-#endif
-
-  /* Populate the release field. */
-  r = snprintf(buffer->release,
-               sizeof(buffer->release),
-               "%d.%d.%d",
-               (unsigned int) os_info.dwMajorVersion,
-               (unsigned int) os_info.dwMinorVersion,
-               (unsigned int) os_info.dwBuildNumber);
-  assert(r < sizeof(buffer->release));
-
-  /* Populate the machine field. */
-  GetSystemInfo(&system_info);
-
-  switch (system_info.wProcessorArchitecture) {
-    case PROCESSOR_ARCHITECTURE_AMD64:
-      uv__strscpy(buffer->machine, "x86_64", sizeof(buffer->machine));
-      break;
-    case PROCESSOR_ARCHITECTURE_IA64:
-      uv__strscpy(buffer->machine, "ia64", sizeof(buffer->machine));
-      break;
-    case PROCESSOR_ARCHITECTURE_INTEL:
-      uv__strscpy(buffer->machine, "i386", sizeof(buffer->machine));
-
-      if (system_info.wProcessorLevel > 3) {
-        processor_level = system_info.wProcessorLevel < 6 ?
-                          system_info.wProcessorLevel : 6;
-        buffer->machine[1] = '0' + processor_level;
-      }
-
-      break;
-    case PROCESSOR_ARCHITECTURE_IA32_ON_WIN64:
-      uv__strscpy(buffer->machine, "i686", sizeof(buffer->machine));
-      break;
-    case PROCESSOR_ARCHITECTURE_MIPS:
-      uv__strscpy(buffer->machine, "mips", sizeof(buffer->machine));
-      break;
-    case PROCESSOR_ARCHITECTURE_ALPHA:
-    case PROCESSOR_ARCHITECTURE_ALPHA64:
-      uv__strscpy(buffer->machine, "alpha", sizeof(buffer->machine));
-      break;
-    case PROCESSOR_ARCHITECTURE_PPC:
-      uv__strscpy(buffer->machine, "powerpc", sizeof(buffer->machine));
-      break;
-    case PROCESSOR_ARCHITECTURE_SHX:
-      uv__strscpy(buffer->machine, "sh", sizeof(buffer->machine));
-      break;
-    case PROCESSOR_ARCHITECTURE_ARM:
-      uv__strscpy(buffer->machine, "arm", sizeof(buffer->machine));
-      break;
-    default:
-      uv__strscpy(buffer->machine, "unknown", sizeof(buffer->machine));
-      break;
-  }
-
-  return 0;
-
-error:
-  buffer->sysname[0] = '\0';
-  buffer->release[0] = '\0';
-  buffer->version[0] = '\0';
-  buffer->machine[0] = '\0';
-  return r;
-}
-
-int uv_gettimeofday(uv_timeval64_t* tv) {
-  /* Based on https://doxygen.postgresql.org/gettimeofday_8c_source.html */
-  const uint64_t epoch = (uint64_t) 116444736000000000ULL;
-  FILETIME file_time;
-  ULARGE_INTEGER ularge;
-
-  if (tv == NULL)
-    return UV_EINVAL;
-
-  GetSystemTimeAsFileTime(&file_time);
-  ularge.LowPart = file_time.dwLowDateTime;
-  ularge.HighPart = file_time.dwHighDateTime;
-  tv->tv_sec = (int64_t) ((ularge.QuadPart - epoch) / 10000000L);
-  tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10);
-  return 0;
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/winapi.cpp b/wpiutil/src/main/native/libuv/src/win/winapi.cpp
deleted file mode 100644
index fbbbcee..0000000
--- a/wpiutil/src/main/native/libuv/src/win/winapi.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-
-#include "uv.h"
-#include "internal.h"
-
-
-/* Ntdll function pointers */
-sRtlGetVersion pRtlGetVersion;
-sRtlNtStatusToDosError pRtlNtStatusToDosError;
-sNtDeviceIoControlFile pNtDeviceIoControlFile;
-sNtQueryInformationFile pNtQueryInformationFile;
-sNtSetInformationFile pNtSetInformationFile;
-sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
-sNtQueryDirectoryFile pNtQueryDirectoryFile;
-sNtQuerySystemInformation pNtQuerySystemInformation;
-
-/* Kernel32 function pointers */
-sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
-
-/* Powrprof.dll function pointer */
-sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
-
-/* User32.dll function pointer */
-sSetWinEventHook pSetWinEventHook;
-
-
-void uv_winapi_init(void) {
-  HMODULE ntdll_module;
-  HMODULE powrprof_module;
-  HMODULE user32_module;
-  HMODULE kernel32_module;
-
-  ntdll_module = GetModuleHandleA("ntdll.dll");
-  if (ntdll_module == NULL) {
-    uv_fatal_error(GetLastError(), "GetModuleHandleA");
-  }
-
-  pRtlGetVersion = (sRtlGetVersion) GetProcAddress(ntdll_module,
-                                                   "RtlGetVersion");
-
-  pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(
-      ntdll_module,
-      "RtlNtStatusToDosError");
-  if (pRtlNtStatusToDosError == NULL) {
-    uv_fatal_error(GetLastError(), "GetProcAddress");
-  }
-
-  pNtDeviceIoControlFile = (sNtDeviceIoControlFile) GetProcAddress(
-      ntdll_module,
-      "NtDeviceIoControlFile");
-  if (pNtDeviceIoControlFile == NULL) {
-    uv_fatal_error(GetLastError(), "GetProcAddress");
-  }
-
-  pNtQueryInformationFile = (sNtQueryInformationFile) GetProcAddress(
-      ntdll_module,
-      "NtQueryInformationFile");
-  if (pNtQueryInformationFile == NULL) {
-    uv_fatal_error(GetLastError(), "GetProcAddress");
-  }
-
-  pNtSetInformationFile = (sNtSetInformationFile) GetProcAddress(
-      ntdll_module,
-      "NtSetInformationFile");
-  if (pNtSetInformationFile == NULL) {
-    uv_fatal_error(GetLastError(), "GetProcAddress");
-  }
-
-  pNtQueryVolumeInformationFile = (sNtQueryVolumeInformationFile)
-      GetProcAddress(ntdll_module, "NtQueryVolumeInformationFile");
-  if (pNtQueryVolumeInformationFile == NULL) {
-    uv_fatal_error(GetLastError(), "GetProcAddress");
-  }
-
-  pNtQueryDirectoryFile = (sNtQueryDirectoryFile)
-      GetProcAddress(ntdll_module, "NtQueryDirectoryFile");
-  if (pNtQueryVolumeInformationFile == NULL) {
-    uv_fatal_error(GetLastError(), "GetProcAddress");
-  }
-
-  pNtQuerySystemInformation = (sNtQuerySystemInformation) GetProcAddress(
-      ntdll_module,
-      "NtQuerySystemInformation");
-  if (pNtQuerySystemInformation == NULL) {
-    uv_fatal_error(GetLastError(), "GetProcAddress");
-  }
-
-  kernel32_module = GetModuleHandleA("kernel32.dll");
-  if (kernel32_module == NULL) {
-    uv_fatal_error(GetLastError(), "GetModuleHandleA");
-  }
-
-  pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress(
-      kernel32_module,
-      "GetQueuedCompletionStatusEx");
-
-  powrprof_module = LoadLibraryA("powrprof.dll");
-  if (powrprof_module != NULL) {
-    pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification)
-      GetProcAddress(powrprof_module, "PowerRegisterSuspendResumeNotification");
-  }
-
-  user32_module = LoadLibraryA("user32.dll");
-  if (user32_module != NULL) {
-    pSetWinEventHook = (sSetWinEventHook)
-      GetProcAddress(user32_module, "SetWinEventHook");
-  }
-
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/winapi.h b/wpiutil/src/main/native/libuv/src/win/winapi.h
deleted file mode 100644
index 82c5ed4..0000000
--- a/wpiutil/src/main/native/libuv/src/win/winapi.h
+++ /dev/null
@@ -1,4731 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_WIN_WINAPI_H_
-#define UV_WIN_WINAPI_H_
-
-#include <windows.h>
-
-
-/*
- * Ntdll headers
- */
-#ifndef STATUS_SEVERITY_SUCCESS
-# define STATUS_SEVERITY_SUCCESS 0x0
-#endif
-
-#ifndef STATUS_SEVERITY_INFORMATIONAL
-# define STATUS_SEVERITY_INFORMATIONAL 0x1
-#endif
-
-#ifndef STATUS_SEVERITY_WARNING
-# define STATUS_SEVERITY_WARNING 0x2
-#endif
-
-#ifndef STATUS_SEVERITY_ERROR
-# define STATUS_SEVERITY_ERROR 0x3
-#endif
-
-#ifndef FACILITY_NTWIN32
-# define FACILITY_NTWIN32 0x7
-#endif
-
-#ifndef NT_SUCCESS
-# define NT_SUCCESS(status) (((NTSTATUS) (status)) >= 0)
-#endif
-
-#ifndef NT_INFORMATION
-# define NT_INFORMATION(status) ((((ULONG) (status)) >> 30) == 1)
-#endif
-
-#ifndef NT_WARNING
-# define NT_WARNING(status) ((((ULONG) (status)) >> 30) == 2)
-#endif
-
-#ifndef NT_ERROR
-# define NT_ERROR(status) ((((ULONG) (status)) >> 30) == 3)
-#endif
-
-#ifndef STATUS_SUCCESS
-# define STATUS_SUCCESS ((NTSTATUS) 0x00000000L)
-#endif
-
-#ifndef STATUS_WAIT_0
-# define STATUS_WAIT_0 ((NTSTATUS) 0x00000000L)
-#endif
-
-#ifndef STATUS_WAIT_1
-# define STATUS_WAIT_1 ((NTSTATUS) 0x00000001L)
-#endif
-
-#ifndef STATUS_WAIT_2
-# define STATUS_WAIT_2 ((NTSTATUS) 0x00000002L)
-#endif
-
-#ifndef STATUS_WAIT_3
-# define STATUS_WAIT_3 ((NTSTATUS) 0x00000003L)
-#endif
-
-#ifndef STATUS_WAIT_63
-# define STATUS_WAIT_63 ((NTSTATUS) 0x0000003FL)
-#endif
-
-#ifndef STATUS_ABANDONED
-# define STATUS_ABANDONED ((NTSTATUS) 0x00000080L)
-#endif
-
-#ifndef STATUS_ABANDONED_WAIT_0
-# define STATUS_ABANDONED_WAIT_0 ((NTSTATUS) 0x00000080L)
-#endif
-
-#ifndef STATUS_ABANDONED_WAIT_63
-# define STATUS_ABANDONED_WAIT_63 ((NTSTATUS) 0x000000BFL)
-#endif
-
-#ifndef STATUS_USER_APC
-# define STATUS_USER_APC ((NTSTATUS) 0x000000C0L)
-#endif
-
-#ifndef STATUS_KERNEL_APC
-# define STATUS_KERNEL_APC ((NTSTATUS) 0x00000100L)
-#endif
-
-#ifndef STATUS_ALERTED
-# define STATUS_ALERTED ((NTSTATUS) 0x00000101L)
-#endif
-
-#ifndef STATUS_TIMEOUT
-# define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L)
-#endif
-
-#ifndef STATUS_PENDING
-# define STATUS_PENDING ((NTSTATUS) 0x00000103L)
-#endif
-
-#ifndef STATUS_REPARSE
-# define STATUS_REPARSE ((NTSTATUS) 0x00000104L)
-#endif
-
-#ifndef STATUS_MORE_ENTRIES
-# define STATUS_MORE_ENTRIES ((NTSTATUS) 0x00000105L)
-#endif
-
-#ifndef STATUS_NOT_ALL_ASSIGNED
-# define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106L)
-#endif
-
-#ifndef STATUS_SOME_NOT_MAPPED
-# define STATUS_SOME_NOT_MAPPED ((NTSTATUS) 0x00000107L)
-#endif
-
-#ifndef STATUS_OPLOCK_BREAK_IN_PROGRESS
-# define STATUS_OPLOCK_BREAK_IN_PROGRESS ((NTSTATUS) 0x00000108L)
-#endif
-
-#ifndef STATUS_VOLUME_MOUNTED
-# define STATUS_VOLUME_MOUNTED ((NTSTATUS) 0x00000109L)
-#endif
-
-#ifndef STATUS_RXACT_COMMITTED
-# define STATUS_RXACT_COMMITTED ((NTSTATUS) 0x0000010AL)
-#endif
-
-#ifndef STATUS_NOTIFY_CLEANUP
-# define STATUS_NOTIFY_CLEANUP ((NTSTATUS) 0x0000010BL)
-#endif
-
-#ifndef STATUS_NOTIFY_ENUM_DIR
-# define STATUS_NOTIFY_ENUM_DIR ((NTSTATUS) 0x0000010CL)
-#endif
-
-#ifndef STATUS_NO_QUOTAS_FOR_ACCOUNT
-# define STATUS_NO_QUOTAS_FOR_ACCOUNT ((NTSTATUS) 0x0000010DL)
-#endif
-
-#ifndef STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED
-# define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED ((NTSTATUS) 0x0000010EL)
-#endif
-
-#ifndef STATUS_PAGE_FAULT_TRANSITION
-# define STATUS_PAGE_FAULT_TRANSITION ((NTSTATUS) 0x00000110L)
-#endif
-
-#ifndef STATUS_PAGE_FAULT_DEMAND_ZERO
-# define STATUS_PAGE_FAULT_DEMAND_ZERO ((NTSTATUS) 0x00000111L)
-#endif
-
-#ifndef STATUS_PAGE_FAULT_COPY_ON_WRITE
-# define STATUS_PAGE_FAULT_COPY_ON_WRITE ((NTSTATUS) 0x00000112L)
-#endif
-
-#ifndef STATUS_PAGE_FAULT_GUARD_PAGE
-# define STATUS_PAGE_FAULT_GUARD_PAGE ((NTSTATUS) 0x00000113L)
-#endif
-
-#ifndef STATUS_PAGE_FAULT_PAGING_FILE
-# define STATUS_PAGE_FAULT_PAGING_FILE ((NTSTATUS) 0x00000114L)
-#endif
-
-#ifndef STATUS_CACHE_PAGE_LOCKED
-# define STATUS_CACHE_PAGE_LOCKED ((NTSTATUS) 0x00000115L)
-#endif
-
-#ifndef STATUS_CRASH_DUMP
-# define STATUS_CRASH_DUMP ((NTSTATUS) 0x00000116L)
-#endif
-
-#ifndef STATUS_BUFFER_ALL_ZEROS
-# define STATUS_BUFFER_ALL_ZEROS ((NTSTATUS) 0x00000117L)
-#endif
-
-#ifndef STATUS_REPARSE_OBJECT
-# define STATUS_REPARSE_OBJECT ((NTSTATUS) 0x00000118L)
-#endif
-
-#ifndef STATUS_RESOURCE_REQUIREMENTS_CHANGED
-# define STATUS_RESOURCE_REQUIREMENTS_CHANGED ((NTSTATUS) 0x00000119L)
-#endif
-
-#ifndef STATUS_TRANSLATION_COMPLETE
-# define STATUS_TRANSLATION_COMPLETE ((NTSTATUS) 0x00000120L)
-#endif
-
-#ifndef STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY
-# define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY ((NTSTATUS) 0x00000121L)
-#endif
-
-#ifndef STATUS_NOTHING_TO_TERMINATE
-# define STATUS_NOTHING_TO_TERMINATE ((NTSTATUS) 0x00000122L)
-#endif
-
-#ifndef STATUS_PROCESS_NOT_IN_JOB
-# define STATUS_PROCESS_NOT_IN_JOB ((NTSTATUS) 0x00000123L)
-#endif
-
-#ifndef STATUS_PROCESS_IN_JOB
-# define STATUS_PROCESS_IN_JOB ((NTSTATUS) 0x00000124L)
-#endif
-
-#ifndef STATUS_VOLSNAP_HIBERNATE_READY
-# define STATUS_VOLSNAP_HIBERNATE_READY ((NTSTATUS) 0x00000125L)
-#endif
-
-#ifndef STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY
-# define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY ((NTSTATUS) 0x00000126L)
-#endif
-
-#ifndef STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED
-# define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED ((NTSTATUS) 0x00000127L)
-#endif
-
-#ifndef STATUS_INTERRUPT_STILL_CONNECTED
-# define STATUS_INTERRUPT_STILL_CONNECTED ((NTSTATUS) 0x00000128L)
-#endif
-
-#ifndef STATUS_PROCESS_CLONED
-# define STATUS_PROCESS_CLONED ((NTSTATUS) 0x00000129L)
-#endif
-
-#ifndef STATUS_FILE_LOCKED_WITH_ONLY_READERS
-# define STATUS_FILE_LOCKED_WITH_ONLY_READERS ((NTSTATUS) 0x0000012AL)
-#endif
-
-#ifndef STATUS_FILE_LOCKED_WITH_WRITERS
-# define STATUS_FILE_LOCKED_WITH_WRITERS ((NTSTATUS) 0x0000012BL)
-#endif
-
-#ifndef STATUS_RESOURCEMANAGER_READ_ONLY
-# define STATUS_RESOURCEMANAGER_READ_ONLY ((NTSTATUS) 0x00000202L)
-#endif
-
-#ifndef STATUS_RING_PREVIOUSLY_EMPTY
-# define STATUS_RING_PREVIOUSLY_EMPTY ((NTSTATUS) 0x00000210L)
-#endif
-
-#ifndef STATUS_RING_PREVIOUSLY_FULL
-# define STATUS_RING_PREVIOUSLY_FULL ((NTSTATUS) 0x00000211L)
-#endif
-
-#ifndef STATUS_RING_PREVIOUSLY_ABOVE_QUOTA
-# define STATUS_RING_PREVIOUSLY_ABOVE_QUOTA ((NTSTATUS) 0x00000212L)
-#endif
-
-#ifndef STATUS_RING_NEWLY_EMPTY
-# define STATUS_RING_NEWLY_EMPTY ((NTSTATUS) 0x00000213L)
-#endif
-
-#ifndef STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT
-# define STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT ((NTSTATUS) 0x00000214L)
-#endif
-
-#ifndef STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE
-# define STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE ((NTSTATUS) 0x00000215L)
-#endif
-
-#ifndef STATUS_OPLOCK_HANDLE_CLOSED
-# define STATUS_OPLOCK_HANDLE_CLOSED ((NTSTATUS) 0x00000216L)
-#endif
-
-#ifndef STATUS_WAIT_FOR_OPLOCK
-# define STATUS_WAIT_FOR_OPLOCK ((NTSTATUS) 0x00000367L)
-#endif
-
-#ifndef STATUS_OBJECT_NAME_EXISTS
-# define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000L)
-#endif
-
-#ifndef STATUS_THREAD_WAS_SUSPENDED
-# define STATUS_THREAD_WAS_SUSPENDED ((NTSTATUS) 0x40000001L)
-#endif
-
-#ifndef STATUS_WORKING_SET_LIMIT_RANGE
-# define STATUS_WORKING_SET_LIMIT_RANGE ((NTSTATUS) 0x40000002L)
-#endif
-
-#ifndef STATUS_IMAGE_NOT_AT_BASE
-# define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS) 0x40000003L)
-#endif
-
-#ifndef STATUS_RXACT_STATE_CREATED
-# define STATUS_RXACT_STATE_CREATED ((NTSTATUS) 0x40000004L)
-#endif
-
-#ifndef STATUS_SEGMENT_NOTIFICATION
-# define STATUS_SEGMENT_NOTIFICATION ((NTSTATUS) 0x40000005L)
-#endif
-
-#ifndef STATUS_LOCAL_USER_SESSION_KEY
-# define STATUS_LOCAL_USER_SESSION_KEY ((NTSTATUS) 0x40000006L)
-#endif
-
-#ifndef STATUS_BAD_CURRENT_DIRECTORY
-# define STATUS_BAD_CURRENT_DIRECTORY ((NTSTATUS) 0x40000007L)
-#endif
-
-#ifndef STATUS_SERIAL_MORE_WRITES
-# define STATUS_SERIAL_MORE_WRITES ((NTSTATUS) 0x40000008L)
-#endif
-
-#ifndef STATUS_REGISTRY_RECOVERED
-# define STATUS_REGISTRY_RECOVERED ((NTSTATUS) 0x40000009L)
-#endif
-
-#ifndef STATUS_FT_READ_RECOVERY_FROM_BACKUP
-# define STATUS_FT_READ_RECOVERY_FROM_BACKUP ((NTSTATUS) 0x4000000AL)
-#endif
-
-#ifndef STATUS_FT_WRITE_RECOVERY
-# define STATUS_FT_WRITE_RECOVERY ((NTSTATUS) 0x4000000BL)
-#endif
-
-#ifndef STATUS_SERIAL_COUNTER_TIMEOUT
-# define STATUS_SERIAL_COUNTER_TIMEOUT ((NTSTATUS) 0x4000000CL)
-#endif
-
-#ifndef STATUS_NULL_LM_PASSWORD
-# define STATUS_NULL_LM_PASSWORD ((NTSTATUS) 0x4000000DL)
-#endif
-
-#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH
-# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH ((NTSTATUS) 0x4000000EL)
-#endif
-
-#ifndef STATUS_RECEIVE_PARTIAL
-# define STATUS_RECEIVE_PARTIAL ((NTSTATUS) 0x4000000FL)
-#endif
-
-#ifndef STATUS_RECEIVE_EXPEDITED
-# define STATUS_RECEIVE_EXPEDITED ((NTSTATUS) 0x40000010L)
-#endif
-
-#ifndef STATUS_RECEIVE_PARTIAL_EXPEDITED
-# define STATUS_RECEIVE_PARTIAL_EXPEDITED ((NTSTATUS) 0x40000011L)
-#endif
-
-#ifndef STATUS_EVENT_DONE
-# define STATUS_EVENT_DONE ((NTSTATUS) 0x40000012L)
-#endif
-
-#ifndef STATUS_EVENT_PENDING
-# define STATUS_EVENT_PENDING ((NTSTATUS) 0x40000013L)
-#endif
-
-#ifndef STATUS_CHECKING_FILE_SYSTEM
-# define STATUS_CHECKING_FILE_SYSTEM ((NTSTATUS) 0x40000014L)
-#endif
-
-#ifndef STATUS_FATAL_APP_EXIT
-# define STATUS_FATAL_APP_EXIT ((NTSTATUS) 0x40000015L)
-#endif
-
-#ifndef STATUS_PREDEFINED_HANDLE
-# define STATUS_PREDEFINED_HANDLE ((NTSTATUS) 0x40000016L)
-#endif
-
-#ifndef STATUS_WAS_UNLOCKED
-# define STATUS_WAS_UNLOCKED ((NTSTATUS) 0x40000017L)
-#endif
-
-#ifndef STATUS_SERVICE_NOTIFICATION
-# define STATUS_SERVICE_NOTIFICATION ((NTSTATUS) 0x40000018L)
-#endif
-
-#ifndef STATUS_WAS_LOCKED
-# define STATUS_WAS_LOCKED ((NTSTATUS) 0x40000019L)
-#endif
-
-#ifndef STATUS_LOG_HARD_ERROR
-# define STATUS_LOG_HARD_ERROR ((NTSTATUS) 0x4000001AL)
-#endif
-
-#ifndef STATUS_ALREADY_WIN32
-# define STATUS_ALREADY_WIN32 ((NTSTATUS) 0x4000001BL)
-#endif
-
-#ifndef STATUS_WX86_UNSIMULATE
-# define STATUS_WX86_UNSIMULATE ((NTSTATUS) 0x4000001CL)
-#endif
-
-#ifndef STATUS_WX86_CONTINUE
-# define STATUS_WX86_CONTINUE ((NTSTATUS) 0x4000001DL)
-#endif
-
-#ifndef STATUS_WX86_SINGLE_STEP
-# define STATUS_WX86_SINGLE_STEP ((NTSTATUS) 0x4000001EL)
-#endif
-
-#ifndef STATUS_WX86_BREAKPOINT
-# define STATUS_WX86_BREAKPOINT ((NTSTATUS) 0x4000001FL)
-#endif
-
-#ifndef STATUS_WX86_EXCEPTION_CONTINUE
-# define STATUS_WX86_EXCEPTION_CONTINUE ((NTSTATUS) 0x40000020L)
-#endif
-
-#ifndef STATUS_WX86_EXCEPTION_LASTCHANCE
-# define STATUS_WX86_EXCEPTION_LASTCHANCE ((NTSTATUS) 0x40000021L)
-#endif
-
-#ifndef STATUS_WX86_EXCEPTION_CHAIN
-# define STATUS_WX86_EXCEPTION_CHAIN ((NTSTATUS) 0x40000022L)
-#endif
-
-#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE
-# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE ((NTSTATUS) 0x40000023L)
-#endif
-
-#ifndef STATUS_NO_YIELD_PERFORMED
-# define STATUS_NO_YIELD_PERFORMED ((NTSTATUS) 0x40000024L)
-#endif
-
-#ifndef STATUS_TIMER_RESUME_IGNORED
-# define STATUS_TIMER_RESUME_IGNORED ((NTSTATUS) 0x40000025L)
-#endif
-
-#ifndef STATUS_ARBITRATION_UNHANDLED
-# define STATUS_ARBITRATION_UNHANDLED ((NTSTATUS) 0x40000026L)
-#endif
-
-#ifndef STATUS_CARDBUS_NOT_SUPPORTED
-# define STATUS_CARDBUS_NOT_SUPPORTED ((NTSTATUS) 0x40000027L)
-#endif
-
-#ifndef STATUS_WX86_CREATEWX86TIB
-# define STATUS_WX86_CREATEWX86TIB ((NTSTATUS) 0x40000028L)
-#endif
-
-#ifndef STATUS_MP_PROCESSOR_MISMATCH
-# define STATUS_MP_PROCESSOR_MISMATCH ((NTSTATUS) 0x40000029L)
-#endif
-
-#ifndef STATUS_HIBERNATED
-# define STATUS_HIBERNATED ((NTSTATUS) 0x4000002AL)
-#endif
-
-#ifndef STATUS_RESUME_HIBERNATION
-# define STATUS_RESUME_HIBERNATION ((NTSTATUS) 0x4000002BL)
-#endif
-
-#ifndef STATUS_FIRMWARE_UPDATED
-# define STATUS_FIRMWARE_UPDATED ((NTSTATUS) 0x4000002CL)
-#endif
-
-#ifndef STATUS_DRIVERS_LEAKING_LOCKED_PAGES
-# define STATUS_DRIVERS_LEAKING_LOCKED_PAGES ((NTSTATUS) 0x4000002DL)
-#endif
-
-#ifndef STATUS_MESSAGE_RETRIEVED
-# define STATUS_MESSAGE_RETRIEVED ((NTSTATUS) 0x4000002EL)
-#endif
-
-#ifndef STATUS_SYSTEM_POWERSTATE_TRANSITION
-# define STATUS_SYSTEM_POWERSTATE_TRANSITION ((NTSTATUS) 0x4000002FL)
-#endif
-
-#ifndef STATUS_ALPC_CHECK_COMPLETION_LIST
-# define STATUS_ALPC_CHECK_COMPLETION_LIST ((NTSTATUS) 0x40000030L)
-#endif
-
-#ifndef STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION
-# define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION ((NTSTATUS) 0x40000031L)
-#endif
-
-#ifndef STATUS_ACCESS_AUDIT_BY_POLICY
-# define STATUS_ACCESS_AUDIT_BY_POLICY ((NTSTATUS) 0x40000032L)
-#endif
-
-#ifndef STATUS_ABANDON_HIBERFILE
-# define STATUS_ABANDON_HIBERFILE ((NTSTATUS) 0x40000033L)
-#endif
-
-#ifndef STATUS_BIZRULES_NOT_ENABLED
-# define STATUS_BIZRULES_NOT_ENABLED ((NTSTATUS) 0x40000034L)
-#endif
-
-#ifndef STATUS_GUARD_PAGE_VIOLATION
-# define STATUS_GUARD_PAGE_VIOLATION ((NTSTATUS) 0x80000001L)
-#endif
-
-#ifndef STATUS_DATATYPE_MISALIGNMENT
-# define STATUS_DATATYPE_MISALIGNMENT ((NTSTATUS) 0x80000002L)
-#endif
-
-#ifndef STATUS_BREAKPOINT
-# define STATUS_BREAKPOINT ((NTSTATUS) 0x80000003L)
-#endif
-
-#ifndef STATUS_SINGLE_STEP
-# define STATUS_SINGLE_STEP ((NTSTATUS) 0x80000004L)
-#endif
-
-#ifndef STATUS_BUFFER_OVERFLOW
-# define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005L)
-#endif
-
-#ifndef STATUS_NO_MORE_FILES
-# define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006L)
-#endif
-
-#ifndef STATUS_WAKE_SYSTEM_DEBUGGER
-# define STATUS_WAKE_SYSTEM_DEBUGGER ((NTSTATUS) 0x80000007L)
-#endif
-
-#ifndef STATUS_HANDLES_CLOSED
-# define STATUS_HANDLES_CLOSED ((NTSTATUS) 0x8000000AL)
-#endif
-
-#ifndef STATUS_NO_INHERITANCE
-# define STATUS_NO_INHERITANCE ((NTSTATUS) 0x8000000BL)
-#endif
-
-#ifndef STATUS_GUID_SUBSTITUTION_MADE
-# define STATUS_GUID_SUBSTITUTION_MADE ((NTSTATUS) 0x8000000CL)
-#endif
-
-#ifndef STATUS_PARTIAL_COPY
-# define STATUS_PARTIAL_COPY ((NTSTATUS) 0x8000000DL)
-#endif
-
-#ifndef STATUS_DEVICE_PAPER_EMPTY
-# define STATUS_DEVICE_PAPER_EMPTY ((NTSTATUS) 0x8000000EL)
-#endif
-
-#ifndef STATUS_DEVICE_POWERED_OFF
-# define STATUS_DEVICE_POWERED_OFF ((NTSTATUS) 0x8000000FL)
-#endif
-
-#ifndef STATUS_DEVICE_OFF_LINE
-# define STATUS_DEVICE_OFF_LINE ((NTSTATUS) 0x80000010L)
-#endif
-
-#ifndef STATUS_DEVICE_BUSY
-# define STATUS_DEVICE_BUSY ((NTSTATUS) 0x80000011L)
-#endif
-
-#ifndef STATUS_NO_MORE_EAS
-# define STATUS_NO_MORE_EAS ((NTSTATUS) 0x80000012L)
-#endif
-
-#ifndef STATUS_INVALID_EA_NAME
-# define STATUS_INVALID_EA_NAME ((NTSTATUS) 0x80000013L)
-#endif
-
-#ifndef STATUS_EA_LIST_INCONSISTENT
-# define STATUS_EA_LIST_INCONSISTENT ((NTSTATUS) 0x80000014L)
-#endif
-
-#ifndef STATUS_INVALID_EA_FLAG
-# define STATUS_INVALID_EA_FLAG ((NTSTATUS) 0x80000015L)
-#endif
-
-#ifndef STATUS_VERIFY_REQUIRED
-# define STATUS_VERIFY_REQUIRED ((NTSTATUS) 0x80000016L)
-#endif
-
-#ifndef STATUS_EXTRANEOUS_INFORMATION
-# define STATUS_EXTRANEOUS_INFORMATION ((NTSTATUS) 0x80000017L)
-#endif
-
-#ifndef STATUS_RXACT_COMMIT_NECESSARY
-# define STATUS_RXACT_COMMIT_NECESSARY ((NTSTATUS) 0x80000018L)
-#endif
-
-#ifndef STATUS_NO_MORE_ENTRIES
-# define STATUS_NO_MORE_ENTRIES ((NTSTATUS) 0x8000001AL)
-#endif
-
-#ifndef STATUS_FILEMARK_DETECTED
-# define STATUS_FILEMARK_DETECTED ((NTSTATUS) 0x8000001BL)
-#endif
-
-#ifndef STATUS_MEDIA_CHANGED
-# define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL)
-#endif
-
-#ifndef STATUS_BUS_RESET
-# define STATUS_BUS_RESET ((NTSTATUS) 0x8000001DL)
-#endif
-
-#ifndef STATUS_END_OF_MEDIA
-# define STATUS_END_OF_MEDIA ((NTSTATUS) 0x8000001EL)
-#endif
-
-#ifndef STATUS_BEGINNING_OF_MEDIA
-# define STATUS_BEGINNING_OF_MEDIA ((NTSTATUS) 0x8000001FL)
-#endif
-
-#ifndef STATUS_MEDIA_CHECK
-# define STATUS_MEDIA_CHECK ((NTSTATUS) 0x80000020L)
-#endif
-
-#ifndef STATUS_SETMARK_DETECTED
-# define STATUS_SETMARK_DETECTED ((NTSTATUS) 0x80000021L)
-#endif
-
-#ifndef STATUS_NO_DATA_DETECTED
-# define STATUS_NO_DATA_DETECTED ((NTSTATUS) 0x80000022L)
-#endif
-
-#ifndef STATUS_REDIRECTOR_HAS_OPEN_HANDLES
-# define STATUS_REDIRECTOR_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000023L)
-#endif
-
-#ifndef STATUS_SERVER_HAS_OPEN_HANDLES
-# define STATUS_SERVER_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000024L)
-#endif
-
-#ifndef STATUS_ALREADY_DISCONNECTED
-# define STATUS_ALREADY_DISCONNECTED ((NTSTATUS) 0x80000025L)
-#endif
-
-#ifndef STATUS_LONGJUMP
-# define STATUS_LONGJUMP ((NTSTATUS) 0x80000026L)
-#endif
-
-#ifndef STATUS_CLEANER_CARTRIDGE_INSTALLED
-# define STATUS_CLEANER_CARTRIDGE_INSTALLED ((NTSTATUS) 0x80000027L)
-#endif
-
-#ifndef STATUS_PLUGPLAY_QUERY_VETOED
-# define STATUS_PLUGPLAY_QUERY_VETOED ((NTSTATUS) 0x80000028L)
-#endif
-
-#ifndef STATUS_UNWIND_CONSOLIDATE
-# define STATUS_UNWIND_CONSOLIDATE ((NTSTATUS) 0x80000029L)
-#endif
-
-#ifndef STATUS_REGISTRY_HIVE_RECOVERED
-# define STATUS_REGISTRY_HIVE_RECOVERED ((NTSTATUS) 0x8000002AL)
-#endif
-
-#ifndef STATUS_DLL_MIGHT_BE_INSECURE
-# define STATUS_DLL_MIGHT_BE_INSECURE ((NTSTATUS) 0x8000002BL)
-#endif
-
-#ifndef STATUS_DLL_MIGHT_BE_INCOMPATIBLE
-# define STATUS_DLL_MIGHT_BE_INCOMPATIBLE ((NTSTATUS) 0x8000002CL)
-#endif
-
-#ifndef STATUS_STOPPED_ON_SYMLINK
-# define STATUS_STOPPED_ON_SYMLINK ((NTSTATUS) 0x8000002DL)
-#endif
-
-#ifndef STATUS_CANNOT_GRANT_REQUESTED_OPLOCK
-# define STATUS_CANNOT_GRANT_REQUESTED_OPLOCK ((NTSTATUS) 0x8000002EL)
-#endif
-
-#ifndef STATUS_NO_ACE_CONDITION
-# define STATUS_NO_ACE_CONDITION ((NTSTATUS) 0x8000002FL)
-#endif
-
-#ifndef STATUS_UNSUCCESSFUL
-# define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L)
-#endif
-
-#ifndef STATUS_NOT_IMPLEMENTED
-# define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L)
-#endif
-
-#ifndef STATUS_INVALID_INFO_CLASS
-# define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xC0000003L)
-#endif
-
-#ifndef STATUS_INFO_LENGTH_MISMATCH
-# define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004L)
-#endif
-
-#ifndef STATUS_ACCESS_VIOLATION
-# define STATUS_ACCESS_VIOLATION ((NTSTATUS) 0xC0000005L)
-#endif
-
-#ifndef STATUS_IN_PAGE_ERROR
-# define STATUS_IN_PAGE_ERROR ((NTSTATUS) 0xC0000006L)
-#endif
-
-#ifndef STATUS_PAGEFILE_QUOTA
-# define STATUS_PAGEFILE_QUOTA ((NTSTATUS) 0xC0000007L)
-#endif
-
-#ifndef STATUS_INVALID_HANDLE
-# define STATUS_INVALID_HANDLE ((NTSTATUS) 0xC0000008L)
-#endif
-
-#ifndef STATUS_BAD_INITIAL_STACK
-# define STATUS_BAD_INITIAL_STACK ((NTSTATUS) 0xC0000009L)
-#endif
-
-#ifndef STATUS_BAD_INITIAL_PC
-# define STATUS_BAD_INITIAL_PC ((NTSTATUS) 0xC000000AL)
-#endif
-
-#ifndef STATUS_INVALID_CID
-# define STATUS_INVALID_CID ((NTSTATUS) 0xC000000BL)
-#endif
-
-#ifndef STATUS_TIMER_NOT_CANCELED
-# define STATUS_TIMER_NOT_CANCELED ((NTSTATUS) 0xC000000CL)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER
-# define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL)
-#endif
-
-#ifndef STATUS_NO_SUCH_DEVICE
-# define STATUS_NO_SUCH_DEVICE ((NTSTATUS) 0xC000000EL)
-#endif
-
-#ifndef STATUS_NO_SUCH_FILE
-# define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xC000000FL)
-#endif
-
-#ifndef STATUS_INVALID_DEVICE_REQUEST
-# define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xC0000010L)
-#endif
-
-#ifndef STATUS_END_OF_FILE
-# define STATUS_END_OF_FILE ((NTSTATUS) 0xC0000011L)
-#endif
-
-#ifndef STATUS_WRONG_VOLUME
-# define STATUS_WRONG_VOLUME ((NTSTATUS) 0xC0000012L)
-#endif
-
-#ifndef STATUS_NO_MEDIA_IN_DEVICE
-# define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xC0000013L)
-#endif
-
-#ifndef STATUS_UNRECOGNIZED_MEDIA
-# define STATUS_UNRECOGNIZED_MEDIA ((NTSTATUS) 0xC0000014L)
-#endif
-
-#ifndef STATUS_NONEXISTENT_SECTOR
-# define STATUS_NONEXISTENT_SECTOR ((NTSTATUS) 0xC0000015L)
-#endif
-
-#ifndef STATUS_MORE_PROCESSING_REQUIRED
-# define STATUS_MORE_PROCESSING_REQUIRED ((NTSTATUS) 0xC0000016L)
-#endif
-
-#ifndef STATUS_NO_MEMORY
-# define STATUS_NO_MEMORY ((NTSTATUS) 0xC0000017L)
-#endif
-
-#ifndef STATUS_CONFLICTING_ADDRESSES
-# define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS) 0xC0000018L)
-#endif
-
-#ifndef STATUS_NOT_MAPPED_VIEW
-# define STATUS_NOT_MAPPED_VIEW ((NTSTATUS) 0xC0000019L)
-#endif
-
-#ifndef STATUS_UNABLE_TO_FREE_VM
-# define STATUS_UNABLE_TO_FREE_VM ((NTSTATUS) 0xC000001AL)
-#endif
-
-#ifndef STATUS_UNABLE_TO_DELETE_SECTION
-# define STATUS_UNABLE_TO_DELETE_SECTION ((NTSTATUS) 0xC000001BL)
-#endif
-
-#ifndef STATUS_INVALID_SYSTEM_SERVICE
-# define STATUS_INVALID_SYSTEM_SERVICE ((NTSTATUS) 0xC000001CL)
-#endif
-
-#ifndef STATUS_ILLEGAL_INSTRUCTION
-# define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS) 0xC000001DL)
-#endif
-
-#ifndef STATUS_INVALID_LOCK_SEQUENCE
-# define STATUS_INVALID_LOCK_SEQUENCE ((NTSTATUS) 0xC000001EL)
-#endif
-
-#ifndef STATUS_INVALID_VIEW_SIZE
-# define STATUS_INVALID_VIEW_SIZE ((NTSTATUS) 0xC000001FL)
-#endif
-
-#ifndef STATUS_INVALID_FILE_FOR_SECTION
-# define STATUS_INVALID_FILE_FOR_SECTION ((NTSTATUS) 0xC0000020L)
-#endif
-
-#ifndef STATUS_ALREADY_COMMITTED
-# define STATUS_ALREADY_COMMITTED ((NTSTATUS) 0xC0000021L)
-#endif
-
-#ifndef STATUS_ACCESS_DENIED
-# define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L)
-#endif
-
-#ifndef STATUS_BUFFER_TOO_SMALL
-# define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L)
-#endif
-
-#ifndef STATUS_OBJECT_TYPE_MISMATCH
-# define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xC0000024L)
-#endif
-
-#ifndef STATUS_NONCONTINUABLE_EXCEPTION
-# define STATUS_NONCONTINUABLE_EXCEPTION ((NTSTATUS) 0xC0000025L)
-#endif
-
-#ifndef STATUS_INVALID_DISPOSITION
-# define STATUS_INVALID_DISPOSITION ((NTSTATUS) 0xC0000026L)
-#endif
-
-#ifndef STATUS_UNWIND
-# define STATUS_UNWIND ((NTSTATUS) 0xC0000027L)
-#endif
-
-#ifndef STATUS_BAD_STACK
-# define STATUS_BAD_STACK ((NTSTATUS) 0xC0000028L)
-#endif
-
-#ifndef STATUS_INVALID_UNWIND_TARGET
-# define STATUS_INVALID_UNWIND_TARGET ((NTSTATUS) 0xC0000029L)
-#endif
-
-#ifndef STATUS_NOT_LOCKED
-# define STATUS_NOT_LOCKED ((NTSTATUS) 0xC000002AL)
-#endif
-
-#ifndef STATUS_PARITY_ERROR
-# define STATUS_PARITY_ERROR ((NTSTATUS) 0xC000002BL)
-#endif
-
-#ifndef STATUS_UNABLE_TO_DECOMMIT_VM
-# define STATUS_UNABLE_TO_DECOMMIT_VM ((NTSTATUS) 0xC000002CL)
-#endif
-
-#ifndef STATUS_NOT_COMMITTED
-# define STATUS_NOT_COMMITTED ((NTSTATUS) 0xC000002DL)
-#endif
-
-#ifndef STATUS_INVALID_PORT_ATTRIBUTES
-# define STATUS_INVALID_PORT_ATTRIBUTES ((NTSTATUS) 0xC000002EL)
-#endif
-
-#ifndef STATUS_PORT_MESSAGE_TOO_LONG
-# define STATUS_PORT_MESSAGE_TOO_LONG ((NTSTATUS) 0xC000002FL)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_MIX
-# define STATUS_INVALID_PARAMETER_MIX ((NTSTATUS) 0xC0000030L)
-#endif
-
-#ifndef STATUS_INVALID_QUOTA_LOWER
-# define STATUS_INVALID_QUOTA_LOWER ((NTSTATUS) 0xC0000031L)
-#endif
-
-#ifndef STATUS_DISK_CORRUPT_ERROR
-# define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L)
-#endif
-
-#ifndef STATUS_OBJECT_NAME_INVALID
-# define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xC0000033L)
-#endif
-
-#ifndef STATUS_OBJECT_NAME_NOT_FOUND
-# define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xC0000034L)
-#endif
-
-#ifndef STATUS_OBJECT_NAME_COLLISION
-# define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS) 0xC0000035L)
-#endif
-
-#ifndef STATUS_PORT_DISCONNECTED
-# define STATUS_PORT_DISCONNECTED ((NTSTATUS) 0xC0000037L)
-#endif
-
-#ifndef STATUS_DEVICE_ALREADY_ATTACHED
-# define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L)
-#endif
-
-#ifndef STATUS_OBJECT_PATH_INVALID
-# define STATUS_OBJECT_PATH_INVALID ((NTSTATUS) 0xC0000039L)
-#endif
-
-#ifndef STATUS_OBJECT_PATH_NOT_FOUND
-# define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xC000003AL)
-#endif
-
-#ifndef STATUS_OBJECT_PATH_SYNTAX_BAD
-# define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS) 0xC000003BL)
-#endif
-
-#ifndef STATUS_DATA_OVERRUN
-# define STATUS_DATA_OVERRUN ((NTSTATUS) 0xC000003CL)
-#endif
-
-#ifndef STATUS_DATA_LATE_ERROR
-# define STATUS_DATA_LATE_ERROR ((NTSTATUS) 0xC000003DL)
-#endif
-
-#ifndef STATUS_DATA_ERROR
-# define STATUS_DATA_ERROR ((NTSTATUS) 0xC000003EL)
-#endif
-
-#ifndef STATUS_CRC_ERROR
-# define STATUS_CRC_ERROR ((NTSTATUS) 0xC000003FL)
-#endif
-
-#ifndef STATUS_SECTION_TOO_BIG
-# define STATUS_SECTION_TOO_BIG ((NTSTATUS) 0xC0000040L)
-#endif
-
-#ifndef STATUS_PORT_CONNECTION_REFUSED
-# define STATUS_PORT_CONNECTION_REFUSED ((NTSTATUS) 0xC0000041L)
-#endif
-
-#ifndef STATUS_INVALID_PORT_HANDLE
-# define STATUS_INVALID_PORT_HANDLE ((NTSTATUS) 0xC0000042L)
-#endif
-
-#ifndef STATUS_SHARING_VIOLATION
-# define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xC0000043L)
-#endif
-
-#ifndef STATUS_QUOTA_EXCEEDED
-# define STATUS_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000044L)
-#endif
-
-#ifndef STATUS_INVALID_PAGE_PROTECTION
-# define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS) 0xC0000045L)
-#endif
-
-#ifndef STATUS_MUTANT_NOT_OWNED
-# define STATUS_MUTANT_NOT_OWNED ((NTSTATUS) 0xC0000046L)
-#endif
-
-#ifndef STATUS_SEMAPHORE_LIMIT_EXCEEDED
-# define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000047L)
-#endif
-
-#ifndef STATUS_PORT_ALREADY_SET
-# define STATUS_PORT_ALREADY_SET ((NTSTATUS) 0xC0000048L)
-#endif
-
-#ifndef STATUS_SECTION_NOT_IMAGE
-# define STATUS_SECTION_NOT_IMAGE ((NTSTATUS) 0xC0000049L)
-#endif
-
-#ifndef STATUS_SUSPEND_COUNT_EXCEEDED
-# define STATUS_SUSPEND_COUNT_EXCEEDED ((NTSTATUS) 0xC000004AL)
-#endif
-
-#ifndef STATUS_THREAD_IS_TERMINATING
-# define STATUS_THREAD_IS_TERMINATING ((NTSTATUS) 0xC000004BL)
-#endif
-
-#ifndef STATUS_BAD_WORKING_SET_LIMIT
-# define STATUS_BAD_WORKING_SET_LIMIT ((NTSTATUS) 0xC000004CL)
-#endif
-
-#ifndef STATUS_INCOMPATIBLE_FILE_MAP
-# define STATUS_INCOMPATIBLE_FILE_MAP ((NTSTATUS) 0xC000004DL)
-#endif
-
-#ifndef STATUS_SECTION_PROTECTION
-# define STATUS_SECTION_PROTECTION ((NTSTATUS) 0xC000004EL)
-#endif
-
-#ifndef STATUS_EAS_NOT_SUPPORTED
-# define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xC000004FL)
-#endif
-
-#ifndef STATUS_EA_TOO_LARGE
-# define STATUS_EA_TOO_LARGE ((NTSTATUS) 0xC0000050L)
-#endif
-
-#ifndef STATUS_NONEXISTENT_EA_ENTRY
-# define STATUS_NONEXISTENT_EA_ENTRY ((NTSTATUS) 0xC0000051L)
-#endif
-
-#ifndef STATUS_NO_EAS_ON_FILE
-# define STATUS_NO_EAS_ON_FILE ((NTSTATUS) 0xC0000052L)
-#endif
-
-#ifndef STATUS_EA_CORRUPT_ERROR
-# define STATUS_EA_CORRUPT_ERROR ((NTSTATUS) 0xC0000053L)
-#endif
-
-#ifndef STATUS_FILE_LOCK_CONFLICT
-# define STATUS_FILE_LOCK_CONFLICT ((NTSTATUS) 0xC0000054L)
-#endif
-
-#ifndef STATUS_LOCK_NOT_GRANTED
-# define STATUS_LOCK_NOT_GRANTED ((NTSTATUS) 0xC0000055L)
-#endif
-
-#ifndef STATUS_DELETE_PENDING
-# define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056L)
-#endif
-
-#ifndef STATUS_CTL_FILE_NOT_SUPPORTED
-# define STATUS_CTL_FILE_NOT_SUPPORTED ((NTSTATUS) 0xC0000057L)
-#endif
-
-#ifndef STATUS_UNKNOWN_REVISION
-# define STATUS_UNKNOWN_REVISION ((NTSTATUS) 0xC0000058L)
-#endif
-
-#ifndef STATUS_REVISION_MISMATCH
-# define STATUS_REVISION_MISMATCH ((NTSTATUS) 0xC0000059L)
-#endif
-
-#ifndef STATUS_INVALID_OWNER
-# define STATUS_INVALID_OWNER ((NTSTATUS) 0xC000005AL)
-#endif
-
-#ifndef STATUS_INVALID_PRIMARY_GROUP
-# define STATUS_INVALID_PRIMARY_GROUP ((NTSTATUS) 0xC000005BL)
-#endif
-
-#ifndef STATUS_NO_IMPERSONATION_TOKEN
-# define STATUS_NO_IMPERSONATION_TOKEN ((NTSTATUS) 0xC000005CL)
-#endif
-
-#ifndef STATUS_CANT_DISABLE_MANDATORY
-# define STATUS_CANT_DISABLE_MANDATORY ((NTSTATUS) 0xC000005DL)
-#endif
-
-#ifndef STATUS_NO_LOGON_SERVERS
-# define STATUS_NO_LOGON_SERVERS ((NTSTATUS) 0xC000005EL)
-#endif
-
-#ifndef STATUS_NO_SUCH_LOGON_SESSION
-# define STATUS_NO_SUCH_LOGON_SESSION ((NTSTATUS) 0xC000005FL)
-#endif
-
-#ifndef STATUS_NO_SUCH_PRIVILEGE
-# define STATUS_NO_SUCH_PRIVILEGE ((NTSTATUS) 0xC0000060L)
-#endif
-
-#ifndef STATUS_PRIVILEGE_NOT_HELD
-# define STATUS_PRIVILEGE_NOT_HELD ((NTSTATUS) 0xC0000061L)
-#endif
-
-#ifndef STATUS_INVALID_ACCOUNT_NAME
-# define STATUS_INVALID_ACCOUNT_NAME ((NTSTATUS) 0xC0000062L)
-#endif
-
-#ifndef STATUS_USER_EXISTS
-# define STATUS_USER_EXISTS ((NTSTATUS) 0xC0000063L)
-#endif
-
-#ifndef STATUS_NO_SUCH_USER
-# define STATUS_NO_SUCH_USER ((NTSTATUS) 0xC0000064L)
-#endif
-
-#ifndef STATUS_GROUP_EXISTS
-# define STATUS_GROUP_EXISTS ((NTSTATUS) 0xC0000065L)
-#endif
-
-#ifndef STATUS_NO_SUCH_GROUP
-# define STATUS_NO_SUCH_GROUP ((NTSTATUS) 0xC0000066L)
-#endif
-
-#ifndef STATUS_MEMBER_IN_GROUP
-# define STATUS_MEMBER_IN_GROUP ((NTSTATUS) 0xC0000067L)
-#endif
-
-#ifndef STATUS_MEMBER_NOT_IN_GROUP
-# define STATUS_MEMBER_NOT_IN_GROUP ((NTSTATUS) 0xC0000068L)
-#endif
-
-#ifndef STATUS_LAST_ADMIN
-# define STATUS_LAST_ADMIN ((NTSTATUS) 0xC0000069L)
-#endif
-
-#ifndef STATUS_WRONG_PASSWORD
-# define STATUS_WRONG_PASSWORD ((NTSTATUS) 0xC000006AL)
-#endif
-
-#ifndef STATUS_ILL_FORMED_PASSWORD
-# define STATUS_ILL_FORMED_PASSWORD ((NTSTATUS) 0xC000006BL)
-#endif
-
-#ifndef STATUS_PASSWORD_RESTRICTION
-# define STATUS_PASSWORD_RESTRICTION ((NTSTATUS) 0xC000006CL)
-#endif
-
-#ifndef STATUS_LOGON_FAILURE
-# define STATUS_LOGON_FAILURE ((NTSTATUS) 0xC000006DL)
-#endif
-
-#ifndef STATUS_ACCOUNT_RESTRICTION
-# define STATUS_ACCOUNT_RESTRICTION ((NTSTATUS) 0xC000006EL)
-#endif
-
-#ifndef STATUS_INVALID_LOGON_HOURS
-# define STATUS_INVALID_LOGON_HOURS ((NTSTATUS) 0xC000006FL)
-#endif
-
-#ifndef STATUS_INVALID_WORKSTATION
-# define STATUS_INVALID_WORKSTATION ((NTSTATUS) 0xC0000070L)
-#endif
-
-#ifndef STATUS_PASSWORD_EXPIRED
-# define STATUS_PASSWORD_EXPIRED ((NTSTATUS) 0xC0000071L)
-#endif
-
-#ifndef STATUS_ACCOUNT_DISABLED
-# define STATUS_ACCOUNT_DISABLED ((NTSTATUS) 0xC0000072L)
-#endif
-
-#ifndef STATUS_NONE_MAPPED
-# define STATUS_NONE_MAPPED ((NTSTATUS) 0xC0000073L)
-#endif
-
-#ifndef STATUS_TOO_MANY_LUIDS_REQUESTED
-# define STATUS_TOO_MANY_LUIDS_REQUESTED ((NTSTATUS) 0xC0000074L)
-#endif
-
-#ifndef STATUS_LUIDS_EXHAUSTED
-# define STATUS_LUIDS_EXHAUSTED ((NTSTATUS) 0xC0000075L)
-#endif
-
-#ifndef STATUS_INVALID_SUB_AUTHORITY
-# define STATUS_INVALID_SUB_AUTHORITY ((NTSTATUS) 0xC0000076L)
-#endif
-
-#ifndef STATUS_INVALID_ACL
-# define STATUS_INVALID_ACL ((NTSTATUS) 0xC0000077L)
-#endif
-
-#ifndef STATUS_INVALID_SID
-# define STATUS_INVALID_SID ((NTSTATUS) 0xC0000078L)
-#endif
-
-#ifndef STATUS_INVALID_SECURITY_DESCR
-# define STATUS_INVALID_SECURITY_DESCR ((NTSTATUS) 0xC0000079L)
-#endif
-
-#ifndef STATUS_PROCEDURE_NOT_FOUND
-# define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS) 0xC000007AL)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_FORMAT
-# define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS) 0xC000007BL)
-#endif
-
-#ifndef STATUS_NO_TOKEN
-# define STATUS_NO_TOKEN ((NTSTATUS) 0xC000007CL)
-#endif
-
-#ifndef STATUS_BAD_INHERITANCE_ACL
-# define STATUS_BAD_INHERITANCE_ACL ((NTSTATUS) 0xC000007DL)
-#endif
-
-#ifndef STATUS_RANGE_NOT_LOCKED
-# define STATUS_RANGE_NOT_LOCKED ((NTSTATUS) 0xC000007EL)
-#endif
-
-#ifndef STATUS_DISK_FULL
-# define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL)
-#endif
-
-#ifndef STATUS_SERVER_DISABLED
-# define STATUS_SERVER_DISABLED ((NTSTATUS) 0xC0000080L)
-#endif
-
-#ifndef STATUS_SERVER_NOT_DISABLED
-# define STATUS_SERVER_NOT_DISABLED ((NTSTATUS) 0xC0000081L)
-#endif
-
-#ifndef STATUS_TOO_MANY_GUIDS_REQUESTED
-# define STATUS_TOO_MANY_GUIDS_REQUESTED ((NTSTATUS) 0xC0000082L)
-#endif
-
-#ifndef STATUS_GUIDS_EXHAUSTED
-# define STATUS_GUIDS_EXHAUSTED ((NTSTATUS) 0xC0000083L)
-#endif
-
-#ifndef STATUS_INVALID_ID_AUTHORITY
-# define STATUS_INVALID_ID_AUTHORITY ((NTSTATUS) 0xC0000084L)
-#endif
-
-#ifndef STATUS_AGENTS_EXHAUSTED
-# define STATUS_AGENTS_EXHAUSTED ((NTSTATUS) 0xC0000085L)
-#endif
-
-#ifndef STATUS_INVALID_VOLUME_LABEL
-# define STATUS_INVALID_VOLUME_LABEL ((NTSTATUS) 0xC0000086L)
-#endif
-
-#ifndef STATUS_SECTION_NOT_EXTENDED
-# define STATUS_SECTION_NOT_EXTENDED ((NTSTATUS) 0xC0000087L)
-#endif
-
-#ifndef STATUS_NOT_MAPPED_DATA
-# define STATUS_NOT_MAPPED_DATA ((NTSTATUS) 0xC0000088L)
-#endif
-
-#ifndef STATUS_RESOURCE_DATA_NOT_FOUND
-# define STATUS_RESOURCE_DATA_NOT_FOUND ((NTSTATUS) 0xC0000089L)
-#endif
-
-#ifndef STATUS_RESOURCE_TYPE_NOT_FOUND
-# define STATUS_RESOURCE_TYPE_NOT_FOUND ((NTSTATUS) 0xC000008AL)
-#endif
-
-#ifndef STATUS_RESOURCE_NAME_NOT_FOUND
-# define STATUS_RESOURCE_NAME_NOT_FOUND ((NTSTATUS) 0xC000008BL)
-#endif
-
-#ifndef STATUS_ARRAY_BOUNDS_EXCEEDED
-# define STATUS_ARRAY_BOUNDS_EXCEEDED ((NTSTATUS) 0xC000008CL)
-#endif
-
-#ifndef STATUS_FLOAT_DENORMAL_OPERAND
-# define STATUS_FLOAT_DENORMAL_OPERAND ((NTSTATUS) 0xC000008DL)
-#endif
-
-#ifndef STATUS_FLOAT_DIVIDE_BY_ZERO
-# define STATUS_FLOAT_DIVIDE_BY_ZERO ((NTSTATUS) 0xC000008EL)
-#endif
-
-#ifndef STATUS_FLOAT_INEXACT_RESULT
-# define STATUS_FLOAT_INEXACT_RESULT ((NTSTATUS) 0xC000008FL)
-#endif
-
-#ifndef STATUS_FLOAT_INVALID_OPERATION
-# define STATUS_FLOAT_INVALID_OPERATION ((NTSTATUS) 0xC0000090L)
-#endif
-
-#ifndef STATUS_FLOAT_OVERFLOW
-# define STATUS_FLOAT_OVERFLOW ((NTSTATUS) 0xC0000091L)
-#endif
-
-#ifndef STATUS_FLOAT_STACK_CHECK
-# define STATUS_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000092L)
-#endif
-
-#ifndef STATUS_FLOAT_UNDERFLOW
-# define STATUS_FLOAT_UNDERFLOW ((NTSTATUS) 0xC0000093L)
-#endif
-
-#ifndef STATUS_INTEGER_DIVIDE_BY_ZERO
-# define STATUS_INTEGER_DIVIDE_BY_ZERO ((NTSTATUS) 0xC0000094L)
-#endif
-
-#ifndef STATUS_INTEGER_OVERFLOW
-# define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L)
-#endif
-
-#ifndef STATUS_PRIVILEGED_INSTRUCTION
-# define STATUS_PRIVILEGED_INSTRUCTION ((NTSTATUS) 0xC0000096L)
-#endif
-
-#ifndef STATUS_TOO_MANY_PAGING_FILES
-# define STATUS_TOO_MANY_PAGING_FILES ((NTSTATUS) 0xC0000097L)
-#endif
-
-#ifndef STATUS_FILE_INVALID
-# define STATUS_FILE_INVALID ((NTSTATUS) 0xC0000098L)
-#endif
-
-#ifndef STATUS_ALLOTTED_SPACE_EXCEEDED
-# define STATUS_ALLOTTED_SPACE_EXCEEDED ((NTSTATUS) 0xC0000099L)
-#endif
-
-#ifndef STATUS_INSUFFICIENT_RESOURCES
-# define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL)
-#endif
-
-#ifndef STATUS_DFS_EXIT_PATH_FOUND
-# define STATUS_DFS_EXIT_PATH_FOUND ((NTSTATUS) 0xC000009BL)
-#endif
-
-#ifndef STATUS_DEVICE_DATA_ERROR
-# define STATUS_DEVICE_DATA_ERROR ((NTSTATUS) 0xC000009CL)
-#endif
-
-#ifndef STATUS_DEVICE_NOT_CONNECTED
-# define STATUS_DEVICE_NOT_CONNECTED ((NTSTATUS) 0xC000009DL)
-#endif
-
-#ifndef STATUS_DEVICE_POWER_FAILURE
-# define STATUS_DEVICE_POWER_FAILURE ((NTSTATUS) 0xC000009EL)
-#endif
-
-#ifndef STATUS_FREE_VM_NOT_AT_BASE
-# define STATUS_FREE_VM_NOT_AT_BASE ((NTSTATUS) 0xC000009FL)
-#endif
-
-#ifndef STATUS_MEMORY_NOT_ALLOCATED
-# define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS) 0xC00000A0L)
-#endif
-
-#ifndef STATUS_WORKING_SET_QUOTA
-# define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xC00000A1L)
-#endif
-
-#ifndef STATUS_MEDIA_WRITE_PROTECTED
-# define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L)
-#endif
-
-#ifndef STATUS_DEVICE_NOT_READY
-# define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L)
-#endif
-
-#ifndef STATUS_INVALID_GROUP_ATTRIBUTES
-# define STATUS_INVALID_GROUP_ATTRIBUTES ((NTSTATUS) 0xC00000A4L)
-#endif
-
-#ifndef STATUS_BAD_IMPERSONATION_LEVEL
-# define STATUS_BAD_IMPERSONATION_LEVEL ((NTSTATUS) 0xC00000A5L)
-#endif
-
-#ifndef STATUS_CANT_OPEN_ANONYMOUS
-# define STATUS_CANT_OPEN_ANONYMOUS ((NTSTATUS) 0xC00000A6L)
-#endif
-
-#ifndef STATUS_BAD_VALIDATION_CLASS
-# define STATUS_BAD_VALIDATION_CLASS ((NTSTATUS) 0xC00000A7L)
-#endif
-
-#ifndef STATUS_BAD_TOKEN_TYPE
-# define STATUS_BAD_TOKEN_TYPE ((NTSTATUS) 0xC00000A8L)
-#endif
-
-#ifndef STATUS_BAD_MASTER_BOOT_RECORD
-# define STATUS_BAD_MASTER_BOOT_RECORD ((NTSTATUS) 0xC00000A9L)
-#endif
-
-#ifndef STATUS_INSTRUCTION_MISALIGNMENT
-# define STATUS_INSTRUCTION_MISALIGNMENT ((NTSTATUS) 0xC00000AAL)
-#endif
-
-#ifndef STATUS_INSTANCE_NOT_AVAILABLE
-# define STATUS_INSTANCE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ABL)
-#endif
-
-#ifndef STATUS_PIPE_NOT_AVAILABLE
-# define STATUS_PIPE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ACL)
-#endif
-
-#ifndef STATUS_INVALID_PIPE_STATE
-# define STATUS_INVALID_PIPE_STATE ((NTSTATUS) 0xC00000ADL)
-#endif
-
-#ifndef STATUS_PIPE_BUSY
-# define STATUS_PIPE_BUSY ((NTSTATUS) 0xC00000AEL)
-#endif
-
-#ifndef STATUS_ILLEGAL_FUNCTION
-# define STATUS_ILLEGAL_FUNCTION ((NTSTATUS) 0xC00000AFL)
-#endif
-
-#ifndef STATUS_PIPE_DISCONNECTED
-# define STATUS_PIPE_DISCONNECTED ((NTSTATUS) 0xC00000B0L)
-#endif
-
-#ifndef STATUS_PIPE_CLOSING
-# define STATUS_PIPE_CLOSING ((NTSTATUS) 0xC00000B1L)
-#endif
-
-#ifndef STATUS_PIPE_CONNECTED
-# define STATUS_PIPE_CONNECTED ((NTSTATUS) 0xC00000B2L)
-#endif
-
-#ifndef STATUS_PIPE_LISTENING
-# define STATUS_PIPE_LISTENING ((NTSTATUS) 0xC00000B3L)
-#endif
-
-#ifndef STATUS_INVALID_READ_MODE
-# define STATUS_INVALID_READ_MODE ((NTSTATUS) 0xC00000B4L)
-#endif
-
-#ifndef STATUS_IO_TIMEOUT
-# define STATUS_IO_TIMEOUT ((NTSTATUS) 0xC00000B5L)
-#endif
-
-#ifndef STATUS_FILE_FORCED_CLOSED
-# define STATUS_FILE_FORCED_CLOSED ((NTSTATUS) 0xC00000B6L)
-#endif
-
-#ifndef STATUS_PROFILING_NOT_STARTED
-# define STATUS_PROFILING_NOT_STARTED ((NTSTATUS) 0xC00000B7L)
-#endif
-
-#ifndef STATUS_PROFILING_NOT_STOPPED
-# define STATUS_PROFILING_NOT_STOPPED ((NTSTATUS) 0xC00000B8L)
-#endif
-
-#ifndef STATUS_COULD_NOT_INTERPRET
-# define STATUS_COULD_NOT_INTERPRET ((NTSTATUS) 0xC00000B9L)
-#endif
-
-#ifndef STATUS_FILE_IS_A_DIRECTORY
-# define STATUS_FILE_IS_A_DIRECTORY ((NTSTATUS) 0xC00000BAL)
-#endif
-
-#ifndef STATUS_NOT_SUPPORTED
-# define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL)
-#endif
-
-#ifndef STATUS_REMOTE_NOT_LISTENING
-# define STATUS_REMOTE_NOT_LISTENING ((NTSTATUS) 0xC00000BCL)
-#endif
-
-#ifndef STATUS_DUPLICATE_NAME
-# define STATUS_DUPLICATE_NAME ((NTSTATUS) 0xC00000BDL)
-#endif
-
-#ifndef STATUS_BAD_NETWORK_PATH
-# define STATUS_BAD_NETWORK_PATH ((NTSTATUS) 0xC00000BEL)
-#endif
-
-#ifndef STATUS_NETWORK_BUSY
-# define STATUS_NETWORK_BUSY ((NTSTATUS) 0xC00000BFL)
-#endif
-
-#ifndef STATUS_DEVICE_DOES_NOT_EXIST
-# define STATUS_DEVICE_DOES_NOT_EXIST ((NTSTATUS) 0xC00000C0L)
-#endif
-
-#ifndef STATUS_TOO_MANY_COMMANDS
-# define STATUS_TOO_MANY_COMMANDS ((NTSTATUS) 0xC00000C1L)
-#endif
-
-#ifndef STATUS_ADAPTER_HARDWARE_ERROR
-# define STATUS_ADAPTER_HARDWARE_ERROR ((NTSTATUS) 0xC00000C2L)
-#endif
-
-#ifndef STATUS_INVALID_NETWORK_RESPONSE
-# define STATUS_INVALID_NETWORK_RESPONSE ((NTSTATUS) 0xC00000C3L)
-#endif
-
-#ifndef STATUS_UNEXPECTED_NETWORK_ERROR
-# define STATUS_UNEXPECTED_NETWORK_ERROR ((NTSTATUS) 0xC00000C4L)
-#endif
-
-#ifndef STATUS_BAD_REMOTE_ADAPTER
-# define STATUS_BAD_REMOTE_ADAPTER ((NTSTATUS) 0xC00000C5L)
-#endif
-
-#ifndef STATUS_PRINT_QUEUE_FULL
-# define STATUS_PRINT_QUEUE_FULL ((NTSTATUS) 0xC00000C6L)
-#endif
-
-#ifndef STATUS_NO_SPOOL_SPACE
-# define STATUS_NO_SPOOL_SPACE ((NTSTATUS) 0xC00000C7L)
-#endif
-
-#ifndef STATUS_PRINT_CANCELLED
-# define STATUS_PRINT_CANCELLED ((NTSTATUS) 0xC00000C8L)
-#endif
-
-#ifndef STATUS_NETWORK_NAME_DELETED
-# define STATUS_NETWORK_NAME_DELETED ((NTSTATUS) 0xC00000C9L)
-#endif
-
-#ifndef STATUS_NETWORK_ACCESS_DENIED
-# define STATUS_NETWORK_ACCESS_DENIED ((NTSTATUS) 0xC00000CAL)
-#endif
-
-#ifndef STATUS_BAD_DEVICE_TYPE
-# define STATUS_BAD_DEVICE_TYPE ((NTSTATUS) 0xC00000CBL)
-#endif
-
-#ifndef STATUS_BAD_NETWORK_NAME
-# define STATUS_BAD_NETWORK_NAME ((NTSTATUS) 0xC00000CCL)
-#endif
-
-#ifndef STATUS_TOO_MANY_NAMES
-# define STATUS_TOO_MANY_NAMES ((NTSTATUS) 0xC00000CDL)
-#endif
-
-#ifndef STATUS_TOO_MANY_SESSIONS
-# define STATUS_TOO_MANY_SESSIONS ((NTSTATUS) 0xC00000CEL)
-#endif
-
-#ifndef STATUS_SHARING_PAUSED
-# define STATUS_SHARING_PAUSED ((NTSTATUS) 0xC00000CFL)
-#endif
-
-#ifndef STATUS_REQUEST_NOT_ACCEPTED
-# define STATUS_REQUEST_NOT_ACCEPTED ((NTSTATUS) 0xC00000D0L)
-#endif
-
-#ifndef STATUS_REDIRECTOR_PAUSED
-# define STATUS_REDIRECTOR_PAUSED ((NTSTATUS) 0xC00000D1L)
-#endif
-
-#ifndef STATUS_NET_WRITE_FAULT
-# define STATUS_NET_WRITE_FAULT ((NTSTATUS) 0xC00000D2L)
-#endif
-
-#ifndef STATUS_PROFILING_AT_LIMIT
-# define STATUS_PROFILING_AT_LIMIT ((NTSTATUS) 0xC00000D3L)
-#endif
-
-#ifndef STATUS_NOT_SAME_DEVICE
-# define STATUS_NOT_SAME_DEVICE ((NTSTATUS) 0xC00000D4L)
-#endif
-
-#ifndef STATUS_FILE_RENAMED
-# define STATUS_FILE_RENAMED ((NTSTATUS) 0xC00000D5L)
-#endif
-
-#ifndef STATUS_VIRTUAL_CIRCUIT_CLOSED
-# define STATUS_VIRTUAL_CIRCUIT_CLOSED ((NTSTATUS) 0xC00000D6L)
-#endif
-
-#ifndef STATUS_NO_SECURITY_ON_OBJECT
-# define STATUS_NO_SECURITY_ON_OBJECT ((NTSTATUS) 0xC00000D7L)
-#endif
-
-#ifndef STATUS_CANT_WAIT
-# define STATUS_CANT_WAIT ((NTSTATUS) 0xC00000D8L)
-#endif
-
-#ifndef STATUS_PIPE_EMPTY
-# define STATUS_PIPE_EMPTY ((NTSTATUS) 0xC00000D9L)
-#endif
-
-#ifndef STATUS_CANT_ACCESS_DOMAIN_INFO
-# define STATUS_CANT_ACCESS_DOMAIN_INFO ((NTSTATUS) 0xC00000DAL)
-#endif
-
-#ifndef STATUS_CANT_TERMINATE_SELF
-# define STATUS_CANT_TERMINATE_SELF ((NTSTATUS) 0xC00000DBL)
-#endif
-
-#ifndef STATUS_INVALID_SERVER_STATE
-# define STATUS_INVALID_SERVER_STATE ((NTSTATUS) 0xC00000DCL)
-#endif
-
-#ifndef STATUS_INVALID_DOMAIN_STATE
-# define STATUS_INVALID_DOMAIN_STATE ((NTSTATUS) 0xC00000DDL)
-#endif
-
-#ifndef STATUS_INVALID_DOMAIN_ROLE
-# define STATUS_INVALID_DOMAIN_ROLE ((NTSTATUS) 0xC00000DEL)
-#endif
-
-#ifndef STATUS_NO_SUCH_DOMAIN
-# define STATUS_NO_SUCH_DOMAIN ((NTSTATUS) 0xC00000DFL)
-#endif
-
-#ifndef STATUS_DOMAIN_EXISTS
-# define STATUS_DOMAIN_EXISTS ((NTSTATUS) 0xC00000E0L)
-#endif
-
-#ifndef STATUS_DOMAIN_LIMIT_EXCEEDED
-# define STATUS_DOMAIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00000E1L)
-#endif
-
-#ifndef STATUS_OPLOCK_NOT_GRANTED
-# define STATUS_OPLOCK_NOT_GRANTED ((NTSTATUS) 0xC00000E2L)
-#endif
-
-#ifndef STATUS_INVALID_OPLOCK_PROTOCOL
-# define STATUS_INVALID_OPLOCK_PROTOCOL ((NTSTATUS) 0xC00000E3L)
-#endif
-
-#ifndef STATUS_INTERNAL_DB_CORRUPTION
-# define STATUS_INTERNAL_DB_CORRUPTION ((NTSTATUS) 0xC00000E4L)
-#endif
-
-#ifndef STATUS_INTERNAL_ERROR
-# define STATUS_INTERNAL_ERROR ((NTSTATUS) 0xC00000E5L)
-#endif
-
-#ifndef STATUS_GENERIC_NOT_MAPPED
-# define STATUS_GENERIC_NOT_MAPPED ((NTSTATUS) 0xC00000E6L)
-#endif
-
-#ifndef STATUS_BAD_DESCRIPTOR_FORMAT
-# define STATUS_BAD_DESCRIPTOR_FORMAT ((NTSTATUS) 0xC00000E7L)
-#endif
-
-#ifndef STATUS_INVALID_USER_BUFFER
-# define STATUS_INVALID_USER_BUFFER ((NTSTATUS) 0xC00000E8L)
-#endif
-
-#ifndef STATUS_UNEXPECTED_IO_ERROR
-# define STATUS_UNEXPECTED_IO_ERROR ((NTSTATUS) 0xC00000E9L)
-#endif
-
-#ifndef STATUS_UNEXPECTED_MM_CREATE_ERR
-# define STATUS_UNEXPECTED_MM_CREATE_ERR ((NTSTATUS) 0xC00000EAL)
-#endif
-
-#ifndef STATUS_UNEXPECTED_MM_MAP_ERROR
-# define STATUS_UNEXPECTED_MM_MAP_ERROR ((NTSTATUS) 0xC00000EBL)
-#endif
-
-#ifndef STATUS_UNEXPECTED_MM_EXTEND_ERR
-# define STATUS_UNEXPECTED_MM_EXTEND_ERR ((NTSTATUS) 0xC00000ECL)
-#endif
-
-#ifndef STATUS_NOT_LOGON_PROCESS
-# define STATUS_NOT_LOGON_PROCESS ((NTSTATUS) 0xC00000EDL)
-#endif
-
-#ifndef STATUS_LOGON_SESSION_EXISTS
-# define STATUS_LOGON_SESSION_EXISTS ((NTSTATUS) 0xC00000EEL)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_1
-# define STATUS_INVALID_PARAMETER_1 ((NTSTATUS) 0xC00000EFL)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_2
-# define STATUS_INVALID_PARAMETER_2 ((NTSTATUS) 0xC00000F0L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_3
-# define STATUS_INVALID_PARAMETER_3 ((NTSTATUS) 0xC00000F1L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_4
-# define STATUS_INVALID_PARAMETER_4 ((NTSTATUS) 0xC00000F2L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_5
-# define STATUS_INVALID_PARAMETER_5 ((NTSTATUS) 0xC00000F3L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_6
-# define STATUS_INVALID_PARAMETER_6 ((NTSTATUS) 0xC00000F4L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_7
-# define STATUS_INVALID_PARAMETER_7 ((NTSTATUS) 0xC00000F5L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_8
-# define STATUS_INVALID_PARAMETER_8 ((NTSTATUS) 0xC00000F6L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_9
-# define STATUS_INVALID_PARAMETER_9 ((NTSTATUS) 0xC00000F7L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_10
-# define STATUS_INVALID_PARAMETER_10 ((NTSTATUS) 0xC00000F8L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_11
-# define STATUS_INVALID_PARAMETER_11 ((NTSTATUS) 0xC00000F9L)
-#endif
-
-#ifndef STATUS_INVALID_PARAMETER_12
-# define STATUS_INVALID_PARAMETER_12 ((NTSTATUS) 0xC00000FAL)
-#endif
-
-#ifndef STATUS_REDIRECTOR_NOT_STARTED
-# define STATUS_REDIRECTOR_NOT_STARTED ((NTSTATUS) 0xC00000FBL)
-#endif
-
-#ifndef STATUS_REDIRECTOR_STARTED
-# define STATUS_REDIRECTOR_STARTED ((NTSTATUS) 0xC00000FCL)
-#endif
-
-#ifndef STATUS_STACK_OVERFLOW
-# define STATUS_STACK_OVERFLOW ((NTSTATUS) 0xC00000FDL)
-#endif
-
-#ifndef STATUS_NO_SUCH_PACKAGE
-# define STATUS_NO_SUCH_PACKAGE ((NTSTATUS) 0xC00000FEL)
-#endif
-
-#ifndef STATUS_BAD_FUNCTION_TABLE
-# define STATUS_BAD_FUNCTION_TABLE ((NTSTATUS) 0xC00000FFL)
-#endif
-
-#ifndef STATUS_VARIABLE_NOT_FOUND
-# define STATUS_VARIABLE_NOT_FOUND ((NTSTATUS) 0xC0000100L)
-#endif
-
-#ifndef STATUS_DIRECTORY_NOT_EMPTY
-# define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xC0000101L)
-#endif
-
-#ifndef STATUS_FILE_CORRUPT_ERROR
-# define STATUS_FILE_CORRUPT_ERROR ((NTSTATUS) 0xC0000102L)
-#endif
-
-#ifndef STATUS_NOT_A_DIRECTORY
-# define STATUS_NOT_A_DIRECTORY ((NTSTATUS) 0xC0000103L)
-#endif
-
-#ifndef STATUS_BAD_LOGON_SESSION_STATE
-# define STATUS_BAD_LOGON_SESSION_STATE ((NTSTATUS) 0xC0000104L)
-#endif
-
-#ifndef STATUS_LOGON_SESSION_COLLISION
-# define STATUS_LOGON_SESSION_COLLISION ((NTSTATUS) 0xC0000105L)
-#endif
-
-#ifndef STATUS_NAME_TOO_LONG
-# define STATUS_NAME_TOO_LONG ((NTSTATUS) 0xC0000106L)
-#endif
-
-#ifndef STATUS_FILES_OPEN
-# define STATUS_FILES_OPEN ((NTSTATUS) 0xC0000107L)
-#endif
-
-#ifndef STATUS_CONNECTION_IN_USE
-# define STATUS_CONNECTION_IN_USE ((NTSTATUS) 0xC0000108L)
-#endif
-
-#ifndef STATUS_MESSAGE_NOT_FOUND
-# define STATUS_MESSAGE_NOT_FOUND ((NTSTATUS) 0xC0000109L)
-#endif
-
-#ifndef STATUS_PROCESS_IS_TERMINATING
-# define STATUS_PROCESS_IS_TERMINATING ((NTSTATUS) 0xC000010AL)
-#endif
-
-#ifndef STATUS_INVALID_LOGON_TYPE
-# define STATUS_INVALID_LOGON_TYPE ((NTSTATUS) 0xC000010BL)
-#endif
-
-#ifndef STATUS_NO_GUID_TRANSLATION
-# define STATUS_NO_GUID_TRANSLATION ((NTSTATUS) 0xC000010CL)
-#endif
-
-#ifndef STATUS_CANNOT_IMPERSONATE
-# define STATUS_CANNOT_IMPERSONATE ((NTSTATUS) 0xC000010DL)
-#endif
-
-#ifndef STATUS_IMAGE_ALREADY_LOADED
-# define STATUS_IMAGE_ALREADY_LOADED ((NTSTATUS) 0xC000010EL)
-#endif
-
-#ifndef STATUS_ABIOS_NOT_PRESENT
-# define STATUS_ABIOS_NOT_PRESENT ((NTSTATUS) 0xC000010FL)
-#endif
-
-#ifndef STATUS_ABIOS_LID_NOT_EXIST
-# define STATUS_ABIOS_LID_NOT_EXIST ((NTSTATUS) 0xC0000110L)
-#endif
-
-#ifndef STATUS_ABIOS_LID_ALREADY_OWNED
-# define STATUS_ABIOS_LID_ALREADY_OWNED ((NTSTATUS) 0xC0000111L)
-#endif
-
-#ifndef STATUS_ABIOS_NOT_LID_OWNER
-# define STATUS_ABIOS_NOT_LID_OWNER ((NTSTATUS) 0xC0000112L)
-#endif
-
-#ifndef STATUS_ABIOS_INVALID_COMMAND
-# define STATUS_ABIOS_INVALID_COMMAND ((NTSTATUS) 0xC0000113L)
-#endif
-
-#ifndef STATUS_ABIOS_INVALID_LID
-# define STATUS_ABIOS_INVALID_LID ((NTSTATUS) 0xC0000114L)
-#endif
-
-#ifndef STATUS_ABIOS_SELECTOR_NOT_AVAILABLE
-# define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE ((NTSTATUS) 0xC0000115L)
-#endif
-
-#ifndef STATUS_ABIOS_INVALID_SELECTOR
-# define STATUS_ABIOS_INVALID_SELECTOR ((NTSTATUS) 0xC0000116L)
-#endif
-
-#ifndef STATUS_NO_LDT
-# define STATUS_NO_LDT ((NTSTATUS) 0xC0000117L)
-#endif
-
-#ifndef STATUS_INVALID_LDT_SIZE
-# define STATUS_INVALID_LDT_SIZE ((NTSTATUS) 0xC0000118L)
-#endif
-
-#ifndef STATUS_INVALID_LDT_OFFSET
-# define STATUS_INVALID_LDT_OFFSET ((NTSTATUS) 0xC0000119L)
-#endif
-
-#ifndef STATUS_INVALID_LDT_DESCRIPTOR
-# define STATUS_INVALID_LDT_DESCRIPTOR ((NTSTATUS) 0xC000011AL)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_NE_FORMAT
-# define STATUS_INVALID_IMAGE_NE_FORMAT ((NTSTATUS) 0xC000011BL)
-#endif
-
-#ifndef STATUS_RXACT_INVALID_STATE
-# define STATUS_RXACT_INVALID_STATE ((NTSTATUS) 0xC000011CL)
-#endif
-
-#ifndef STATUS_RXACT_COMMIT_FAILURE
-# define STATUS_RXACT_COMMIT_FAILURE ((NTSTATUS) 0xC000011DL)
-#endif
-
-#ifndef STATUS_MAPPED_FILE_SIZE_ZERO
-# define STATUS_MAPPED_FILE_SIZE_ZERO ((NTSTATUS) 0xC000011EL)
-#endif
-
-#ifndef STATUS_TOO_MANY_OPENED_FILES
-# define STATUS_TOO_MANY_OPENED_FILES ((NTSTATUS) 0xC000011FL)
-#endif
-
-#ifndef STATUS_CANCELLED
-# define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L)
-#endif
-
-#ifndef STATUS_CANNOT_DELETE
-# define STATUS_CANNOT_DELETE ((NTSTATUS) 0xC0000121L)
-#endif
-
-#ifndef STATUS_INVALID_COMPUTER_NAME
-# define STATUS_INVALID_COMPUTER_NAME ((NTSTATUS) 0xC0000122L)
-#endif
-
-#ifndef STATUS_FILE_DELETED
-# define STATUS_FILE_DELETED ((NTSTATUS) 0xC0000123L)
-#endif
-
-#ifndef STATUS_SPECIAL_ACCOUNT
-# define STATUS_SPECIAL_ACCOUNT ((NTSTATUS) 0xC0000124L)
-#endif
-
-#ifndef STATUS_SPECIAL_GROUP
-# define STATUS_SPECIAL_GROUP ((NTSTATUS) 0xC0000125L)
-#endif
-
-#ifndef STATUS_SPECIAL_USER
-# define STATUS_SPECIAL_USER ((NTSTATUS) 0xC0000126L)
-#endif
-
-#ifndef STATUS_MEMBERS_PRIMARY_GROUP
-# define STATUS_MEMBERS_PRIMARY_GROUP ((NTSTATUS) 0xC0000127L)
-#endif
-
-#ifndef STATUS_FILE_CLOSED
-# define STATUS_FILE_CLOSED ((NTSTATUS) 0xC0000128L)
-#endif
-
-#ifndef STATUS_TOO_MANY_THREADS
-# define STATUS_TOO_MANY_THREADS ((NTSTATUS) 0xC0000129L)
-#endif
-
-#ifndef STATUS_THREAD_NOT_IN_PROCESS
-# define STATUS_THREAD_NOT_IN_PROCESS ((NTSTATUS) 0xC000012AL)
-#endif
-
-#ifndef STATUS_TOKEN_ALREADY_IN_USE
-# define STATUS_TOKEN_ALREADY_IN_USE ((NTSTATUS) 0xC000012BL)
-#endif
-
-#ifndef STATUS_PAGEFILE_QUOTA_EXCEEDED
-# define STATUS_PAGEFILE_QUOTA_EXCEEDED ((NTSTATUS) 0xC000012CL)
-#endif
-
-#ifndef STATUS_COMMITMENT_LIMIT
-# define STATUS_COMMITMENT_LIMIT ((NTSTATUS) 0xC000012DL)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_LE_FORMAT
-# define STATUS_INVALID_IMAGE_LE_FORMAT ((NTSTATUS) 0xC000012EL)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_NOT_MZ
-# define STATUS_INVALID_IMAGE_NOT_MZ ((NTSTATUS) 0xC000012FL)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_PROTECT
-# define STATUS_INVALID_IMAGE_PROTECT ((NTSTATUS) 0xC0000130L)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_WIN_16
-# define STATUS_INVALID_IMAGE_WIN_16 ((NTSTATUS) 0xC0000131L)
-#endif
-
-#ifndef STATUS_LOGON_SERVER_CONFLICT
-# define STATUS_LOGON_SERVER_CONFLICT ((NTSTATUS) 0xC0000132L)
-#endif
-
-#ifndef STATUS_TIME_DIFFERENCE_AT_DC
-# define STATUS_TIME_DIFFERENCE_AT_DC ((NTSTATUS) 0xC0000133L)
-#endif
-
-#ifndef STATUS_SYNCHRONIZATION_REQUIRED
-# define STATUS_SYNCHRONIZATION_REQUIRED ((NTSTATUS) 0xC0000134L)
-#endif
-
-#ifndef STATUS_DLL_NOT_FOUND
-# define STATUS_DLL_NOT_FOUND ((NTSTATUS) 0xC0000135L)
-#endif
-
-#ifndef STATUS_OPEN_FAILED
-# define STATUS_OPEN_FAILED ((NTSTATUS) 0xC0000136L)
-#endif
-
-#ifndef STATUS_IO_PRIVILEGE_FAILED
-# define STATUS_IO_PRIVILEGE_FAILED ((NTSTATUS) 0xC0000137L)
-#endif
-
-#ifndef STATUS_ORDINAL_NOT_FOUND
-# define STATUS_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000138L)
-#endif
-
-#ifndef STATUS_ENTRYPOINT_NOT_FOUND
-# define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000139L)
-#endif
-
-#ifndef STATUS_CONTROL_C_EXIT
-# define STATUS_CONTROL_C_EXIT ((NTSTATUS) 0xC000013AL)
-#endif
-
-#ifndef STATUS_LOCAL_DISCONNECT
-# define STATUS_LOCAL_DISCONNECT ((NTSTATUS) 0xC000013BL)
-#endif
-
-#ifndef STATUS_REMOTE_DISCONNECT
-# define STATUS_REMOTE_DISCONNECT ((NTSTATUS) 0xC000013CL)
-#endif
-
-#ifndef STATUS_REMOTE_RESOURCES
-# define STATUS_REMOTE_RESOURCES ((NTSTATUS) 0xC000013DL)
-#endif
-
-#ifndef STATUS_LINK_FAILED
-# define STATUS_LINK_FAILED ((NTSTATUS) 0xC000013EL)
-#endif
-
-#ifndef STATUS_LINK_TIMEOUT
-# define STATUS_LINK_TIMEOUT ((NTSTATUS) 0xC000013FL)
-#endif
-
-#ifndef STATUS_INVALID_CONNECTION
-# define STATUS_INVALID_CONNECTION ((NTSTATUS) 0xC0000140L)
-#endif
-
-#ifndef STATUS_INVALID_ADDRESS
-# define STATUS_INVALID_ADDRESS ((NTSTATUS) 0xC0000141L)
-#endif
-
-#ifndef STATUS_DLL_INIT_FAILED
-# define STATUS_DLL_INIT_FAILED ((NTSTATUS) 0xC0000142L)
-#endif
-
-#ifndef STATUS_MISSING_SYSTEMFILE
-# define STATUS_MISSING_SYSTEMFILE ((NTSTATUS) 0xC0000143L)
-#endif
-
-#ifndef STATUS_UNHANDLED_EXCEPTION
-# define STATUS_UNHANDLED_EXCEPTION ((NTSTATUS) 0xC0000144L)
-#endif
-
-#ifndef STATUS_APP_INIT_FAILURE
-# define STATUS_APP_INIT_FAILURE ((NTSTATUS) 0xC0000145L)
-#endif
-
-#ifndef STATUS_PAGEFILE_CREATE_FAILED
-# define STATUS_PAGEFILE_CREATE_FAILED ((NTSTATUS) 0xC0000146L)
-#endif
-
-#ifndef STATUS_NO_PAGEFILE
-# define STATUS_NO_PAGEFILE ((NTSTATUS) 0xC0000147L)
-#endif
-
-#ifndef STATUS_INVALID_LEVEL
-# define STATUS_INVALID_LEVEL ((NTSTATUS) 0xC0000148L)
-#endif
-
-#ifndef STATUS_WRONG_PASSWORD_CORE
-# define STATUS_WRONG_PASSWORD_CORE ((NTSTATUS) 0xC0000149L)
-#endif
-
-#ifndef STATUS_ILLEGAL_FLOAT_CONTEXT
-# define STATUS_ILLEGAL_FLOAT_CONTEXT ((NTSTATUS) 0xC000014AL)
-#endif
-
-#ifndef STATUS_PIPE_BROKEN
-# define STATUS_PIPE_BROKEN ((NTSTATUS) 0xC000014BL)
-#endif
-
-#ifndef STATUS_REGISTRY_CORRUPT
-# define STATUS_REGISTRY_CORRUPT ((NTSTATUS) 0xC000014CL)
-#endif
-
-#ifndef STATUS_REGISTRY_IO_FAILED
-# define STATUS_REGISTRY_IO_FAILED ((NTSTATUS) 0xC000014DL)
-#endif
-
-#ifndef STATUS_NO_EVENT_PAIR
-# define STATUS_NO_EVENT_PAIR ((NTSTATUS) 0xC000014EL)
-#endif
-
-#ifndef STATUS_UNRECOGNIZED_VOLUME
-# define STATUS_UNRECOGNIZED_VOLUME ((NTSTATUS) 0xC000014FL)
-#endif
-
-#ifndef STATUS_SERIAL_NO_DEVICE_INITED
-# define STATUS_SERIAL_NO_DEVICE_INITED ((NTSTATUS) 0xC0000150L)
-#endif
-
-#ifndef STATUS_NO_SUCH_ALIAS
-# define STATUS_NO_SUCH_ALIAS ((NTSTATUS) 0xC0000151L)
-#endif
-
-#ifndef STATUS_MEMBER_NOT_IN_ALIAS
-# define STATUS_MEMBER_NOT_IN_ALIAS ((NTSTATUS) 0xC0000152L)
-#endif
-
-#ifndef STATUS_MEMBER_IN_ALIAS
-# define STATUS_MEMBER_IN_ALIAS ((NTSTATUS) 0xC0000153L)
-#endif
-
-#ifndef STATUS_ALIAS_EXISTS
-# define STATUS_ALIAS_EXISTS ((NTSTATUS) 0xC0000154L)
-#endif
-
-#ifndef STATUS_LOGON_NOT_GRANTED
-# define STATUS_LOGON_NOT_GRANTED ((NTSTATUS) 0xC0000155L)
-#endif
-
-#ifndef STATUS_TOO_MANY_SECRETS
-# define STATUS_TOO_MANY_SECRETS ((NTSTATUS) 0xC0000156L)
-#endif
-
-#ifndef STATUS_SECRET_TOO_LONG
-# define STATUS_SECRET_TOO_LONG ((NTSTATUS) 0xC0000157L)
-#endif
-
-#ifndef STATUS_INTERNAL_DB_ERROR
-# define STATUS_INTERNAL_DB_ERROR ((NTSTATUS) 0xC0000158L)
-#endif
-
-#ifndef STATUS_FULLSCREEN_MODE
-# define STATUS_FULLSCREEN_MODE ((NTSTATUS) 0xC0000159L)
-#endif
-
-#ifndef STATUS_TOO_MANY_CONTEXT_IDS
-# define STATUS_TOO_MANY_CONTEXT_IDS ((NTSTATUS) 0xC000015AL)
-#endif
-
-#ifndef STATUS_LOGON_TYPE_NOT_GRANTED
-# define STATUS_LOGON_TYPE_NOT_GRANTED ((NTSTATUS) 0xC000015BL)
-#endif
-
-#ifndef STATUS_NOT_REGISTRY_FILE
-# define STATUS_NOT_REGISTRY_FILE ((NTSTATUS) 0xC000015CL)
-#endif
-
-#ifndef STATUS_NT_CROSS_ENCRYPTION_REQUIRED
-# define STATUS_NT_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000015DL)
-#endif
-
-#ifndef STATUS_DOMAIN_CTRLR_CONFIG_ERROR
-# define STATUS_DOMAIN_CTRLR_CONFIG_ERROR ((NTSTATUS) 0xC000015EL)
-#endif
-
-#ifndef STATUS_FT_MISSING_MEMBER
-# define STATUS_FT_MISSING_MEMBER ((NTSTATUS) 0xC000015FL)
-#endif
-
-#ifndef STATUS_ILL_FORMED_SERVICE_ENTRY
-# define STATUS_ILL_FORMED_SERVICE_ENTRY ((NTSTATUS) 0xC0000160L)
-#endif
-
-#ifndef STATUS_ILLEGAL_CHARACTER
-# define STATUS_ILLEGAL_CHARACTER ((NTSTATUS) 0xC0000161L)
-#endif
-
-#ifndef STATUS_UNMAPPABLE_CHARACTER
-# define STATUS_UNMAPPABLE_CHARACTER ((NTSTATUS) 0xC0000162L)
-#endif
-
-#ifndef STATUS_UNDEFINED_CHARACTER
-# define STATUS_UNDEFINED_CHARACTER ((NTSTATUS) 0xC0000163L)
-#endif
-
-#ifndef STATUS_FLOPPY_VOLUME
-# define STATUS_FLOPPY_VOLUME ((NTSTATUS) 0xC0000164L)
-#endif
-
-#ifndef STATUS_FLOPPY_ID_MARK_NOT_FOUND
-# define STATUS_FLOPPY_ID_MARK_NOT_FOUND ((NTSTATUS) 0xC0000165L)
-#endif
-
-#ifndef STATUS_FLOPPY_WRONG_CYLINDER
-# define STATUS_FLOPPY_WRONG_CYLINDER ((NTSTATUS) 0xC0000166L)
-#endif
-
-#ifndef STATUS_FLOPPY_UNKNOWN_ERROR
-# define STATUS_FLOPPY_UNKNOWN_ERROR ((NTSTATUS) 0xC0000167L)
-#endif
-
-#ifndef STATUS_FLOPPY_BAD_REGISTERS
-# define STATUS_FLOPPY_BAD_REGISTERS ((NTSTATUS) 0xC0000168L)
-#endif
-
-#ifndef STATUS_DISK_RECALIBRATE_FAILED
-# define STATUS_DISK_RECALIBRATE_FAILED ((NTSTATUS) 0xC0000169L)
-#endif
-
-#ifndef STATUS_DISK_OPERATION_FAILED
-# define STATUS_DISK_OPERATION_FAILED ((NTSTATUS) 0xC000016AL)
-#endif
-
-#ifndef STATUS_DISK_RESET_FAILED
-# define STATUS_DISK_RESET_FAILED ((NTSTATUS) 0xC000016BL)
-#endif
-
-#ifndef STATUS_SHARED_IRQ_BUSY
-# define STATUS_SHARED_IRQ_BUSY ((NTSTATUS) 0xC000016CL)
-#endif
-
-#ifndef STATUS_FT_ORPHANING
-# define STATUS_FT_ORPHANING ((NTSTATUS) 0xC000016DL)
-#endif
-
-#ifndef STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT
-# define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT ((NTSTATUS) 0xC000016EL)
-#endif
-
-#ifndef STATUS_PARTITION_FAILURE
-# define STATUS_PARTITION_FAILURE ((NTSTATUS) 0xC0000172L)
-#endif
-
-#ifndef STATUS_INVALID_BLOCK_LENGTH
-# define STATUS_INVALID_BLOCK_LENGTH ((NTSTATUS) 0xC0000173L)
-#endif
-
-#ifndef STATUS_DEVICE_NOT_PARTITIONED
-# define STATUS_DEVICE_NOT_PARTITIONED ((NTSTATUS) 0xC0000174L)
-#endif
-
-#ifndef STATUS_UNABLE_TO_LOCK_MEDIA
-# define STATUS_UNABLE_TO_LOCK_MEDIA ((NTSTATUS) 0xC0000175L)
-#endif
-
-#ifndef STATUS_UNABLE_TO_UNLOAD_MEDIA
-# define STATUS_UNABLE_TO_UNLOAD_MEDIA ((NTSTATUS) 0xC0000176L)
-#endif
-
-#ifndef STATUS_EOM_OVERFLOW
-# define STATUS_EOM_OVERFLOW ((NTSTATUS) 0xC0000177L)
-#endif
-
-#ifndef STATUS_NO_MEDIA
-# define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L)
-#endif
-
-#ifndef STATUS_NO_SUCH_MEMBER
-# define STATUS_NO_SUCH_MEMBER ((NTSTATUS) 0xC000017AL)
-#endif
-
-#ifndef STATUS_INVALID_MEMBER
-# define STATUS_INVALID_MEMBER ((NTSTATUS) 0xC000017BL)
-#endif
-
-#ifndef STATUS_KEY_DELETED
-# define STATUS_KEY_DELETED ((NTSTATUS) 0xC000017CL)
-#endif
-
-#ifndef STATUS_NO_LOG_SPACE
-# define STATUS_NO_LOG_SPACE ((NTSTATUS) 0xC000017DL)
-#endif
-
-#ifndef STATUS_TOO_MANY_SIDS
-# define STATUS_TOO_MANY_SIDS ((NTSTATUS) 0xC000017EL)
-#endif
-
-#ifndef STATUS_LM_CROSS_ENCRYPTION_REQUIRED
-# define STATUS_LM_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000017FL)
-#endif
-
-#ifndef STATUS_KEY_HAS_CHILDREN
-# define STATUS_KEY_HAS_CHILDREN ((NTSTATUS) 0xC0000180L)
-#endif
-
-#ifndef STATUS_CHILD_MUST_BE_VOLATILE
-# define STATUS_CHILD_MUST_BE_VOLATILE ((NTSTATUS) 0xC0000181L)
-#endif
-
-#ifndef STATUS_DEVICE_CONFIGURATION_ERROR
-# define STATUS_DEVICE_CONFIGURATION_ERROR ((NTSTATUS) 0xC0000182L)
-#endif
-
-#ifndef STATUS_DRIVER_INTERNAL_ERROR
-# define STATUS_DRIVER_INTERNAL_ERROR ((NTSTATUS) 0xC0000183L)
-#endif
-
-#ifndef STATUS_INVALID_DEVICE_STATE
-# define STATUS_INVALID_DEVICE_STATE ((NTSTATUS) 0xC0000184L)
-#endif
-
-#ifndef STATUS_IO_DEVICE_ERROR
-# define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L)
-#endif
-
-#ifndef STATUS_DEVICE_PROTOCOL_ERROR
-# define STATUS_DEVICE_PROTOCOL_ERROR ((NTSTATUS) 0xC0000186L)
-#endif
-
-#ifndef STATUS_BACKUP_CONTROLLER
-# define STATUS_BACKUP_CONTROLLER ((NTSTATUS) 0xC0000187L)
-#endif
-
-#ifndef STATUS_LOG_FILE_FULL
-# define STATUS_LOG_FILE_FULL ((NTSTATUS) 0xC0000188L)
-#endif
-
-#ifndef STATUS_TOO_LATE
-# define STATUS_TOO_LATE ((NTSTATUS) 0xC0000189L)
-#endif
-
-#ifndef STATUS_NO_TRUST_LSA_SECRET
-# define STATUS_NO_TRUST_LSA_SECRET ((NTSTATUS) 0xC000018AL)
-#endif
-
-#ifndef STATUS_NO_TRUST_SAM_ACCOUNT
-# define STATUS_NO_TRUST_SAM_ACCOUNT ((NTSTATUS) 0xC000018BL)
-#endif
-
-#ifndef STATUS_TRUSTED_DOMAIN_FAILURE
-# define STATUS_TRUSTED_DOMAIN_FAILURE ((NTSTATUS) 0xC000018CL)
-#endif
-
-#ifndef STATUS_TRUSTED_RELATIONSHIP_FAILURE
-# define STATUS_TRUSTED_RELATIONSHIP_FAILURE ((NTSTATUS) 0xC000018DL)
-#endif
-
-#ifndef STATUS_EVENTLOG_FILE_CORRUPT
-# define STATUS_EVENTLOG_FILE_CORRUPT ((NTSTATUS) 0xC000018EL)
-#endif
-
-#ifndef STATUS_EVENTLOG_CANT_START
-# define STATUS_EVENTLOG_CANT_START ((NTSTATUS) 0xC000018FL)
-#endif
-
-#ifndef STATUS_TRUST_FAILURE
-# define STATUS_TRUST_FAILURE ((NTSTATUS) 0xC0000190L)
-#endif
-
-#ifndef STATUS_MUTANT_LIMIT_EXCEEDED
-# define STATUS_MUTANT_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000191L)
-#endif
-
-#ifndef STATUS_NETLOGON_NOT_STARTED
-# define STATUS_NETLOGON_NOT_STARTED ((NTSTATUS) 0xC0000192L)
-#endif
-
-#ifndef STATUS_ACCOUNT_EXPIRED
-# define STATUS_ACCOUNT_EXPIRED ((NTSTATUS) 0xC0000193L)
-#endif
-
-#ifndef STATUS_POSSIBLE_DEADLOCK
-# define STATUS_POSSIBLE_DEADLOCK ((NTSTATUS) 0xC0000194L)
-#endif
-
-#ifndef STATUS_NETWORK_CREDENTIAL_CONFLICT
-# define STATUS_NETWORK_CREDENTIAL_CONFLICT ((NTSTATUS) 0xC0000195L)
-#endif
-
-#ifndef STATUS_REMOTE_SESSION_LIMIT
-# define STATUS_REMOTE_SESSION_LIMIT ((NTSTATUS) 0xC0000196L)
-#endif
-
-#ifndef STATUS_EVENTLOG_FILE_CHANGED
-# define STATUS_EVENTLOG_FILE_CHANGED ((NTSTATUS) 0xC0000197L)
-#endif
-
-#ifndef STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
-# define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ((NTSTATUS) 0xC0000198L)
-#endif
-
-#ifndef STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
-# define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT ((NTSTATUS) 0xC0000199L)
-#endif
-
-#ifndef STATUS_NOLOGON_SERVER_TRUST_ACCOUNT
-# define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT ((NTSTATUS) 0xC000019AL)
-#endif
-
-#ifndef STATUS_DOMAIN_TRUST_INCONSISTENT
-# define STATUS_DOMAIN_TRUST_INCONSISTENT ((NTSTATUS) 0xC000019BL)
-#endif
-
-#ifndef STATUS_FS_DRIVER_REQUIRED
-# define STATUS_FS_DRIVER_REQUIRED ((NTSTATUS) 0xC000019CL)
-#endif
-
-#ifndef STATUS_IMAGE_ALREADY_LOADED_AS_DLL
-# define STATUS_IMAGE_ALREADY_LOADED_AS_DLL ((NTSTATUS) 0xC000019DL)
-#endif
-
-#ifndef STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING
-# define STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING ((NTSTATUS) 0xC000019EL)
-#endif
-
-#ifndef STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME
-# define STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME ((NTSTATUS) 0xC000019FL)
-#endif
-
-#ifndef STATUS_SECURITY_STREAM_IS_INCONSISTENT
-# define STATUS_SECURITY_STREAM_IS_INCONSISTENT ((NTSTATUS) 0xC00001A0L)
-#endif
-
-#ifndef STATUS_INVALID_LOCK_RANGE
-# define STATUS_INVALID_LOCK_RANGE ((NTSTATUS) 0xC00001A1L)
-#endif
-
-#ifndef STATUS_INVALID_ACE_CONDITION
-# define STATUS_INVALID_ACE_CONDITION ((NTSTATUS) 0xC00001A2L)
-#endif
-
-#ifndef STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT
-# define STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT ((NTSTATUS) 0xC00001A3L)
-#endif
-
-#ifndef STATUS_NOTIFICATION_GUID_ALREADY_DEFINED
-# define STATUS_NOTIFICATION_GUID_ALREADY_DEFINED ((NTSTATUS) 0xC00001A4L)
-#endif
-
-#ifndef STATUS_NETWORK_OPEN_RESTRICTION
-# define STATUS_NETWORK_OPEN_RESTRICTION ((NTSTATUS) 0xC0000201L)
-#endif
-
-#ifndef STATUS_NO_USER_SESSION_KEY
-# define STATUS_NO_USER_SESSION_KEY ((NTSTATUS) 0xC0000202L)
-#endif
-
-#ifndef STATUS_USER_SESSION_DELETED
-# define STATUS_USER_SESSION_DELETED ((NTSTATUS) 0xC0000203L)
-#endif
-
-#ifndef STATUS_RESOURCE_LANG_NOT_FOUND
-# define STATUS_RESOURCE_LANG_NOT_FOUND ((NTSTATUS) 0xC0000204L)
-#endif
-
-#ifndef STATUS_INSUFF_SERVER_RESOURCES
-# define STATUS_INSUFF_SERVER_RESOURCES ((NTSTATUS) 0xC0000205L)
-#endif
-
-#ifndef STATUS_INVALID_BUFFER_SIZE
-# define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS) 0xC0000206L)
-#endif
-
-#ifndef STATUS_INVALID_ADDRESS_COMPONENT
-# define STATUS_INVALID_ADDRESS_COMPONENT ((NTSTATUS) 0xC0000207L)
-#endif
-
-#ifndef STATUS_INVALID_ADDRESS_WILDCARD
-# define STATUS_INVALID_ADDRESS_WILDCARD ((NTSTATUS) 0xC0000208L)
-#endif
-
-#ifndef STATUS_TOO_MANY_ADDRESSES
-# define STATUS_TOO_MANY_ADDRESSES ((NTSTATUS) 0xC0000209L)
-#endif
-
-#ifndef STATUS_ADDRESS_ALREADY_EXISTS
-# define STATUS_ADDRESS_ALREADY_EXISTS ((NTSTATUS) 0xC000020AL)
-#endif
-
-#ifndef STATUS_ADDRESS_CLOSED
-# define STATUS_ADDRESS_CLOSED ((NTSTATUS) 0xC000020BL)
-#endif
-
-#ifndef STATUS_CONNECTION_DISCONNECTED
-# define STATUS_CONNECTION_DISCONNECTED ((NTSTATUS) 0xC000020CL)
-#endif
-
-#ifndef STATUS_CONNECTION_RESET
-# define STATUS_CONNECTION_RESET ((NTSTATUS) 0xC000020DL)
-#endif
-
-#ifndef STATUS_TOO_MANY_NODES
-# define STATUS_TOO_MANY_NODES ((NTSTATUS) 0xC000020EL)
-#endif
-
-#ifndef STATUS_TRANSACTION_ABORTED
-# define STATUS_TRANSACTION_ABORTED ((NTSTATUS) 0xC000020FL)
-#endif
-
-#ifndef STATUS_TRANSACTION_TIMED_OUT
-# define STATUS_TRANSACTION_TIMED_OUT ((NTSTATUS) 0xC0000210L)
-#endif
-
-#ifndef STATUS_TRANSACTION_NO_RELEASE
-# define STATUS_TRANSACTION_NO_RELEASE ((NTSTATUS) 0xC0000211L)
-#endif
-
-#ifndef STATUS_TRANSACTION_NO_MATCH
-# define STATUS_TRANSACTION_NO_MATCH ((NTSTATUS) 0xC0000212L)
-#endif
-
-#ifndef STATUS_TRANSACTION_RESPONDED
-# define STATUS_TRANSACTION_RESPONDED ((NTSTATUS) 0xC0000213L)
-#endif
-
-#ifndef STATUS_TRANSACTION_INVALID_ID
-# define STATUS_TRANSACTION_INVALID_ID ((NTSTATUS) 0xC0000214L)
-#endif
-
-#ifndef STATUS_TRANSACTION_INVALID_TYPE
-# define STATUS_TRANSACTION_INVALID_TYPE ((NTSTATUS) 0xC0000215L)
-#endif
-
-#ifndef STATUS_NOT_SERVER_SESSION
-# define STATUS_NOT_SERVER_SESSION ((NTSTATUS) 0xC0000216L)
-#endif
-
-#ifndef STATUS_NOT_CLIENT_SESSION
-# define STATUS_NOT_CLIENT_SESSION ((NTSTATUS) 0xC0000217L)
-#endif
-
-#ifndef STATUS_CANNOT_LOAD_REGISTRY_FILE
-# define STATUS_CANNOT_LOAD_REGISTRY_FILE ((NTSTATUS) 0xC0000218L)
-#endif
-
-#ifndef STATUS_DEBUG_ATTACH_FAILED
-# define STATUS_DEBUG_ATTACH_FAILED ((NTSTATUS) 0xC0000219L)
-#endif
-
-#ifndef STATUS_SYSTEM_PROCESS_TERMINATED
-# define STATUS_SYSTEM_PROCESS_TERMINATED ((NTSTATUS) 0xC000021AL)
-#endif
-
-#ifndef STATUS_DATA_NOT_ACCEPTED
-# define STATUS_DATA_NOT_ACCEPTED ((NTSTATUS) 0xC000021BL)
-#endif
-
-#ifndef STATUS_NO_BROWSER_SERVERS_FOUND
-# define STATUS_NO_BROWSER_SERVERS_FOUND ((NTSTATUS) 0xC000021CL)
-#endif
-
-#ifndef STATUS_VDM_HARD_ERROR
-# define STATUS_VDM_HARD_ERROR ((NTSTATUS) 0xC000021DL)
-#endif
-
-#ifndef STATUS_DRIVER_CANCEL_TIMEOUT
-# define STATUS_DRIVER_CANCEL_TIMEOUT ((NTSTATUS) 0xC000021EL)
-#endif
-
-#ifndef STATUS_REPLY_MESSAGE_MISMATCH
-# define STATUS_REPLY_MESSAGE_MISMATCH ((NTSTATUS) 0xC000021FL)
-#endif
-
-#ifndef STATUS_MAPPED_ALIGNMENT
-# define STATUS_MAPPED_ALIGNMENT ((NTSTATUS) 0xC0000220L)
-#endif
-
-#ifndef STATUS_IMAGE_CHECKSUM_MISMATCH
-# define STATUS_IMAGE_CHECKSUM_MISMATCH ((NTSTATUS) 0xC0000221L)
-#endif
-
-#ifndef STATUS_LOST_WRITEBEHIND_DATA
-# define STATUS_LOST_WRITEBEHIND_DATA ((NTSTATUS) 0xC0000222L)
-#endif
-
-#ifndef STATUS_CLIENT_SERVER_PARAMETERS_INVALID
-# define STATUS_CLIENT_SERVER_PARAMETERS_INVALID ((NTSTATUS) 0xC0000223L)
-#endif
-
-#ifndef STATUS_PASSWORD_MUST_CHANGE
-# define STATUS_PASSWORD_MUST_CHANGE ((NTSTATUS) 0xC0000224L)
-#endif
-
-#ifndef STATUS_NOT_FOUND
-# define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L)
-#endif
-
-#ifndef STATUS_NOT_TINY_STREAM
-# define STATUS_NOT_TINY_STREAM ((NTSTATUS) 0xC0000226L)
-#endif
-
-#ifndef STATUS_RECOVERY_FAILURE
-# define STATUS_RECOVERY_FAILURE ((NTSTATUS) 0xC0000227L)
-#endif
-
-#ifndef STATUS_STACK_OVERFLOW_READ
-# define STATUS_STACK_OVERFLOW_READ ((NTSTATUS) 0xC0000228L)
-#endif
-
-#ifndef STATUS_FAIL_CHECK
-# define STATUS_FAIL_CHECK ((NTSTATUS) 0xC0000229L)
-#endif
-
-#ifndef STATUS_DUPLICATE_OBJECTID
-# define STATUS_DUPLICATE_OBJECTID ((NTSTATUS) 0xC000022AL)
-#endif
-
-#ifndef STATUS_OBJECTID_EXISTS
-# define STATUS_OBJECTID_EXISTS ((NTSTATUS) 0xC000022BL)
-#endif
-
-#ifndef STATUS_CONVERT_TO_LARGE
-# define STATUS_CONVERT_TO_LARGE ((NTSTATUS) 0xC000022CL)
-#endif
-
-#ifndef STATUS_RETRY
-# define STATUS_RETRY ((NTSTATUS) 0xC000022DL)
-#endif
-
-#ifndef STATUS_FOUND_OUT_OF_SCOPE
-# define STATUS_FOUND_OUT_OF_SCOPE ((NTSTATUS) 0xC000022EL)
-#endif
-
-#ifndef STATUS_ALLOCATE_BUCKET
-# define STATUS_ALLOCATE_BUCKET ((NTSTATUS) 0xC000022FL)
-#endif
-
-#ifndef STATUS_PROPSET_NOT_FOUND
-# define STATUS_PROPSET_NOT_FOUND ((NTSTATUS) 0xC0000230L)
-#endif
-
-#ifndef STATUS_MARSHALL_OVERFLOW
-# define STATUS_MARSHALL_OVERFLOW ((NTSTATUS) 0xC0000231L)
-#endif
-
-#ifndef STATUS_INVALID_VARIANT
-# define STATUS_INVALID_VARIANT ((NTSTATUS) 0xC0000232L)
-#endif
-
-#ifndef STATUS_DOMAIN_CONTROLLER_NOT_FOUND
-# define STATUS_DOMAIN_CONTROLLER_NOT_FOUND ((NTSTATUS) 0xC0000233L)
-#endif
-
-#ifndef STATUS_ACCOUNT_LOCKED_OUT
-# define STATUS_ACCOUNT_LOCKED_OUT ((NTSTATUS) 0xC0000234L)
-#endif
-
-#ifndef STATUS_HANDLE_NOT_CLOSABLE
-# define STATUS_HANDLE_NOT_CLOSABLE ((NTSTATUS) 0xC0000235L)
-#endif
-
-#ifndef STATUS_CONNECTION_REFUSED
-# define STATUS_CONNECTION_REFUSED ((NTSTATUS) 0xC0000236L)
-#endif
-
-#ifndef STATUS_GRACEFUL_DISCONNECT
-# define STATUS_GRACEFUL_DISCONNECT ((NTSTATUS) 0xC0000237L)
-#endif
-
-#ifndef STATUS_ADDRESS_ALREADY_ASSOCIATED
-# define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS) 0xC0000238L)
-#endif
-
-#ifndef STATUS_ADDRESS_NOT_ASSOCIATED
-# define STATUS_ADDRESS_NOT_ASSOCIATED ((NTSTATUS) 0xC0000239L)
-#endif
-
-#ifndef STATUS_CONNECTION_INVALID
-# define STATUS_CONNECTION_INVALID ((NTSTATUS) 0xC000023AL)
-#endif
-
-#ifndef STATUS_CONNECTION_ACTIVE
-# define STATUS_CONNECTION_ACTIVE ((NTSTATUS) 0xC000023BL)
-#endif
-
-#ifndef STATUS_NETWORK_UNREACHABLE
-# define STATUS_NETWORK_UNREACHABLE ((NTSTATUS) 0xC000023CL)
-#endif
-
-#ifndef STATUS_HOST_UNREACHABLE
-# define STATUS_HOST_UNREACHABLE ((NTSTATUS) 0xC000023DL)
-#endif
-
-#ifndef STATUS_PROTOCOL_UNREACHABLE
-# define STATUS_PROTOCOL_UNREACHABLE ((NTSTATUS) 0xC000023EL)
-#endif
-
-#ifndef STATUS_PORT_UNREACHABLE
-# define STATUS_PORT_UNREACHABLE ((NTSTATUS) 0xC000023FL)
-#endif
-
-#ifndef STATUS_REQUEST_ABORTED
-# define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L)
-#endif
-
-#ifndef STATUS_CONNECTION_ABORTED
-# define STATUS_CONNECTION_ABORTED ((NTSTATUS) 0xC0000241L)
-#endif
-
-#ifndef STATUS_BAD_COMPRESSION_BUFFER
-# define STATUS_BAD_COMPRESSION_BUFFER ((NTSTATUS) 0xC0000242L)
-#endif
-
-#ifndef STATUS_USER_MAPPED_FILE
-# define STATUS_USER_MAPPED_FILE ((NTSTATUS) 0xC0000243L)
-#endif
-
-#ifndef STATUS_AUDIT_FAILED
-# define STATUS_AUDIT_FAILED ((NTSTATUS) 0xC0000244L)
-#endif
-
-#ifndef STATUS_TIMER_RESOLUTION_NOT_SET
-# define STATUS_TIMER_RESOLUTION_NOT_SET ((NTSTATUS) 0xC0000245L)
-#endif
-
-#ifndef STATUS_CONNECTION_COUNT_LIMIT
-# define STATUS_CONNECTION_COUNT_LIMIT ((NTSTATUS) 0xC0000246L)
-#endif
-
-#ifndef STATUS_LOGIN_TIME_RESTRICTION
-# define STATUS_LOGIN_TIME_RESTRICTION ((NTSTATUS) 0xC0000247L)
-#endif
-
-#ifndef STATUS_LOGIN_WKSTA_RESTRICTION
-# define STATUS_LOGIN_WKSTA_RESTRICTION ((NTSTATUS) 0xC0000248L)
-#endif
-
-#ifndef STATUS_IMAGE_MP_UP_MISMATCH
-# define STATUS_IMAGE_MP_UP_MISMATCH ((NTSTATUS) 0xC0000249L)
-#endif
-
-#ifndef STATUS_INSUFFICIENT_LOGON_INFO
-# define STATUS_INSUFFICIENT_LOGON_INFO ((NTSTATUS) 0xC0000250L)
-#endif
-
-#ifndef STATUS_BAD_DLL_ENTRYPOINT
-# define STATUS_BAD_DLL_ENTRYPOINT ((NTSTATUS) 0xC0000251L)
-#endif
-
-#ifndef STATUS_BAD_SERVICE_ENTRYPOINT
-# define STATUS_BAD_SERVICE_ENTRYPOINT ((NTSTATUS) 0xC0000252L)
-#endif
-
-#ifndef STATUS_LPC_REPLY_LOST
-# define STATUS_LPC_REPLY_LOST ((NTSTATUS) 0xC0000253L)
-#endif
-
-#ifndef STATUS_IP_ADDRESS_CONFLICT1
-# define STATUS_IP_ADDRESS_CONFLICT1 ((NTSTATUS) 0xC0000254L)
-#endif
-
-#ifndef STATUS_IP_ADDRESS_CONFLICT2
-# define STATUS_IP_ADDRESS_CONFLICT2 ((NTSTATUS) 0xC0000255L)
-#endif
-
-#ifndef STATUS_REGISTRY_QUOTA_LIMIT
-# define STATUS_REGISTRY_QUOTA_LIMIT ((NTSTATUS) 0xC0000256L)
-#endif
-
-#ifndef STATUS_PATH_NOT_COVERED
-# define STATUS_PATH_NOT_COVERED ((NTSTATUS) 0xC0000257L)
-#endif
-
-#ifndef STATUS_NO_CALLBACK_ACTIVE
-# define STATUS_NO_CALLBACK_ACTIVE ((NTSTATUS) 0xC0000258L)
-#endif
-
-#ifndef STATUS_LICENSE_QUOTA_EXCEEDED
-# define STATUS_LICENSE_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000259L)
-#endif
-
-#ifndef STATUS_PWD_TOO_SHORT
-# define STATUS_PWD_TOO_SHORT ((NTSTATUS) 0xC000025AL)
-#endif
-
-#ifndef STATUS_PWD_TOO_RECENT
-# define STATUS_PWD_TOO_RECENT ((NTSTATUS) 0xC000025BL)
-#endif
-
-#ifndef STATUS_PWD_HISTORY_CONFLICT
-# define STATUS_PWD_HISTORY_CONFLICT ((NTSTATUS) 0xC000025CL)
-#endif
-
-#ifndef STATUS_PLUGPLAY_NO_DEVICE
-# define STATUS_PLUGPLAY_NO_DEVICE ((NTSTATUS) 0xC000025EL)
-#endif
-
-#ifndef STATUS_UNSUPPORTED_COMPRESSION
-# define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS) 0xC000025FL)
-#endif
-
-#ifndef STATUS_INVALID_HW_PROFILE
-# define STATUS_INVALID_HW_PROFILE ((NTSTATUS) 0xC0000260L)
-#endif
-
-#ifndef STATUS_INVALID_PLUGPLAY_DEVICE_PATH
-# define STATUS_INVALID_PLUGPLAY_DEVICE_PATH ((NTSTATUS) 0xC0000261L)
-#endif
-
-#ifndef STATUS_DRIVER_ORDINAL_NOT_FOUND
-# define STATUS_DRIVER_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000262L)
-#endif
-
-#ifndef STATUS_DRIVER_ENTRYPOINT_NOT_FOUND
-# define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000263L)
-#endif
-
-#ifndef STATUS_RESOURCE_NOT_OWNED
-# define STATUS_RESOURCE_NOT_OWNED ((NTSTATUS) 0xC0000264L)
-#endif
-
-#ifndef STATUS_TOO_MANY_LINKS
-# define STATUS_TOO_MANY_LINKS ((NTSTATUS) 0xC0000265L)
-#endif
-
-#ifndef STATUS_QUOTA_LIST_INCONSISTENT
-# define STATUS_QUOTA_LIST_INCONSISTENT ((NTSTATUS) 0xC0000266L)
-#endif
-
-#ifndef STATUS_FILE_IS_OFFLINE
-# define STATUS_FILE_IS_OFFLINE ((NTSTATUS) 0xC0000267L)
-#endif
-
-#ifndef STATUS_EVALUATION_EXPIRATION
-# define STATUS_EVALUATION_EXPIRATION ((NTSTATUS) 0xC0000268L)
-#endif
-
-#ifndef STATUS_ILLEGAL_DLL_RELOCATION
-# define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xC0000269L)
-#endif
-
-#ifndef STATUS_LICENSE_VIOLATION
-# define STATUS_LICENSE_VIOLATION ((NTSTATUS) 0xC000026AL)
-#endif
-
-#ifndef STATUS_DLL_INIT_FAILED_LOGOFF
-# define STATUS_DLL_INIT_FAILED_LOGOFF ((NTSTATUS) 0xC000026BL)
-#endif
-
-#ifndef STATUS_DRIVER_UNABLE_TO_LOAD
-# define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL)
-#endif
-
-#ifndef STATUS_DFS_UNAVAILABLE
-# define STATUS_DFS_UNAVAILABLE ((NTSTATUS) 0xC000026DL)
-#endif
-
-#ifndef STATUS_VOLUME_DISMOUNTED
-# define STATUS_VOLUME_DISMOUNTED ((NTSTATUS) 0xC000026EL)
-#endif
-
-#ifndef STATUS_WX86_INTERNAL_ERROR
-# define STATUS_WX86_INTERNAL_ERROR ((NTSTATUS) 0xC000026FL)
-#endif
-
-#ifndef STATUS_WX86_FLOAT_STACK_CHECK
-# define STATUS_WX86_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000270L)
-#endif
-
-#ifndef STATUS_VALIDATE_CONTINUE
-# define STATUS_VALIDATE_CONTINUE ((NTSTATUS) 0xC0000271L)
-#endif
-
-#ifndef STATUS_NO_MATCH
-# define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L)
-#endif
-
-#ifndef STATUS_NO_MORE_MATCHES
-# define STATUS_NO_MORE_MATCHES ((NTSTATUS) 0xC0000273L)
-#endif
-
-#ifndef STATUS_NOT_A_REPARSE_POINT
-# define STATUS_NOT_A_REPARSE_POINT ((NTSTATUS) 0xC0000275L)
-#endif
-
-#ifndef STATUS_IO_REPARSE_TAG_INVALID
-# define STATUS_IO_REPARSE_TAG_INVALID ((NTSTATUS) 0xC0000276L)
-#endif
-
-#ifndef STATUS_IO_REPARSE_TAG_MISMATCH
-# define STATUS_IO_REPARSE_TAG_MISMATCH ((NTSTATUS) 0xC0000277L)
-#endif
-
-#ifndef STATUS_IO_REPARSE_DATA_INVALID
-# define STATUS_IO_REPARSE_DATA_INVALID ((NTSTATUS) 0xC0000278L)
-#endif
-
-#ifndef STATUS_IO_REPARSE_TAG_NOT_HANDLED
-# define STATUS_IO_REPARSE_TAG_NOT_HANDLED ((NTSTATUS) 0xC0000279L)
-#endif
-
-#ifndef STATUS_REPARSE_POINT_NOT_RESOLVED
-# define STATUS_REPARSE_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000280L)
-#endif
-
-#ifndef STATUS_DIRECTORY_IS_A_REPARSE_POINT
-# define STATUS_DIRECTORY_IS_A_REPARSE_POINT ((NTSTATUS) 0xC0000281L)
-#endif
-
-#ifndef STATUS_RANGE_LIST_CONFLICT
-# define STATUS_RANGE_LIST_CONFLICT ((NTSTATUS) 0xC0000282L)
-#endif
-
-#ifndef STATUS_SOURCE_ELEMENT_EMPTY
-# define STATUS_SOURCE_ELEMENT_EMPTY ((NTSTATUS) 0xC0000283L)
-#endif
-
-#ifndef STATUS_DESTINATION_ELEMENT_FULL
-# define STATUS_DESTINATION_ELEMENT_FULL ((NTSTATUS) 0xC0000284L)
-#endif
-
-#ifndef STATUS_ILLEGAL_ELEMENT_ADDRESS
-# define STATUS_ILLEGAL_ELEMENT_ADDRESS ((NTSTATUS) 0xC0000285L)
-#endif
-
-#ifndef STATUS_MAGAZINE_NOT_PRESENT
-# define STATUS_MAGAZINE_NOT_PRESENT ((NTSTATUS) 0xC0000286L)
-#endif
-
-#ifndef STATUS_REINITIALIZATION_NEEDED
-# define STATUS_REINITIALIZATION_NEEDED ((NTSTATUS) 0xC0000287L)
-#endif
-
-#ifndef STATUS_DEVICE_REQUIRES_CLEANING
-# define STATUS_DEVICE_REQUIRES_CLEANING ((NTSTATUS) 0x80000288L)
-#endif
-
-#ifndef STATUS_DEVICE_DOOR_OPEN
-# define STATUS_DEVICE_DOOR_OPEN ((NTSTATUS) 0x80000289L)
-#endif
-
-#ifndef STATUS_ENCRYPTION_FAILED
-# define STATUS_ENCRYPTION_FAILED ((NTSTATUS) 0xC000028AL)
-#endif
-
-#ifndef STATUS_DECRYPTION_FAILED
-# define STATUS_DECRYPTION_FAILED ((NTSTATUS) 0xC000028BL)
-#endif
-
-#ifndef STATUS_RANGE_NOT_FOUND
-# define STATUS_RANGE_NOT_FOUND ((NTSTATUS) 0xC000028CL)
-#endif
-
-#ifndef STATUS_NO_RECOVERY_POLICY
-# define STATUS_NO_RECOVERY_POLICY ((NTSTATUS) 0xC000028DL)
-#endif
-
-#ifndef STATUS_NO_EFS
-# define STATUS_NO_EFS ((NTSTATUS) 0xC000028EL)
-#endif
-
-#ifndef STATUS_WRONG_EFS
-# define STATUS_WRONG_EFS ((NTSTATUS) 0xC000028FL)
-#endif
-
-#ifndef STATUS_NO_USER_KEYS
-# define STATUS_NO_USER_KEYS ((NTSTATUS) 0xC0000290L)
-#endif
-
-#ifndef STATUS_FILE_NOT_ENCRYPTED
-# define STATUS_FILE_NOT_ENCRYPTED ((NTSTATUS) 0xC0000291L)
-#endif
-
-#ifndef STATUS_NOT_EXPORT_FORMAT
-# define STATUS_NOT_EXPORT_FORMAT ((NTSTATUS) 0xC0000292L)
-#endif
-
-#ifndef STATUS_FILE_ENCRYPTED
-# define STATUS_FILE_ENCRYPTED ((NTSTATUS) 0xC0000293L)
-#endif
-
-#ifndef STATUS_WAKE_SYSTEM
-# define STATUS_WAKE_SYSTEM ((NTSTATUS) 0x40000294L)
-#endif
-
-#ifndef STATUS_WMI_GUID_NOT_FOUND
-# define STATUS_WMI_GUID_NOT_FOUND ((NTSTATUS) 0xC0000295L)
-#endif
-
-#ifndef STATUS_WMI_INSTANCE_NOT_FOUND
-# define STATUS_WMI_INSTANCE_NOT_FOUND ((NTSTATUS) 0xC0000296L)
-#endif
-
-#ifndef STATUS_WMI_ITEMID_NOT_FOUND
-# define STATUS_WMI_ITEMID_NOT_FOUND ((NTSTATUS) 0xC0000297L)
-#endif
-
-#ifndef STATUS_WMI_TRY_AGAIN
-# define STATUS_WMI_TRY_AGAIN ((NTSTATUS) 0xC0000298L)
-#endif
-
-#ifndef STATUS_SHARED_POLICY
-# define STATUS_SHARED_POLICY ((NTSTATUS) 0xC0000299L)
-#endif
-
-#ifndef STATUS_POLICY_OBJECT_NOT_FOUND
-# define STATUS_POLICY_OBJECT_NOT_FOUND ((NTSTATUS) 0xC000029AL)
-#endif
-
-#ifndef STATUS_POLICY_ONLY_IN_DS
-# define STATUS_POLICY_ONLY_IN_DS ((NTSTATUS) 0xC000029BL)
-#endif
-
-#ifndef STATUS_VOLUME_NOT_UPGRADED
-# define STATUS_VOLUME_NOT_UPGRADED ((NTSTATUS) 0xC000029CL)
-#endif
-
-#ifndef STATUS_REMOTE_STORAGE_NOT_ACTIVE
-# define STATUS_REMOTE_STORAGE_NOT_ACTIVE ((NTSTATUS) 0xC000029DL)
-#endif
-
-#ifndef STATUS_REMOTE_STORAGE_MEDIA_ERROR
-# define STATUS_REMOTE_STORAGE_MEDIA_ERROR ((NTSTATUS) 0xC000029EL)
-#endif
-
-#ifndef STATUS_NO_TRACKING_SERVICE
-# define STATUS_NO_TRACKING_SERVICE ((NTSTATUS) 0xC000029FL)
-#endif
-
-#ifndef STATUS_SERVER_SID_MISMATCH
-# define STATUS_SERVER_SID_MISMATCH ((NTSTATUS) 0xC00002A0L)
-#endif
-
-#ifndef STATUS_DS_NO_ATTRIBUTE_OR_VALUE
-# define STATUS_DS_NO_ATTRIBUTE_OR_VALUE ((NTSTATUS) 0xC00002A1L)
-#endif
-
-#ifndef STATUS_DS_INVALID_ATTRIBUTE_SYNTAX
-# define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX ((NTSTATUS) 0xC00002A2L)
-#endif
-
-#ifndef STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED
-# define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED ((NTSTATUS) 0xC00002A3L)
-#endif
-
-#ifndef STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS
-# define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS ((NTSTATUS) 0xC00002A4L)
-#endif
-
-#ifndef STATUS_DS_BUSY
-# define STATUS_DS_BUSY ((NTSTATUS) 0xC00002A5L)
-#endif
-
-#ifndef STATUS_DS_UNAVAILABLE
-# define STATUS_DS_UNAVAILABLE ((NTSTATUS) 0xC00002A6L)
-#endif
-
-#ifndef STATUS_DS_NO_RIDS_ALLOCATED
-# define STATUS_DS_NO_RIDS_ALLOCATED ((NTSTATUS) 0xC00002A7L)
-#endif
-
-#ifndef STATUS_DS_NO_MORE_RIDS
-# define STATUS_DS_NO_MORE_RIDS ((NTSTATUS) 0xC00002A8L)
-#endif
-
-#ifndef STATUS_DS_INCORRECT_ROLE_OWNER
-# define STATUS_DS_INCORRECT_ROLE_OWNER ((NTSTATUS) 0xC00002A9L)
-#endif
-
-#ifndef STATUS_DS_RIDMGR_INIT_ERROR
-# define STATUS_DS_RIDMGR_INIT_ERROR ((NTSTATUS) 0xC00002AAL)
-#endif
-
-#ifndef STATUS_DS_OBJ_CLASS_VIOLATION
-# define STATUS_DS_OBJ_CLASS_VIOLATION ((NTSTATUS) 0xC00002ABL)
-#endif
-
-#ifndef STATUS_DS_CANT_ON_NON_LEAF
-# define STATUS_DS_CANT_ON_NON_LEAF ((NTSTATUS) 0xC00002ACL)
-#endif
-
-#ifndef STATUS_DS_CANT_ON_RDN
-# define STATUS_DS_CANT_ON_RDN ((NTSTATUS) 0xC00002ADL)
-#endif
-
-#ifndef STATUS_DS_CANT_MOD_OBJ_CLASS
-# define STATUS_DS_CANT_MOD_OBJ_CLASS ((NTSTATUS) 0xC00002AEL)
-#endif
-
-#ifndef STATUS_DS_CROSS_DOM_MOVE_FAILED
-# define STATUS_DS_CROSS_DOM_MOVE_FAILED ((NTSTATUS) 0xC00002AFL)
-#endif
-
-#ifndef STATUS_DS_GC_NOT_AVAILABLE
-# define STATUS_DS_GC_NOT_AVAILABLE ((NTSTATUS) 0xC00002B0L)
-#endif
-
-#ifndef STATUS_DIRECTORY_SERVICE_REQUIRED
-# define STATUS_DIRECTORY_SERVICE_REQUIRED ((NTSTATUS) 0xC00002B1L)
-#endif
-
-#ifndef STATUS_REPARSE_ATTRIBUTE_CONFLICT
-# define STATUS_REPARSE_ATTRIBUTE_CONFLICT ((NTSTATUS) 0xC00002B2L)
-#endif
-
-#ifndef STATUS_CANT_ENABLE_DENY_ONLY
-# define STATUS_CANT_ENABLE_DENY_ONLY ((NTSTATUS) 0xC00002B3L)
-#endif
-
-#ifndef STATUS_FLOAT_MULTIPLE_FAULTS
-# define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS) 0xC00002B4L)
-#endif
-
-#ifndef STATUS_FLOAT_MULTIPLE_TRAPS
-# define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS) 0xC00002B5L)
-#endif
-
-#ifndef STATUS_DEVICE_REMOVED
-# define STATUS_DEVICE_REMOVED ((NTSTATUS) 0xC00002B6L)
-#endif
-
-#ifndef STATUS_JOURNAL_DELETE_IN_PROGRESS
-# define STATUS_JOURNAL_DELETE_IN_PROGRESS ((NTSTATUS) 0xC00002B7L)
-#endif
-
-#ifndef STATUS_JOURNAL_NOT_ACTIVE
-# define STATUS_JOURNAL_NOT_ACTIVE ((NTSTATUS) 0xC00002B8L)
-#endif
-
-#ifndef STATUS_NOINTERFACE
-# define STATUS_NOINTERFACE ((NTSTATUS) 0xC00002B9L)
-#endif
-
-#ifndef STATUS_DS_ADMIN_LIMIT_EXCEEDED
-# define STATUS_DS_ADMIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00002C1L)
-#endif
-
-#ifndef STATUS_DRIVER_FAILED_SLEEP
-# define STATUS_DRIVER_FAILED_SLEEP ((NTSTATUS) 0xC00002C2L)
-#endif
-
-#ifndef STATUS_MUTUAL_AUTHENTICATION_FAILED
-# define STATUS_MUTUAL_AUTHENTICATION_FAILED ((NTSTATUS) 0xC00002C3L)
-#endif
-
-#ifndef STATUS_CORRUPT_SYSTEM_FILE
-# define STATUS_CORRUPT_SYSTEM_FILE ((NTSTATUS) 0xC00002C4L)
-#endif
-
-#ifndef STATUS_DATATYPE_MISALIGNMENT_ERROR
-# define STATUS_DATATYPE_MISALIGNMENT_ERROR ((NTSTATUS) 0xC00002C5L)
-#endif
-
-#ifndef STATUS_WMI_READ_ONLY
-# define STATUS_WMI_READ_ONLY ((NTSTATUS) 0xC00002C6L)
-#endif
-
-#ifndef STATUS_WMI_SET_FAILURE
-# define STATUS_WMI_SET_FAILURE ((NTSTATUS) 0xC00002C7L)
-#endif
-
-#ifndef STATUS_COMMITMENT_MINIMUM
-# define STATUS_COMMITMENT_MINIMUM ((NTSTATUS) 0xC00002C8L)
-#endif
-
-#ifndef STATUS_REG_NAT_CONSUMPTION
-# define STATUS_REG_NAT_CONSUMPTION ((NTSTATUS) 0xC00002C9L)
-#endif
-
-#ifndef STATUS_TRANSPORT_FULL
-# define STATUS_TRANSPORT_FULL ((NTSTATUS) 0xC00002CAL)
-#endif
-
-#ifndef STATUS_DS_SAM_INIT_FAILURE
-# define STATUS_DS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002CBL)
-#endif
-
-#ifndef STATUS_ONLY_IF_CONNECTED
-# define STATUS_ONLY_IF_CONNECTED ((NTSTATUS) 0xC00002CCL)
-#endif
-
-#ifndef STATUS_DS_SENSITIVE_GROUP_VIOLATION
-# define STATUS_DS_SENSITIVE_GROUP_VIOLATION ((NTSTATUS) 0xC00002CDL)
-#endif
-
-#ifndef STATUS_PNP_RESTART_ENUMERATION
-# define STATUS_PNP_RESTART_ENUMERATION ((NTSTATUS) 0xC00002CEL)
-#endif
-
-#ifndef STATUS_JOURNAL_ENTRY_DELETED
-# define STATUS_JOURNAL_ENTRY_DELETED ((NTSTATUS) 0xC00002CFL)
-#endif
-
-#ifndef STATUS_DS_CANT_MOD_PRIMARYGROUPID
-# define STATUS_DS_CANT_MOD_PRIMARYGROUPID ((NTSTATUS) 0xC00002D0L)
-#endif
-
-#ifndef STATUS_SYSTEM_IMAGE_BAD_SIGNATURE
-# define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE ((NTSTATUS) 0xC00002D1L)
-#endif
-
-#ifndef STATUS_PNP_REBOOT_REQUIRED
-# define STATUS_PNP_REBOOT_REQUIRED ((NTSTATUS) 0xC00002D2L)
-#endif
-
-#ifndef STATUS_POWER_STATE_INVALID
-# define STATUS_POWER_STATE_INVALID ((NTSTATUS) 0xC00002D3L)
-#endif
-
-#ifndef STATUS_DS_INVALID_GROUP_TYPE
-# define STATUS_DS_INVALID_GROUP_TYPE ((NTSTATUS) 0xC00002D4L)
-#endif
-
-#ifndef STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN
-# define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D5L)
-#endif
-
-#ifndef STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN
-# define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D6L)
-#endif
-
-#ifndef STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER
-# define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D7L)
-#endif
-
-#ifndef STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER
-# define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC00002D8L)
-#endif
-
-#ifndef STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER
-# define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D9L)
-#endif
-
-#ifndef STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER
-# define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER ((NTSTATUS) 0xC00002DAL)
-#endif
-
-#ifndef STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER
-# define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER ((NTSTATUS) 0xC00002DBL)
-#endif
-
-#ifndef STATUS_DS_HAVE_PRIMARY_MEMBERS
-# define STATUS_DS_HAVE_PRIMARY_MEMBERS ((NTSTATUS) 0xC00002DCL)
-#endif
-
-#ifndef STATUS_WMI_NOT_SUPPORTED
-# define STATUS_WMI_NOT_SUPPORTED ((NTSTATUS) 0xC00002DDL)
-#endif
-
-#ifndef STATUS_INSUFFICIENT_POWER
-# define STATUS_INSUFFICIENT_POWER ((NTSTATUS) 0xC00002DEL)
-#endif
-
-#ifndef STATUS_SAM_NEED_BOOTKEY_PASSWORD
-# define STATUS_SAM_NEED_BOOTKEY_PASSWORD ((NTSTATUS) 0xC00002DFL)
-#endif
-
-#ifndef STATUS_SAM_NEED_BOOTKEY_FLOPPY
-# define STATUS_SAM_NEED_BOOTKEY_FLOPPY ((NTSTATUS) 0xC00002E0L)
-#endif
-
-#ifndef STATUS_DS_CANT_START
-# define STATUS_DS_CANT_START ((NTSTATUS) 0xC00002E1L)
-#endif
-
-#ifndef STATUS_DS_INIT_FAILURE
-# define STATUS_DS_INIT_FAILURE ((NTSTATUS) 0xC00002E2L)
-#endif
-
-#ifndef STATUS_SAM_INIT_FAILURE
-# define STATUS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002E3L)
-#endif
-
-#ifndef STATUS_DS_GC_REQUIRED
-# define STATUS_DS_GC_REQUIRED ((NTSTATUS) 0xC00002E4L)
-#endif
-
-#ifndef STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY
-# define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY ((NTSTATUS) 0xC00002E5L)
-#endif
-
-#ifndef STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS
-# define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS ((NTSTATUS) 0xC00002E6L)
-#endif
-
-#ifndef STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED
-# define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED ((NTSTATUS) 0xC00002E7L)
-#endif
-
-#ifndef STATUS_MULTIPLE_FAULT_VIOLATION
-# define STATUS_MULTIPLE_FAULT_VIOLATION ((NTSTATUS) 0xC00002E8L)
-#endif
-
-#ifndef STATUS_CURRENT_DOMAIN_NOT_ALLOWED
-# define STATUS_CURRENT_DOMAIN_NOT_ALLOWED ((NTSTATUS) 0xC00002E9L)
-#endif
-
-#ifndef STATUS_CANNOT_MAKE
-# define STATUS_CANNOT_MAKE ((NTSTATUS) 0xC00002EAL)
-#endif
-
-#ifndef STATUS_SYSTEM_SHUTDOWN
-# define STATUS_SYSTEM_SHUTDOWN ((NTSTATUS) 0xC00002EBL)
-#endif
-
-#ifndef STATUS_DS_INIT_FAILURE_CONSOLE
-# define STATUS_DS_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002ECL)
-#endif
-
-#ifndef STATUS_DS_SAM_INIT_FAILURE_CONSOLE
-# define STATUS_DS_SAM_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002EDL)
-#endif
-
-#ifndef STATUS_UNFINISHED_CONTEXT_DELETED
-# define STATUS_UNFINISHED_CONTEXT_DELETED ((NTSTATUS) 0xC00002EEL)
-#endif
-
-#ifndef STATUS_NO_TGT_REPLY
-# define STATUS_NO_TGT_REPLY ((NTSTATUS) 0xC00002EFL)
-#endif
-
-#ifndef STATUS_OBJECTID_NOT_FOUND
-# define STATUS_OBJECTID_NOT_FOUND ((NTSTATUS) 0xC00002F0L)
-#endif
-
-#ifndef STATUS_NO_IP_ADDRESSES
-# define STATUS_NO_IP_ADDRESSES ((NTSTATUS) 0xC00002F1L)
-#endif
-
-#ifndef STATUS_WRONG_CREDENTIAL_HANDLE
-# define STATUS_WRONG_CREDENTIAL_HANDLE ((NTSTATUS) 0xC00002F2L)
-#endif
-
-#ifndef STATUS_CRYPTO_SYSTEM_INVALID
-# define STATUS_CRYPTO_SYSTEM_INVALID ((NTSTATUS) 0xC00002F3L)
-#endif
-
-#ifndef STATUS_MAX_REFERRALS_EXCEEDED
-# define STATUS_MAX_REFERRALS_EXCEEDED ((NTSTATUS) 0xC00002F4L)
-#endif
-
-#ifndef STATUS_MUST_BE_KDC
-# define STATUS_MUST_BE_KDC ((NTSTATUS) 0xC00002F5L)
-#endif
-
-#ifndef STATUS_STRONG_CRYPTO_NOT_SUPPORTED
-# define STATUS_STRONG_CRYPTO_NOT_SUPPORTED ((NTSTATUS) 0xC00002F6L)
-#endif
-
-#ifndef STATUS_TOO_MANY_PRINCIPALS
-# define STATUS_TOO_MANY_PRINCIPALS ((NTSTATUS) 0xC00002F7L)
-#endif
-
-#ifndef STATUS_NO_PA_DATA
-# define STATUS_NO_PA_DATA ((NTSTATUS) 0xC00002F8L)
-#endif
-
-#ifndef STATUS_PKINIT_NAME_MISMATCH
-# define STATUS_PKINIT_NAME_MISMATCH ((NTSTATUS) 0xC00002F9L)
-#endif
-
-#ifndef STATUS_SMARTCARD_LOGON_REQUIRED
-# define STATUS_SMARTCARD_LOGON_REQUIRED ((NTSTATUS) 0xC00002FAL)
-#endif
-
-#ifndef STATUS_KDC_INVALID_REQUEST
-# define STATUS_KDC_INVALID_REQUEST ((NTSTATUS) 0xC00002FBL)
-#endif
-
-#ifndef STATUS_KDC_UNABLE_TO_REFER
-# define STATUS_KDC_UNABLE_TO_REFER ((NTSTATUS) 0xC00002FCL)
-#endif
-
-#ifndef STATUS_KDC_UNKNOWN_ETYPE
-# define STATUS_KDC_UNKNOWN_ETYPE ((NTSTATUS) 0xC00002FDL)
-#endif
-
-#ifndef STATUS_SHUTDOWN_IN_PROGRESS
-# define STATUS_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FEL)
-#endif
-
-#ifndef STATUS_SERVER_SHUTDOWN_IN_PROGRESS
-# define STATUS_SERVER_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FFL)
-#endif
-
-#ifndef STATUS_NOT_SUPPORTED_ON_SBS
-# define STATUS_NOT_SUPPORTED_ON_SBS ((NTSTATUS) 0xC0000300L)
-#endif
-
-#ifndef STATUS_WMI_GUID_DISCONNECTED
-# define STATUS_WMI_GUID_DISCONNECTED ((NTSTATUS) 0xC0000301L)
-#endif
-
-#ifndef STATUS_WMI_ALREADY_DISABLED
-# define STATUS_WMI_ALREADY_DISABLED ((NTSTATUS) 0xC0000302L)
-#endif
-
-#ifndef STATUS_WMI_ALREADY_ENABLED
-# define STATUS_WMI_ALREADY_ENABLED ((NTSTATUS) 0xC0000303L)
-#endif
-
-#ifndef STATUS_MFT_TOO_FRAGMENTED
-# define STATUS_MFT_TOO_FRAGMENTED ((NTSTATUS) 0xC0000304L)
-#endif
-
-#ifndef STATUS_COPY_PROTECTION_FAILURE
-# define STATUS_COPY_PROTECTION_FAILURE ((NTSTATUS) 0xC0000305L)
-#endif
-
-#ifndef STATUS_CSS_AUTHENTICATION_FAILURE
-# define STATUS_CSS_AUTHENTICATION_FAILURE ((NTSTATUS) 0xC0000306L)
-#endif
-
-#ifndef STATUS_CSS_KEY_NOT_PRESENT
-# define STATUS_CSS_KEY_NOT_PRESENT ((NTSTATUS) 0xC0000307L)
-#endif
-
-#ifndef STATUS_CSS_KEY_NOT_ESTABLISHED
-# define STATUS_CSS_KEY_NOT_ESTABLISHED ((NTSTATUS) 0xC0000308L)
-#endif
-
-#ifndef STATUS_CSS_SCRAMBLED_SECTOR
-# define STATUS_CSS_SCRAMBLED_SECTOR ((NTSTATUS) 0xC0000309L)
-#endif
-
-#ifndef STATUS_CSS_REGION_MISMATCH
-# define STATUS_CSS_REGION_MISMATCH ((NTSTATUS) 0xC000030AL)
-#endif
-
-#ifndef STATUS_CSS_RESETS_EXHAUSTED
-# define STATUS_CSS_RESETS_EXHAUSTED ((NTSTATUS) 0xC000030BL)
-#endif
-
-#ifndef STATUS_PKINIT_FAILURE
-# define STATUS_PKINIT_FAILURE ((NTSTATUS) 0xC0000320L)
-#endif
-
-#ifndef STATUS_SMARTCARD_SUBSYSTEM_FAILURE
-# define STATUS_SMARTCARD_SUBSYSTEM_FAILURE ((NTSTATUS) 0xC0000321L)
-#endif
-
-#ifndef STATUS_NO_KERB_KEY
-# define STATUS_NO_KERB_KEY ((NTSTATUS) 0xC0000322L)
-#endif
-
-#ifndef STATUS_HOST_DOWN
-# define STATUS_HOST_DOWN ((NTSTATUS) 0xC0000350L)
-#endif
-
-#ifndef STATUS_UNSUPPORTED_PREAUTH
-# define STATUS_UNSUPPORTED_PREAUTH ((NTSTATUS) 0xC0000351L)
-#endif
-
-#ifndef STATUS_EFS_ALG_BLOB_TOO_BIG
-# define STATUS_EFS_ALG_BLOB_TOO_BIG ((NTSTATUS) 0xC0000352L)
-#endif
-
-#ifndef STATUS_PORT_NOT_SET
-# define STATUS_PORT_NOT_SET ((NTSTATUS) 0xC0000353L)
-#endif
-
-#ifndef STATUS_DEBUGGER_INACTIVE
-# define STATUS_DEBUGGER_INACTIVE ((NTSTATUS) 0xC0000354L)
-#endif
-
-#ifndef STATUS_DS_VERSION_CHECK_FAILURE
-# define STATUS_DS_VERSION_CHECK_FAILURE ((NTSTATUS) 0xC0000355L)
-#endif
-
-#ifndef STATUS_AUDITING_DISABLED
-# define STATUS_AUDITING_DISABLED ((NTSTATUS) 0xC0000356L)
-#endif
-
-#ifndef STATUS_PRENT4_MACHINE_ACCOUNT
-# define STATUS_PRENT4_MACHINE_ACCOUNT ((NTSTATUS) 0xC0000357L)
-#endif
-
-#ifndef STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER
-# define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC0000358L)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_WIN_32
-# define STATUS_INVALID_IMAGE_WIN_32 ((NTSTATUS) 0xC0000359L)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_WIN_64
-# define STATUS_INVALID_IMAGE_WIN_64 ((NTSTATUS) 0xC000035AL)
-#endif
-
-#ifndef STATUS_BAD_BINDINGS
-# define STATUS_BAD_BINDINGS ((NTSTATUS) 0xC000035BL)
-#endif
-
-#ifndef STATUS_NETWORK_SESSION_EXPIRED
-# define STATUS_NETWORK_SESSION_EXPIRED ((NTSTATUS) 0xC000035CL)
-#endif
-
-#ifndef STATUS_APPHELP_BLOCK
-# define STATUS_APPHELP_BLOCK ((NTSTATUS) 0xC000035DL)
-#endif
-
-#ifndef STATUS_ALL_SIDS_FILTERED
-# define STATUS_ALL_SIDS_FILTERED ((NTSTATUS) 0xC000035EL)
-#endif
-
-#ifndef STATUS_NOT_SAFE_MODE_DRIVER
-# define STATUS_NOT_SAFE_MODE_DRIVER ((NTSTATUS) 0xC000035FL)
-#endif
-
-#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT
-# define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT ((NTSTATUS) 0xC0000361L)
-#endif
-
-#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PATH
-# define STATUS_ACCESS_DISABLED_BY_POLICY_PATH ((NTSTATUS) 0xC0000362L)
-#endif
-
-#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER
-# define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER ((NTSTATUS) 0xC0000363L)
-#endif
-
-#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_OTHER
-# define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ((NTSTATUS) 0xC0000364L)
-#endif
-
-#ifndef STATUS_FAILED_DRIVER_ENTRY
-# define STATUS_FAILED_DRIVER_ENTRY ((NTSTATUS) 0xC0000365L)
-#endif
-
-#ifndef STATUS_DEVICE_ENUMERATION_ERROR
-# define STATUS_DEVICE_ENUMERATION_ERROR ((NTSTATUS) 0xC0000366L)
-#endif
-
-#ifndef STATUS_MOUNT_POINT_NOT_RESOLVED
-# define STATUS_MOUNT_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000368L)
-#endif
-
-#ifndef STATUS_INVALID_DEVICE_OBJECT_PARAMETER
-# define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS) 0xC0000369L)
-#endif
-
-#ifndef STATUS_MCA_OCCURED
-# define STATUS_MCA_OCCURED ((NTSTATUS) 0xC000036AL)
-#endif
-
-#ifndef STATUS_DRIVER_BLOCKED_CRITICAL
-# define STATUS_DRIVER_BLOCKED_CRITICAL ((NTSTATUS) 0xC000036BL)
-#endif
-
-#ifndef STATUS_DRIVER_BLOCKED
-# define STATUS_DRIVER_BLOCKED ((NTSTATUS) 0xC000036CL)
-#endif
-
-#ifndef STATUS_DRIVER_DATABASE_ERROR
-# define STATUS_DRIVER_DATABASE_ERROR ((NTSTATUS) 0xC000036DL)
-#endif
-
-#ifndef STATUS_SYSTEM_HIVE_TOO_LARGE
-# define STATUS_SYSTEM_HIVE_TOO_LARGE ((NTSTATUS) 0xC000036EL)
-#endif
-
-#ifndef STATUS_INVALID_IMPORT_OF_NON_DLL
-# define STATUS_INVALID_IMPORT_OF_NON_DLL ((NTSTATUS) 0xC000036FL)
-#endif
-
-#ifndef STATUS_DS_SHUTTING_DOWN
-# define STATUS_DS_SHUTTING_DOWN ((NTSTATUS) 0x40000370L)
-#endif
-
-#ifndef STATUS_NO_SECRETS
-# define STATUS_NO_SECRETS ((NTSTATUS) 0xC0000371L)
-#endif
-
-#ifndef STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY
-# define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY ((NTSTATUS) 0xC0000372L)
-#endif
-
-#ifndef STATUS_FAILED_STACK_SWITCH
-# define STATUS_FAILED_STACK_SWITCH ((NTSTATUS) 0xC0000373L)
-#endif
-
-#ifndef STATUS_HEAP_CORRUPTION
-# define STATUS_HEAP_CORRUPTION ((NTSTATUS) 0xC0000374L)
-#endif
-
-#ifndef STATUS_SMARTCARD_WRONG_PIN
-# define STATUS_SMARTCARD_WRONG_PIN ((NTSTATUS) 0xC0000380L)
-#endif
-
-#ifndef STATUS_SMARTCARD_CARD_BLOCKED
-# define STATUS_SMARTCARD_CARD_BLOCKED ((NTSTATUS) 0xC0000381L)
-#endif
-
-#ifndef STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED
-# define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED ((NTSTATUS) 0xC0000382L)
-#endif
-
-#ifndef STATUS_SMARTCARD_NO_CARD
-# define STATUS_SMARTCARD_NO_CARD ((NTSTATUS) 0xC0000383L)
-#endif
-
-#ifndef STATUS_SMARTCARD_NO_KEY_CONTAINER
-# define STATUS_SMARTCARD_NO_KEY_CONTAINER ((NTSTATUS) 0xC0000384L)
-#endif
-
-#ifndef STATUS_SMARTCARD_NO_CERTIFICATE
-# define STATUS_SMARTCARD_NO_CERTIFICATE ((NTSTATUS) 0xC0000385L)
-#endif
-
-#ifndef STATUS_SMARTCARD_NO_KEYSET
-# define STATUS_SMARTCARD_NO_KEYSET ((NTSTATUS) 0xC0000386L)
-#endif
-
-#ifndef STATUS_SMARTCARD_IO_ERROR
-# define STATUS_SMARTCARD_IO_ERROR ((NTSTATUS) 0xC0000387L)
-#endif
-
-#ifndef STATUS_DOWNGRADE_DETECTED
-# define STATUS_DOWNGRADE_DETECTED ((NTSTATUS) 0xC0000388L)
-#endif
-
-#ifndef STATUS_SMARTCARD_CERT_REVOKED
-# define STATUS_SMARTCARD_CERT_REVOKED ((NTSTATUS) 0xC0000389L)
-#endif
-
-#ifndef STATUS_ISSUING_CA_UNTRUSTED
-# define STATUS_ISSUING_CA_UNTRUSTED ((NTSTATUS) 0xC000038AL)
-#endif
-
-#ifndef STATUS_REVOCATION_OFFLINE_C
-# define STATUS_REVOCATION_OFFLINE_C ((NTSTATUS) 0xC000038BL)
-#endif
-
-#ifndef STATUS_PKINIT_CLIENT_FAILURE
-# define STATUS_PKINIT_CLIENT_FAILURE ((NTSTATUS) 0xC000038CL)
-#endif
-
-#ifndef STATUS_SMARTCARD_CERT_EXPIRED
-# define STATUS_SMARTCARD_CERT_EXPIRED ((NTSTATUS) 0xC000038DL)
-#endif
-
-#ifndef STATUS_DRIVER_FAILED_PRIOR_UNLOAD
-# define STATUS_DRIVER_FAILED_PRIOR_UNLOAD ((NTSTATUS) 0xC000038EL)
-#endif
-
-#ifndef STATUS_SMARTCARD_SILENT_CONTEXT
-# define STATUS_SMARTCARD_SILENT_CONTEXT ((NTSTATUS) 0xC000038FL)
-#endif
-
-#ifndef STATUS_PER_USER_TRUST_QUOTA_EXCEEDED
-# define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000401L)
-#endif
-
-#ifndef STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED
-# define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000402L)
-#endif
-
-#ifndef STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED
-# define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000403L)
-#endif
-
-#ifndef STATUS_DS_NAME_NOT_UNIQUE
-# define STATUS_DS_NAME_NOT_UNIQUE ((NTSTATUS) 0xC0000404L)
-#endif
-
-#ifndef STATUS_DS_DUPLICATE_ID_FOUND
-# define STATUS_DS_DUPLICATE_ID_FOUND ((NTSTATUS) 0xC0000405L)
-#endif
-
-#ifndef STATUS_DS_GROUP_CONVERSION_ERROR
-# define STATUS_DS_GROUP_CONVERSION_ERROR ((NTSTATUS) 0xC0000406L)
-#endif
-
-#ifndef STATUS_VOLSNAP_PREPARE_HIBERNATE
-# define STATUS_VOLSNAP_PREPARE_HIBERNATE ((NTSTATUS) 0xC0000407L)
-#endif
-
-#ifndef STATUS_USER2USER_REQUIRED
-# define STATUS_USER2USER_REQUIRED ((NTSTATUS) 0xC0000408L)
-#endif
-
-#ifndef STATUS_STACK_BUFFER_OVERRUN
-# define STATUS_STACK_BUFFER_OVERRUN ((NTSTATUS) 0xC0000409L)
-#endif
-
-#ifndef STATUS_NO_S4U_PROT_SUPPORT
-# define STATUS_NO_S4U_PROT_SUPPORT ((NTSTATUS) 0xC000040AL)
-#endif
-
-#ifndef STATUS_CROSSREALM_DELEGATION_FAILURE
-# define STATUS_CROSSREALM_DELEGATION_FAILURE ((NTSTATUS) 0xC000040BL)
-#endif
-
-#ifndef STATUS_REVOCATION_OFFLINE_KDC
-# define STATUS_REVOCATION_OFFLINE_KDC ((NTSTATUS) 0xC000040CL)
-#endif
-
-#ifndef STATUS_ISSUING_CA_UNTRUSTED_KDC
-# define STATUS_ISSUING_CA_UNTRUSTED_KDC ((NTSTATUS) 0xC000040DL)
-#endif
-
-#ifndef STATUS_KDC_CERT_EXPIRED
-# define STATUS_KDC_CERT_EXPIRED ((NTSTATUS) 0xC000040EL)
-#endif
-
-#ifndef STATUS_KDC_CERT_REVOKED
-# define STATUS_KDC_CERT_REVOKED ((NTSTATUS) 0xC000040FL)
-#endif
-
-#ifndef STATUS_PARAMETER_QUOTA_EXCEEDED
-# define STATUS_PARAMETER_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000410L)
-#endif
-
-#ifndef STATUS_HIBERNATION_FAILURE
-# define STATUS_HIBERNATION_FAILURE ((NTSTATUS) 0xC0000411L)
-#endif
-
-#ifndef STATUS_DELAY_LOAD_FAILED
-# define STATUS_DELAY_LOAD_FAILED ((NTSTATUS) 0xC0000412L)
-#endif
-
-#ifndef STATUS_AUTHENTICATION_FIREWALL_FAILED
-# define STATUS_AUTHENTICATION_FIREWALL_FAILED ((NTSTATUS) 0xC0000413L)
-#endif
-
-#ifndef STATUS_VDM_DISALLOWED
-# define STATUS_VDM_DISALLOWED ((NTSTATUS) 0xC0000414L)
-#endif
-
-#ifndef STATUS_HUNG_DISPLAY_DRIVER_THREAD
-# define STATUS_HUNG_DISPLAY_DRIVER_THREAD ((NTSTATUS) 0xC0000415L)
-#endif
-
-#ifndef STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE
-# define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE ((NTSTATUS) 0xC0000416L)
-#endif
-
-#ifndef STATUS_INVALID_CRUNTIME_PARAMETER
-# define STATUS_INVALID_CRUNTIME_PARAMETER ((NTSTATUS) 0xC0000417L)
-#endif
-
-#ifndef STATUS_NTLM_BLOCKED
-# define STATUS_NTLM_BLOCKED ((NTSTATUS) 0xC0000418L)
-#endif
-
-#ifndef STATUS_DS_SRC_SID_EXISTS_IN_FOREST
-# define STATUS_DS_SRC_SID_EXISTS_IN_FOREST ((NTSTATUS) 0xC0000419L)
-#endif
-
-#ifndef STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST
-# define STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041AL)
-#endif
-
-#ifndef STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST
-# define STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041BL)
-#endif
-
-#ifndef STATUS_INVALID_USER_PRINCIPAL_NAME
-# define STATUS_INVALID_USER_PRINCIPAL_NAME ((NTSTATUS) 0xC000041CL)
-#endif
-
-#ifndef STATUS_FATAL_USER_CALLBACK_EXCEPTION
-# define STATUS_FATAL_USER_CALLBACK_EXCEPTION ((NTSTATUS) 0xC000041DL)
-#endif
-
-#ifndef STATUS_ASSERTION_FAILURE
-# define STATUS_ASSERTION_FAILURE ((NTSTATUS) 0xC0000420L)
-#endif
-
-#ifndef STATUS_VERIFIER_STOP
-# define STATUS_VERIFIER_STOP ((NTSTATUS) 0xC0000421L)
-#endif
-
-#ifndef STATUS_CALLBACK_POP_STACK
-# define STATUS_CALLBACK_POP_STACK ((NTSTATUS) 0xC0000423L)
-#endif
-
-#ifndef STATUS_INCOMPATIBLE_DRIVER_BLOCKED
-# define STATUS_INCOMPATIBLE_DRIVER_BLOCKED ((NTSTATUS) 0xC0000424L)
-#endif
-
-#ifndef STATUS_HIVE_UNLOADED
-# define STATUS_HIVE_UNLOADED ((NTSTATUS) 0xC0000425L)
-#endif
-
-#ifndef STATUS_COMPRESSION_DISABLED
-# define STATUS_COMPRESSION_DISABLED ((NTSTATUS) 0xC0000426L)
-#endif
-
-#ifndef STATUS_FILE_SYSTEM_LIMITATION
-# define STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS) 0xC0000427L)
-#endif
-
-#ifndef STATUS_INVALID_IMAGE_HASH
-# define STATUS_INVALID_IMAGE_HASH ((NTSTATUS) 0xC0000428L)
-#endif
-
-#ifndef STATUS_NOT_CAPABLE
-# define STATUS_NOT_CAPABLE ((NTSTATUS) 0xC0000429L)
-#endif
-
-#ifndef STATUS_REQUEST_OUT_OF_SEQUENCE
-# define STATUS_REQUEST_OUT_OF_SEQUENCE ((NTSTATUS) 0xC000042AL)
-#endif
-
-#ifndef STATUS_IMPLEMENTATION_LIMIT
-# define STATUS_IMPLEMENTATION_LIMIT ((NTSTATUS) 0xC000042BL)
-#endif
-
-#ifndef STATUS_ELEVATION_REQUIRED
-# define STATUS_ELEVATION_REQUIRED ((NTSTATUS) 0xC000042CL)
-#endif
-
-#ifndef STATUS_NO_SECURITY_CONTEXT
-# define STATUS_NO_SECURITY_CONTEXT ((NTSTATUS) 0xC000042DL)
-#endif
-
-#ifndef STATUS_PKU2U_CERT_FAILURE
-# define STATUS_PKU2U_CERT_FAILURE ((NTSTATUS) 0xC000042FL)
-#endif
-
-#ifndef STATUS_BEYOND_VDL
-# define STATUS_BEYOND_VDL ((NTSTATUS) 0xC0000432L)
-#endif
-
-#ifndef STATUS_ENCOUNTERED_WRITE_IN_PROGRESS
-# define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS ((NTSTATUS) 0xC0000433L)
-#endif
-
-#ifndef STATUS_PTE_CHANGED
-# define STATUS_PTE_CHANGED ((NTSTATUS) 0xC0000434L)
-#endif
-
-#ifndef STATUS_PURGE_FAILED
-# define STATUS_PURGE_FAILED ((NTSTATUS) 0xC0000435L)
-#endif
-
-#ifndef STATUS_CRED_REQUIRES_CONFIRMATION
-# define STATUS_CRED_REQUIRES_CONFIRMATION ((NTSTATUS) 0xC0000440L)
-#endif
-
-#ifndef STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE
-# define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE ((NTSTATUS) 0xC0000441L)
-#endif
-
-#ifndef STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER
-# define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER ((NTSTATUS) 0xC0000442L)
-#endif
-
-#ifndef STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE
-# define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE ((NTSTATUS) 0xC0000443L)
-#endif
-
-#ifndef STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE
-# define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE ((NTSTATUS) 0xC0000444L)
-#endif
-
-#ifndef STATUS_CS_ENCRYPTION_FILE_NOT_CSE
-# define STATUS_CS_ENCRYPTION_FILE_NOT_CSE ((NTSTATUS) 0xC0000445L)
-#endif
-
-#ifndef STATUS_INVALID_LABEL
-# define STATUS_INVALID_LABEL ((NTSTATUS) 0xC0000446L)
-#endif
-
-#ifndef STATUS_DRIVER_PROCESS_TERMINATED
-# define STATUS_DRIVER_PROCESS_TERMINATED ((NTSTATUS) 0xC0000450L)
-#endif
-
-#ifndef STATUS_AMBIGUOUS_SYSTEM_DEVICE
-# define STATUS_AMBIGUOUS_SYSTEM_DEVICE ((NTSTATUS) 0xC0000451L)
-#endif
-
-#ifndef STATUS_SYSTEM_DEVICE_NOT_FOUND
-# define STATUS_SYSTEM_DEVICE_NOT_FOUND ((NTSTATUS) 0xC0000452L)
-#endif
-
-#ifndef STATUS_RESTART_BOOT_APPLICATION
-# define STATUS_RESTART_BOOT_APPLICATION ((NTSTATUS) 0xC0000453L)
-#endif
-
-#ifndef STATUS_INSUFFICIENT_NVRAM_RESOURCES
-# define STATUS_INSUFFICIENT_NVRAM_RESOURCES ((NTSTATUS) 0xC0000454L)
-#endif
-
-#ifndef STATUS_INVALID_TASK_NAME
-# define STATUS_INVALID_TASK_NAME ((NTSTATUS) 0xC0000500L)
-#endif
-
-#ifndef STATUS_INVALID_TASK_INDEX
-# define STATUS_INVALID_TASK_INDEX ((NTSTATUS) 0xC0000501L)
-#endif
-
-#ifndef STATUS_THREAD_ALREADY_IN_TASK
-# define STATUS_THREAD_ALREADY_IN_TASK ((NTSTATUS) 0xC0000502L)
-#endif
-
-#ifndef STATUS_CALLBACK_BYPASS
-# define STATUS_CALLBACK_BYPASS ((NTSTATUS) 0xC0000503L)
-#endif
-
-#ifndef STATUS_FAIL_FAST_EXCEPTION
-# define STATUS_FAIL_FAST_EXCEPTION ((NTSTATUS) 0xC0000602L)
-#endif
-
-#ifndef STATUS_IMAGE_CERT_REVOKED
-# define STATUS_IMAGE_CERT_REVOKED ((NTSTATUS) 0xC0000603L)
-#endif
-
-#ifndef STATUS_PORT_CLOSED
-# define STATUS_PORT_CLOSED ((NTSTATUS) 0xC0000700L)
-#endif
-
-#ifndef STATUS_MESSAGE_LOST
-# define STATUS_MESSAGE_LOST ((NTSTATUS) 0xC0000701L)
-#endif
-
-#ifndef STATUS_INVALID_MESSAGE
-# define STATUS_INVALID_MESSAGE ((NTSTATUS) 0xC0000702L)
-#endif
-
-#ifndef STATUS_REQUEST_CANCELED
-# define STATUS_REQUEST_CANCELED ((NTSTATUS) 0xC0000703L)
-#endif
-
-#ifndef STATUS_RECURSIVE_DISPATCH
-# define STATUS_RECURSIVE_DISPATCH ((NTSTATUS) 0xC0000704L)
-#endif
-
-#ifndef STATUS_LPC_RECEIVE_BUFFER_EXPECTED
-# define STATUS_LPC_RECEIVE_BUFFER_EXPECTED ((NTSTATUS) 0xC0000705L)
-#endif
-
-#ifndef STATUS_LPC_INVALID_CONNECTION_USAGE
-# define STATUS_LPC_INVALID_CONNECTION_USAGE ((NTSTATUS) 0xC0000706L)
-#endif
-
-#ifndef STATUS_LPC_REQUESTS_NOT_ALLOWED
-# define STATUS_LPC_REQUESTS_NOT_ALLOWED ((NTSTATUS) 0xC0000707L)
-#endif
-
-#ifndef STATUS_RESOURCE_IN_USE
-# define STATUS_RESOURCE_IN_USE ((NTSTATUS) 0xC0000708L)
-#endif
-
-#ifndef STATUS_HARDWARE_MEMORY_ERROR
-# define STATUS_HARDWARE_MEMORY_ERROR ((NTSTATUS) 0xC0000709L)
-#endif
-
-#ifndef STATUS_THREADPOOL_HANDLE_EXCEPTION
-# define STATUS_THREADPOOL_HANDLE_EXCEPTION ((NTSTATUS) 0xC000070AL)
-#endif
-
-#ifndef STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED
-# define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070BL)
-#endif
-
-#ifndef STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED
-# define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070CL)
-#endif
-
-#ifndef STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED
-# define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070DL)
-#endif
-
-#ifndef STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED
-# define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070EL)
-#endif
-
-#ifndef STATUS_THREADPOOL_RELEASED_DURING_OPERATION
-# define STATUS_THREADPOOL_RELEASED_DURING_OPERATION ((NTSTATUS) 0xC000070FL)
-#endif
-
-#ifndef STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING
-# define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000710L)
-#endif
-
-#ifndef STATUS_APC_RETURNED_WHILE_IMPERSONATING
-# define STATUS_APC_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000711L)
-#endif
-
-#ifndef STATUS_PROCESS_IS_PROTECTED
-# define STATUS_PROCESS_IS_PROTECTED ((NTSTATUS) 0xC0000712L)
-#endif
-
-#ifndef STATUS_MCA_EXCEPTION
-# define STATUS_MCA_EXCEPTION ((NTSTATUS) 0xC0000713L)
-#endif
-
-#ifndef STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE
-# define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE ((NTSTATUS) 0xC0000714L)
-#endif
-
-#ifndef STATUS_SYMLINK_CLASS_DISABLED
-# define STATUS_SYMLINK_CLASS_DISABLED ((NTSTATUS) 0xC0000715L)
-#endif
-
-#ifndef STATUS_INVALID_IDN_NORMALIZATION
-# define STATUS_INVALID_IDN_NORMALIZATION ((NTSTATUS) 0xC0000716L)
-#endif
-
-#ifndef STATUS_NO_UNICODE_TRANSLATION
-# define STATUS_NO_UNICODE_TRANSLATION ((NTSTATUS) 0xC0000717L)
-#endif
-
-#ifndef STATUS_ALREADY_REGISTERED
-# define STATUS_ALREADY_REGISTERED ((NTSTATUS) 0xC0000718L)
-#endif
-
-#ifndef STATUS_CONTEXT_MISMATCH
-# define STATUS_CONTEXT_MISMATCH ((NTSTATUS) 0xC0000719L)
-#endif
-
-#ifndef STATUS_PORT_ALREADY_HAS_COMPLETION_LIST
-# define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST ((NTSTATUS) 0xC000071AL)
-#endif
-
-#ifndef STATUS_CALLBACK_RETURNED_THREAD_PRIORITY
-# define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY ((NTSTATUS) 0xC000071BL)
-#endif
-
-#ifndef STATUS_INVALID_THREAD
-# define STATUS_INVALID_THREAD ((NTSTATUS) 0xC000071CL)
-#endif
-
-#ifndef STATUS_CALLBACK_RETURNED_TRANSACTION
-# define STATUS_CALLBACK_RETURNED_TRANSACTION ((NTSTATUS) 0xC000071DL)
-#endif
-
-#ifndef STATUS_CALLBACK_RETURNED_LDR_LOCK
-# define STATUS_CALLBACK_RETURNED_LDR_LOCK ((NTSTATUS) 0xC000071EL)
-#endif
-
-#ifndef STATUS_CALLBACK_RETURNED_LANG
-# define STATUS_CALLBACK_RETURNED_LANG ((NTSTATUS) 0xC000071FL)
-#endif
-
-#ifndef STATUS_CALLBACK_RETURNED_PRI_BACK
-# define STATUS_CALLBACK_RETURNED_PRI_BACK ((NTSTATUS) 0xC0000720L)
-#endif
-
-#ifndef STATUS_CALLBACK_RETURNED_THREAD_AFFINITY
-# define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY ((NTSTATUS) 0xC0000721L)
-#endif
-
-#ifndef STATUS_DISK_REPAIR_DISABLED
-# define STATUS_DISK_REPAIR_DISABLED ((NTSTATUS) 0xC0000800L)
-#endif
-
-#ifndef STATUS_DS_DOMAIN_RENAME_IN_PROGRESS
-# define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS ((NTSTATUS) 0xC0000801L)
-#endif
-
-#ifndef STATUS_DISK_QUOTA_EXCEEDED
-# define STATUS_DISK_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000802L)
-#endif
-
-#ifndef STATUS_DATA_LOST_REPAIR
-# define STATUS_DATA_LOST_REPAIR ((NTSTATUS) 0x80000803L)
-#endif
-
-#ifndef STATUS_CONTENT_BLOCKED
-# define STATUS_CONTENT_BLOCKED ((NTSTATUS) 0xC0000804L)
-#endif
-
-#ifndef STATUS_BAD_CLUSTERS
-# define STATUS_BAD_CLUSTERS ((NTSTATUS) 0xC0000805L)
-#endif
-
-#ifndef STATUS_VOLUME_DIRTY
-# define STATUS_VOLUME_DIRTY ((NTSTATUS) 0xC0000806L)
-#endif
-
-#ifndef STATUS_FILE_CHECKED_OUT
-# define STATUS_FILE_CHECKED_OUT ((NTSTATUS) 0xC0000901L)
-#endif
-
-#ifndef STATUS_CHECKOUT_REQUIRED
-# define STATUS_CHECKOUT_REQUIRED ((NTSTATUS) 0xC0000902L)
-#endif
-
-#ifndef STATUS_BAD_FILE_TYPE
-# define STATUS_BAD_FILE_TYPE ((NTSTATUS) 0xC0000903L)
-#endif
-
-#ifndef STATUS_FILE_TOO_LARGE
-# define STATUS_FILE_TOO_LARGE ((NTSTATUS) 0xC0000904L)
-#endif
-
-#ifndef STATUS_FORMS_AUTH_REQUIRED
-# define STATUS_FORMS_AUTH_REQUIRED ((NTSTATUS) 0xC0000905L)
-#endif
-
-#ifndef STATUS_VIRUS_INFECTED
-# define STATUS_VIRUS_INFECTED ((NTSTATUS) 0xC0000906L)
-#endif
-
-#ifndef STATUS_VIRUS_DELETED
-# define STATUS_VIRUS_DELETED ((NTSTATUS) 0xC0000907L)
-#endif
-
-#ifndef STATUS_BAD_MCFG_TABLE
-# define STATUS_BAD_MCFG_TABLE ((NTSTATUS) 0xC0000908L)
-#endif
-
-#ifndef STATUS_CANNOT_BREAK_OPLOCK
-# define STATUS_CANNOT_BREAK_OPLOCK ((NTSTATUS) 0xC0000909L)
-#endif
-
-#ifndef STATUS_WOW_ASSERTION
-# define STATUS_WOW_ASSERTION ((NTSTATUS) 0xC0009898L)
-#endif
-
-#ifndef STATUS_INVALID_SIGNATURE
-# define STATUS_INVALID_SIGNATURE ((NTSTATUS) 0xC000A000L)
-#endif
-
-#ifndef STATUS_HMAC_NOT_SUPPORTED
-# define STATUS_HMAC_NOT_SUPPORTED ((NTSTATUS) 0xC000A001L)
-#endif
-
-#ifndef STATUS_AUTH_TAG_MISMATCH
-# define STATUS_AUTH_TAG_MISMATCH ((NTSTATUS) 0xC000A002L)
-#endif
-
-#ifndef STATUS_IPSEC_QUEUE_OVERFLOW
-# define STATUS_IPSEC_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A010L)
-#endif
-
-#ifndef STATUS_ND_QUEUE_OVERFLOW
-# define STATUS_ND_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A011L)
-#endif
-
-#ifndef STATUS_HOPLIMIT_EXCEEDED
-# define STATUS_HOPLIMIT_EXCEEDED ((NTSTATUS) 0xC000A012L)
-#endif
-
-#ifndef STATUS_PROTOCOL_NOT_SUPPORTED
-# define STATUS_PROTOCOL_NOT_SUPPORTED ((NTSTATUS) 0xC000A013L)
-#endif
-
-#ifndef STATUS_FASTPATH_REJECTED
-# define STATUS_FASTPATH_REJECTED ((NTSTATUS) 0xC000A014L)
-#endif
-
-#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED
-# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED ((NTSTATUS) 0xC000A080L)
-#endif
-
-#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR
-# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR ((NTSTATUS) 0xC000A081L)
-#endif
-
-#ifndef STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR
-# define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR ((NTSTATUS) 0xC000A082L)
-#endif
-
-#ifndef STATUS_XML_PARSE_ERROR
-# define STATUS_XML_PARSE_ERROR ((NTSTATUS) 0xC000A083L)
-#endif
-
-#ifndef STATUS_XMLDSIG_ERROR
-# define STATUS_XMLDSIG_ERROR ((NTSTATUS) 0xC000A084L)
-#endif
-
-#ifndef STATUS_WRONG_COMPARTMENT
-# define STATUS_WRONG_COMPARTMENT ((NTSTATUS) 0xC000A085L)
-#endif
-
-#ifndef STATUS_AUTHIP_FAILURE
-# define STATUS_AUTHIP_FAILURE ((NTSTATUS) 0xC000A086L)
-#endif
-
-#ifndef STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS
-# define STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS ((NTSTATUS) 0xC000A087L)
-#endif
-
-#ifndef STATUS_DS_OID_NOT_FOUND
-# define STATUS_DS_OID_NOT_FOUND ((NTSTATUS) 0xC000A088L)
-#endif
-
-#ifndef STATUS_HASH_NOT_SUPPORTED
-# define STATUS_HASH_NOT_SUPPORTED ((NTSTATUS) 0xC000A100L)
-#endif
-
-#ifndef STATUS_HASH_NOT_PRESENT
-# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L)
-#endif
-
-/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the DDK
- * got it wrong! */
-#ifdef NTSTATUS_FROM_WIN32
-# undef NTSTATUS_FROM_WIN32
-#endif
-#define NTSTATUS_FROM_WIN32(error) ((NTSTATUS) (error) <= 0 ? \
-        ((NTSTATUS) (error)) : ((NTSTATUS) (((error) & 0x0000FFFF) | \
-        (FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_WARNING)))
-
-#ifndef JOB_OBJECT_LIMIT_PROCESS_MEMORY
-# define JOB_OBJECT_LIMIT_PROCESS_MEMORY             0x00000100
-#endif
-#ifndef JOB_OBJECT_LIMIT_JOB_MEMORY
-# define JOB_OBJECT_LIMIT_JOB_MEMORY                 0x00000200
-#endif
-#ifndef JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
-# define JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION 0x00000400
-#endif
-#ifndef JOB_OBJECT_LIMIT_BREAKAWAY_OK
-# define JOB_OBJECT_LIMIT_BREAKAWAY_OK               0x00000800
-#endif
-#ifndef JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK
-# define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK        0x00001000
-#endif
-#ifndef JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
-# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE          0x00002000
-#endif
-
-#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
-# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x00000002
-#endif
-
-/* from winternl.h */
-#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32_)
-#define __UNICODE_STRING_DEFINED
-#endif
-typedef struct _UNICODE_STRING {
-  USHORT Length;
-  USHORT MaximumLength;
-  PWSTR  Buffer;
-} UNICODE_STRING, *PUNICODE_STRING;
-
-typedef const UNICODE_STRING *PCUNICODE_STRING;
-
-/* from ntifs.h */
-#ifndef DEVICE_TYPE
-# define DEVICE_TYPE DWORD
-#endif
-
-/* MinGW already has a definition for REPARSE_DATA_BUFFER, but mingw-w64 does
- * not.
- */
-#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR)
-  typedef struct _REPARSE_DATA_BUFFER {
-    ULONG  ReparseTag;
-    USHORT ReparseDataLength;
-    USHORT Reserved;
-    union {
-      struct {
-        USHORT SubstituteNameOffset;
-        USHORT SubstituteNameLength;
-        USHORT PrintNameOffset;
-        USHORT PrintNameLength;
-        ULONG Flags;
-        WCHAR PathBuffer[1];
-      } SymbolicLinkReparseBuffer;
-      struct {
-        USHORT SubstituteNameOffset;
-        USHORT SubstituteNameLength;
-        USHORT PrintNameOffset;
-        USHORT PrintNameLength;
-        WCHAR PathBuffer[1];
-      } MountPointReparseBuffer;
-      struct {
-        UCHAR  DataBuffer[1];
-      } GenericReparseBuffer;
-    };
-  } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
-#endif
-
-typedef struct _IO_STATUS_BLOCK {
-  union {
-    NTSTATUS Status;
-    PVOID Pointer;
-  };
-  ULONG_PTR Information;
-} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
-
-typedef enum _FILE_INFORMATION_CLASS {
-  FileDirectoryInformation = 1,
-  FileFullDirectoryInformation,
-  FileBothDirectoryInformation,
-  FileBasicInformation,
-  FileStandardInformation,
-  FileInternalInformation,
-  FileEaInformation,
-  FileAccessInformation,
-  FileNameInformation,
-  FileRenameInformation,
-  FileLinkInformation,
-  FileNamesInformation,
-  FileDispositionInformation,
-  FilePositionInformation,
-  FileFullEaInformation,
-  FileModeInformation,
-  FileAlignmentInformation,
-  FileAllInformation,
-  FileAllocationInformation,
-  FileEndOfFileInformation,
-  FileAlternateNameInformation,
-  FileStreamInformation,
-  FilePipeInformation,
-  FilePipeLocalInformation,
-  FilePipeRemoteInformation,
-  FileMailslotQueryInformation,
-  FileMailslotSetInformation,
-  FileCompressionInformation,
-  FileObjectIdInformation,
-  FileCompletionInformation,
-  FileMoveClusterInformation,
-  FileQuotaInformation,
-  FileReparsePointInformation,
-  FileNetworkOpenInformation,
-  FileAttributeTagInformation,
-  FileTrackingInformation,
-  FileIdBothDirectoryInformation,
-  FileIdFullDirectoryInformation,
-  FileValidDataLengthInformation,
-  FileShortNameInformation,
-  FileIoCompletionNotificationInformation,
-  FileIoStatusBlockRangeInformation,
-  FileIoPriorityHintInformation,
-  FileSfioReserveInformation,
-  FileSfioVolumeInformation,
-  FileHardLinkInformation,
-  FileProcessIdsUsingFileInformation,
-  FileNormalizedNameInformation,
-  FileNetworkPhysicalNameInformation,
-  FileIdGlobalTxDirectoryInformation,
-  FileIsRemoteDeviceInformation,
-  FileAttributeCacheInformation,
-  FileNumaNodeInformation,
-  FileStandardLinkInformation,
-  FileRemoteProtocolInformation,
-  FileMaximumInformation
-} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
-
-typedef struct _FILE_DIRECTORY_INFORMATION {
-  ULONG NextEntryOffset;
-  ULONG FileIndex;
-  LARGE_INTEGER CreationTime;
-  LARGE_INTEGER LastAccessTime;
-  LARGE_INTEGER LastWriteTime;
-  LARGE_INTEGER ChangeTime;
-  LARGE_INTEGER EndOfFile;
-  LARGE_INTEGER AllocationSize;
-  ULONG FileAttributes;
-  ULONG FileNameLength;
-  WCHAR FileName[1];
-} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
-
-typedef struct _FILE_BOTH_DIR_INFORMATION {
-  ULONG NextEntryOffset;
-  ULONG FileIndex;
-  LARGE_INTEGER CreationTime;
-  LARGE_INTEGER LastAccessTime;
-  LARGE_INTEGER LastWriteTime;
-  LARGE_INTEGER ChangeTime;
-  LARGE_INTEGER EndOfFile;
-  LARGE_INTEGER AllocationSize;
-  ULONG FileAttributes;
-  ULONG FileNameLength;
-  ULONG EaSize;
-  CCHAR ShortNameLength;
-  WCHAR ShortName[12];
-  WCHAR FileName[1];
-} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
-
-typedef struct _FILE_BASIC_INFORMATION {
-  LARGE_INTEGER CreationTime;
-  LARGE_INTEGER LastAccessTime;
-  LARGE_INTEGER LastWriteTime;
-  LARGE_INTEGER ChangeTime;
-  DWORD FileAttributes;
-} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
-
-typedef struct _FILE_STANDARD_INFORMATION {
-  LARGE_INTEGER AllocationSize;
-  LARGE_INTEGER EndOfFile;
-  ULONG         NumberOfLinks;
-  BOOLEAN       DeletePending;
-  BOOLEAN       Directory;
-} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
-
-typedef struct _FILE_INTERNAL_INFORMATION {
-  LARGE_INTEGER IndexNumber;
-} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
-
-typedef struct _FILE_EA_INFORMATION {
-  ULONG EaSize;
-} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
-
-typedef struct _FILE_ACCESS_INFORMATION {
-  ACCESS_MASK AccessFlags;
-} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
-
-typedef struct _FILE_POSITION_INFORMATION {
-  LARGE_INTEGER CurrentByteOffset;
-} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
-
-typedef struct _FILE_MODE_INFORMATION {
-  ULONG Mode;
-} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
-
-typedef struct _FILE_ALIGNMENT_INFORMATION {
-  ULONG AlignmentRequirement;
-} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;
-
-typedef struct _FILE_NAME_INFORMATION {
-  ULONG FileNameLength;
-  WCHAR FileName[1];
-} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
-
-typedef struct _FILE_END_OF_FILE_INFORMATION {
-  LARGE_INTEGER  EndOfFile;
-} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION;
-
-typedef struct _FILE_ALL_INFORMATION {
-  FILE_BASIC_INFORMATION     BasicInformation;
-  FILE_STANDARD_INFORMATION  StandardInformation;
-  FILE_INTERNAL_INFORMATION  InternalInformation;
-  FILE_EA_INFORMATION        EaInformation;
-  FILE_ACCESS_INFORMATION    AccessInformation;
-  FILE_POSITION_INFORMATION  PositionInformation;
-  FILE_MODE_INFORMATION      ModeInformation;
-  FILE_ALIGNMENT_INFORMATION AlignmentInformation;
-  FILE_NAME_INFORMATION      NameInformation;
-} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
-
-typedef struct _FILE_DISPOSITION_INFORMATION {
-  BOOLEAN DeleteFile;
-} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
-
-typedef struct _FILE_PIPE_LOCAL_INFORMATION {
-  ULONG NamedPipeType;
-  ULONG NamedPipeConfiguration;
-  ULONG MaximumInstances;
-  ULONG CurrentInstances;
-  ULONG InboundQuota;
-  ULONG ReadDataAvailable;
-  ULONG OutboundQuota;
-  ULONG WriteQuotaAvailable;
-  ULONG NamedPipeState;
-  ULONG NamedPipeEnd;
-} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
-
-#define FILE_SYNCHRONOUS_IO_ALERT               0x00000010
-#define FILE_SYNCHRONOUS_IO_NONALERT            0x00000020
-
-typedef enum _FS_INFORMATION_CLASS {
-  FileFsVolumeInformation       = 1,
-  FileFsLabelInformation        = 2,
-  FileFsSizeInformation         = 3,
-  FileFsDeviceInformation       = 4,
-  FileFsAttributeInformation    = 5,
-  FileFsControlInformation      = 6,
-  FileFsFullSizeInformation     = 7,
-  FileFsObjectIdInformation     = 8,
-  FileFsDriverPathInformation   = 9,
-  FileFsVolumeFlagsInformation  = 10,
-  FileFsSectorSizeInformation   = 11
-} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
-
-typedef struct _FILE_FS_VOLUME_INFORMATION {
-  LARGE_INTEGER VolumeCreationTime;
-  ULONG         VolumeSerialNumber;
-  ULONG         VolumeLabelLength;
-  BOOLEAN       SupportsObjects;
-  WCHAR         VolumeLabel[1];
-} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION;
-
-typedef struct _FILE_FS_LABEL_INFORMATION {
-  ULONG VolumeLabelLength;
-  WCHAR VolumeLabel[1];
-} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION;
-
-typedef struct _FILE_FS_SIZE_INFORMATION {
-  LARGE_INTEGER TotalAllocationUnits;
-  LARGE_INTEGER AvailableAllocationUnits;
-  ULONG         SectorsPerAllocationUnit;
-  ULONG         BytesPerSector;
-} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION;
-
-typedef struct _FILE_FS_DEVICE_INFORMATION {
-  DEVICE_TYPE DeviceType;
-  ULONG       Characteristics;
-} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION;
-
-typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
-  ULONG FileSystemAttributes;
-  LONG  MaximumComponentNameLength;
-  ULONG FileSystemNameLength;
-  WCHAR FileSystemName[1];
-} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
-
-typedef struct _FILE_FS_CONTROL_INFORMATION {
-  LARGE_INTEGER FreeSpaceStartFiltering;
-  LARGE_INTEGER FreeSpaceThreshold;
-  LARGE_INTEGER FreeSpaceStopFiltering;
-  LARGE_INTEGER DefaultQuotaThreshold;
-  LARGE_INTEGER DefaultQuotaLimit;
-  ULONG         FileSystemControlFlags;
-} FILE_FS_CONTROL_INFORMATION, *PFILE_FS_CONTROL_INFORMATION;
-
-typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
-  LARGE_INTEGER TotalAllocationUnits;
-  LARGE_INTEGER CallerAvailableAllocationUnits;
-  LARGE_INTEGER ActualAvailableAllocationUnits;
-  ULONG         SectorsPerAllocationUnit;
-  ULONG         BytesPerSector;
-} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
-
-typedef struct _FILE_FS_OBJECTID_INFORMATION {
-  UCHAR ObjectId[16];
-  UCHAR ExtendedInfo[48];
-} FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION;
-
-typedef struct _FILE_FS_DRIVER_PATH_INFORMATION {
-  BOOLEAN DriverInPath;
-  ULONG   DriverNameLength;
-  WCHAR   DriverName[1];
-} FILE_FS_DRIVER_PATH_INFORMATION, *PFILE_FS_DRIVER_PATH_INFORMATION;
-
-typedef struct _FILE_FS_VOLUME_FLAGS_INFORMATION {
-  ULONG Flags;
-} FILE_FS_VOLUME_FLAGS_INFORMATION, *PFILE_FS_VOLUME_FLAGS_INFORMATION;
-
-typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION {
-  ULONG LogicalBytesPerSector;
-  ULONG PhysicalBytesPerSectorForAtomicity;
-  ULONG PhysicalBytesPerSectorForPerformance;
-  ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity;
-  ULONG Flags;
-  ULONG ByteOffsetForSectorAlignment;
-  ULONG ByteOffsetForPartitionAlignment;
-} FILE_FS_SECTOR_SIZE_INFORMATION, *PFILE_FS_SECTOR_SIZE_INFORMATION;
-
-typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
-    LARGE_INTEGER IdleTime;
-    LARGE_INTEGER KernelTime;
-    LARGE_INTEGER UserTime;
-    LARGE_INTEGER DpcTime;
-    LARGE_INTEGER InterruptTime;
-    ULONG InterruptCount;
-} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
-
-#ifndef SystemProcessorPerformanceInformation
-# define SystemProcessorPerformanceInformation 8
-#endif
-
-#ifndef FILE_DEVICE_FILE_SYSTEM
-# define FILE_DEVICE_FILE_SYSTEM 0x00000009
-#endif
-
-#ifndef FILE_DEVICE_NETWORK
-# define FILE_DEVICE_NETWORK 0x00000012
-#endif
-
-#ifndef METHOD_BUFFERED
-# define METHOD_BUFFERED 0
-#endif
-
-#ifndef METHOD_IN_DIRECT
-# define METHOD_IN_DIRECT 1
-#endif
-
-#ifndef METHOD_OUT_DIRECT
-# define METHOD_OUT_DIRECT 2
-#endif
-
-#ifndef METHOD_NEITHER
-#define METHOD_NEITHER 3
-#endif
-
-#ifndef METHOD_DIRECT_TO_HARDWARE
-# define METHOD_DIRECT_TO_HARDWARE METHOD_IN_DIRECT
-#endif
-
-#ifndef METHOD_DIRECT_FROM_HARDWARE
-# define METHOD_DIRECT_FROM_HARDWARE METHOD_OUT_DIRECT
-#endif
-
-#ifndef FILE_ANY_ACCESS
-# define FILE_ANY_ACCESS 0
-#endif
-
-#ifndef FILE_SPECIAL_ACCESS
-# define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS)
-#endif
-
-#ifndef FILE_READ_ACCESS
-# define FILE_READ_ACCESS 0x0001
-#endif
-
-#ifndef FILE_WRITE_ACCESS
-# define FILE_WRITE_ACCESS 0x0002
-#endif
-
-#ifndef CTL_CODE
-# define CTL_CODE(device_type, function, method, access)                      \
-    (((device_type) << 16) | ((access) << 14) | ((function) << 2) | (method))
-#endif
-
-#ifndef FSCTL_SET_REPARSE_POINT
-# define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM,            \
-                                          41,                                 \
-                                          METHOD_BUFFERED,                    \
-                                          FILE_SPECIAL_ACCESS)
-#endif
-
-#ifndef FSCTL_GET_REPARSE_POINT
-# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM,            \
-                                          42,                                 \
-                                          METHOD_BUFFERED,                    \
-                                          FILE_ANY_ACCESS)
-#endif
-
-#ifndef FSCTL_DELETE_REPARSE_POINT
-# define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM,         \
-                                             43,                              \
-                                             METHOD_BUFFERED,                 \
-                                             FILE_SPECIAL_ACCESS)
-#endif
-
-#ifndef IO_REPARSE_TAG_SYMLINK
-# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
-#endif
-
-typedef VOID (NTAPI *PIO_APC_ROUTINE)
-             (PVOID ApcContext,
-              PIO_STATUS_BLOCK IoStatusBlock,
-              ULONG Reserved);
-
-typedef NTSTATUS (NTAPI *sRtlGetVersion)
-                 (PRTL_OSVERSIONINFOW lpVersionInformation);
-
-typedef ULONG (NTAPI *sRtlNtStatusToDosError)
-              (NTSTATUS Status);
-
-typedef NTSTATUS (NTAPI *sNtDeviceIoControlFile)
-                 (HANDLE FileHandle,
-                  HANDLE Event,
-                  PIO_APC_ROUTINE ApcRoutine,
-                  PVOID ApcContext,
-                  PIO_STATUS_BLOCK IoStatusBlock,
-                  ULONG IoControlCode,
-                  PVOID InputBuffer,
-                  ULONG InputBufferLength,
-                  PVOID OutputBuffer,
-                  ULONG OutputBufferLength);
-
-typedef NTSTATUS (NTAPI *sNtQueryInformationFile)
-                 (HANDLE FileHandle,
-                  PIO_STATUS_BLOCK IoStatusBlock,
-                  PVOID FileInformation,
-                  ULONG Length,
-                  FILE_INFORMATION_CLASS FileInformationClass);
-
-typedef NTSTATUS (NTAPI *sNtSetInformationFile)
-                 (HANDLE FileHandle,
-                  PIO_STATUS_BLOCK IoStatusBlock,
-                  PVOID FileInformation,
-                  ULONG Length,
-                  FILE_INFORMATION_CLASS FileInformationClass);
-
-typedef NTSTATUS (NTAPI *sNtQueryVolumeInformationFile)
-                 (HANDLE FileHandle,
-                  PIO_STATUS_BLOCK IoStatusBlock,
-                  PVOID FsInformation,
-                  ULONG Length,
-                  FS_INFORMATION_CLASS FsInformationClass);
-
-typedef NTSTATUS (NTAPI *sNtQuerySystemInformation)
-                 (UINT SystemInformationClass,
-                  PVOID SystemInformation,
-                  ULONG SystemInformationLength,
-                  PULONG ReturnLength);
-
-typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
-                 (HANDLE FileHandle,
-                  HANDLE Event,
-                  PIO_APC_ROUTINE ApcRoutine,
-                  PVOID ApcContext,
-                  PIO_STATUS_BLOCK IoStatusBlock,
-                  PVOID FileInformation,
-                  ULONG Length,
-                  FILE_INFORMATION_CLASS FileInformationClass,
-                  BOOLEAN ReturnSingleEntry,
-                  PUNICODE_STRING FileName,
-                  BOOLEAN RestartScan
-                );
-
-/*
- * Kernel32 headers
- */
-#ifndef FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
-# define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1
-#endif
-
-#ifndef FILE_SKIP_SET_EVENT_ON_HANDLE
-# define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2
-#endif
-
-#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
-# define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
-#endif
-
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-  typedef struct _OVERLAPPED_ENTRY {
-      ULONG_PTR lpCompletionKey;
-      LPOVERLAPPED lpOverlapped;
-      ULONG_PTR Internal;
-      DWORD dwNumberOfBytesTransferred;
-  } OVERLAPPED_ENTRY, *LPOVERLAPPED_ENTRY;
-#endif
-
-/* from wincon.h */
-#ifndef ENABLE_INSERT_MODE
-# define ENABLE_INSERT_MODE 0x20
-#endif
-
-#ifndef ENABLE_QUICK_EDIT_MODE
-# define ENABLE_QUICK_EDIT_MODE 0x40
-#endif
-
-#ifndef ENABLE_EXTENDED_FLAGS
-# define ENABLE_EXTENDED_FLAGS 0x80
-#endif
-
-/* from winerror.h */
-#ifndef ERROR_ELEVATION_REQUIRED
-# define ERROR_ELEVATION_REQUIRED 740
-#endif
-
-#ifndef ERROR_SYMLINK_NOT_SUPPORTED
-# define ERROR_SYMLINK_NOT_SUPPORTED 1464
-#endif
-
-#ifndef ERROR_MUI_FILE_NOT_FOUND
-# define ERROR_MUI_FILE_NOT_FOUND 15100
-#endif
-
-#ifndef ERROR_MUI_INVALID_FILE
-# define ERROR_MUI_INVALID_FILE 15101
-#endif
-
-#ifndef ERROR_MUI_INVALID_RC_CONFIG
-# define ERROR_MUI_INVALID_RC_CONFIG 15102
-#endif
-
-#ifndef ERROR_MUI_INVALID_LOCALE_NAME
-# define ERROR_MUI_INVALID_LOCALE_NAME 15103
-#endif
-
-#ifndef ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME
-# define ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME 15104
-#endif
-
-#ifndef ERROR_MUI_FILE_NOT_LOADED
-# define ERROR_MUI_FILE_NOT_LOADED 15105
-#endif
-
-typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx)
-             (HANDLE CompletionPort,
-              LPOVERLAPPED_ENTRY lpCompletionPortEntries,
-              ULONG ulCount,
-              PULONG ulNumEntriesRemoved,
-              DWORD dwMilliseconds,
-              BOOL fAlertable);
-
-/* from powerbase.h */
-#ifndef DEVICE_NOTIFY_CALLBACK
-# define DEVICE_NOTIFY_CALLBACK 2
-#endif
-
-#ifndef PBT_APMRESUMEAUTOMATIC
-# define PBT_APMRESUMEAUTOMATIC 18
-#endif
-
-#ifndef PBT_APMRESUMESUSPEND
-# define PBT_APMRESUMESUSPEND 7
-#endif
-
-typedef ULONG CALLBACK _DEVICE_NOTIFY_CALLBACK_ROUTINE(
-  PVOID Context,
-  ULONG Type,
-  PVOID Setting
-);
-typedef _DEVICE_NOTIFY_CALLBACK_ROUTINE* _PDEVICE_NOTIFY_CALLBACK_ROUTINE;
-
-typedef struct _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS {
-  _PDEVICE_NOTIFY_CALLBACK_ROUTINE Callback;
-  PVOID Context;
-} _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS, *_PDEVICE_NOTIFY_SUBSCRIBE_PARAMETERS;
-
-typedef PVOID _HPOWERNOTIFY;
-typedef _HPOWERNOTIFY *_PHPOWERNOTIFY;
-
-typedef DWORD (WINAPI *sPowerRegisterSuspendResumeNotification)
-              (DWORD         Flags,
-               HANDLE        Recipient,
-               _PHPOWERNOTIFY RegistrationHandle);
-
-/* from Winuser.h */
-typedef VOID (CALLBACK* WINEVENTPROC)
-             (HWINEVENTHOOK hWinEventHook,
-              DWORD         event,
-              HWND          hwnd,
-              LONG          idObject,
-              LONG          idChild,
-              DWORD         idEventThread,
-              DWORD         dwmsEventTime);
-
-typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook)
-                      (UINT         eventMin,
-                       UINT         eventMax,
-                       HMODULE      hmodWinEventProc,
-                       WINEVENTPROC lpfnWinEventProc,
-                       DWORD        idProcess,
-                       DWORD        idThread,
-                       UINT         dwflags);
-
-
-/* Ntdll function pointers */
-extern sRtlGetVersion pRtlGetVersion;
-extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
-extern sNtDeviceIoControlFile pNtDeviceIoControlFile;
-extern sNtQueryInformationFile pNtQueryInformationFile;
-extern sNtSetInformationFile pNtSetInformationFile;
-extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
-extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
-extern sNtQuerySystemInformation pNtQuerySystemInformation;
-
-/* Kernel32 function pointers */
-extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
-
-/* Powrprof.dll function pointer */
-extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
-
-/* User32.dll function pointer */
-extern sSetWinEventHook pSetWinEventHook;
-
-#endif /* UV_WIN_WINAPI_H_ */
diff --git a/wpiutil/src/main/native/libuv/src/win/winsock.cpp b/wpiutil/src/main/native/libuv/src/win/winsock.cpp
deleted file mode 100644
index 668e3b6..0000000
--- a/wpiutil/src/main/native/libuv/src/win/winsock.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "uv.h"
-#include "internal.h"
-
-
-#pragma comment(lib, "Ws2_32.lib")
-
-/* Whether there are any non-IFS LSPs stacked on TCP */
-int uv_tcp_non_ifs_lsp_ipv4;
-int uv_tcp_non_ifs_lsp_ipv6;
-
-/* Ip address used to bind to any port at any interface */
-struct sockaddr_in uv_addr_ip4_any_;
-struct sockaddr_in6 uv_addr_ip6_any_;
-
-
-/*
- * Retrieves the pointer to a winsock extension function.
- */
-static BOOL uv_get_extension_function(SOCKET socket, GUID guid,
-    void **target) {
-  int result;
-  DWORD bytes;
-
-  result = WSAIoctl(socket,
-                    SIO_GET_EXTENSION_FUNCTION_POINTER,
-                    &guid,
-                    sizeof(guid),
-                    (void*)target,
-                    sizeof(*target),
-                    &bytes,
-                    NULL,
-                    NULL);
-
-  if (result == SOCKET_ERROR) {
-    *target = NULL;
-    return FALSE;
-  } else {
-    return TRUE;
-  }
-}
-
-
-BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) {
-  const GUID wsaid_acceptex = WSAID_ACCEPTEX;
-  return uv_get_extension_function(socket, wsaid_acceptex, (void**)target);
-}
-
-
-BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) {
-  const GUID wsaid_connectex = WSAID_CONNECTEX;
-  return uv_get_extension_function(socket, wsaid_connectex, (void**)target);
-}
-
-
-static int error_means_no_support(DWORD error) {
-  return error == WSAEPROTONOSUPPORT || error == WSAESOCKTNOSUPPORT ||
-         error == WSAEPFNOSUPPORT || error == WSAEAFNOSUPPORT;
-}
-
-
-void uv_winsock_init(void) {
-  WSADATA wsa_data;
-  int errorno;
-  SOCKET dummy;
-  WSAPROTOCOL_INFOW protocol_info;
-  int opt_len;
-
-  /* Set implicit binding address used by connectEx */
-  if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) {
-    abort();
-  }
-
-  if (uv_ip6_addr("::", 0, &uv_addr_ip6_any_)) {
-    abort();
-  }
-
-  /* Skip initialization in safe mode without network support */
-  if (1 == GetSystemMetrics(SM_CLEANBOOT)) return;
-
-  /* Initialize winsock */
-  errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
-  if (errorno != 0) {
-    uv_fatal_error(errorno, "WSAStartup");
-  }
-
-  /* Detect non-IFS LSPs */
-  dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
-
-  if (dummy != INVALID_SOCKET) {
-    opt_len = (int) sizeof protocol_info;
-    if (getsockopt(dummy,
-                   SOL_SOCKET,
-                   SO_PROTOCOL_INFOW,
-                   (char*) &protocol_info,
-                   &opt_len) == SOCKET_ERROR)
-      uv_fatal_error(WSAGetLastError(), "getsockopt");
-
-    if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES))
-      uv_tcp_non_ifs_lsp_ipv4 = 1;
-
-    if (closesocket(dummy) == SOCKET_ERROR)
-      uv_fatal_error(WSAGetLastError(), "closesocket");
-
-  } else if (!error_means_no_support(WSAGetLastError())) {
-    /* Any error other than "socket type not supported" is fatal. */
-    uv_fatal_error(WSAGetLastError(), "socket");
-  }
-
-  /* Detect IPV6 support and non-IFS LSPs */
-  dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
-
-  if (dummy != INVALID_SOCKET) {
-    opt_len = (int) sizeof protocol_info;
-    if (getsockopt(dummy,
-                   SOL_SOCKET,
-                   SO_PROTOCOL_INFOW,
-                   (char*) &protocol_info,
-                   &opt_len) == SOCKET_ERROR)
-      uv_fatal_error(WSAGetLastError(), "getsockopt");
-
-    if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES))
-      uv_tcp_non_ifs_lsp_ipv6 = 1;
-
-    if (closesocket(dummy) == SOCKET_ERROR)
-      uv_fatal_error(WSAGetLastError(), "closesocket");
-
-  } else if (!error_means_no_support(WSAGetLastError())) {
-    /* Any error other than "socket type not supported" is fatal. */
-    uv_fatal_error(WSAGetLastError(), "socket");
-  }
-}
-
-
-int uv_ntstatus_to_winsock_error(NTSTATUS status) {
-  switch (status) {
-    case STATUS_SUCCESS:
-      return ERROR_SUCCESS;
-
-    case STATUS_PENDING:
-      return ERROR_IO_PENDING;
-
-    case STATUS_INVALID_HANDLE:
-    case STATUS_OBJECT_TYPE_MISMATCH:
-      return WSAENOTSOCK;
-
-    case STATUS_INSUFFICIENT_RESOURCES:
-    case STATUS_PAGEFILE_QUOTA:
-    case STATUS_COMMITMENT_LIMIT:
-    case STATUS_WORKING_SET_QUOTA:
-    case STATUS_NO_MEMORY:
-    case STATUS_QUOTA_EXCEEDED:
-    case STATUS_TOO_MANY_PAGING_FILES:
-    case STATUS_REMOTE_RESOURCES:
-      return WSAENOBUFS;
-
-    case STATUS_TOO_MANY_ADDRESSES:
-    case STATUS_SHARING_VIOLATION:
-    case STATUS_ADDRESS_ALREADY_EXISTS:
-      return WSAEADDRINUSE;
-
-    case STATUS_LINK_TIMEOUT:
-    case STATUS_IO_TIMEOUT:
-    case STATUS_TIMEOUT:
-      return WSAETIMEDOUT;
-
-    case STATUS_GRACEFUL_DISCONNECT:
-      return WSAEDISCON;
-
-    case STATUS_REMOTE_DISCONNECT:
-    case STATUS_CONNECTION_RESET:
-    case STATUS_LINK_FAILED:
-    case STATUS_CONNECTION_DISCONNECTED:
-    case STATUS_PORT_UNREACHABLE:
-    case STATUS_HOPLIMIT_EXCEEDED:
-      return WSAECONNRESET;
-
-    case STATUS_LOCAL_DISCONNECT:
-    case STATUS_TRANSACTION_ABORTED:
-    case STATUS_CONNECTION_ABORTED:
-      return WSAECONNABORTED;
-
-    case STATUS_BAD_NETWORK_PATH:
-    case STATUS_NETWORK_UNREACHABLE:
-    case STATUS_PROTOCOL_UNREACHABLE:
-      return WSAENETUNREACH;
-
-    case STATUS_HOST_UNREACHABLE:
-      return WSAEHOSTUNREACH;
-
-    case STATUS_CANCELLED:
-    case STATUS_REQUEST_ABORTED:
-      return WSAEINTR;
-
-    case STATUS_BUFFER_OVERFLOW:
-    case STATUS_INVALID_BUFFER_SIZE:
-      return WSAEMSGSIZE;
-
-    case STATUS_BUFFER_TOO_SMALL:
-    case STATUS_ACCESS_VIOLATION:
-      return WSAEFAULT;
-
-    case STATUS_DEVICE_NOT_READY:
-    case STATUS_REQUEST_NOT_ACCEPTED:
-      return WSAEWOULDBLOCK;
-
-    case STATUS_INVALID_NETWORK_RESPONSE:
-    case STATUS_NETWORK_BUSY:
-    case STATUS_NO_SUCH_DEVICE:
-    case STATUS_NO_SUCH_FILE:
-    case STATUS_OBJECT_PATH_NOT_FOUND:
-    case STATUS_OBJECT_NAME_NOT_FOUND:
-    case STATUS_UNEXPECTED_NETWORK_ERROR:
-      return WSAENETDOWN;
-
-    case STATUS_INVALID_CONNECTION:
-      return WSAENOTCONN;
-
-    case STATUS_REMOTE_NOT_LISTENING:
-    case STATUS_CONNECTION_REFUSED:
-      return WSAECONNREFUSED;
-
-    case STATUS_PIPE_DISCONNECTED:
-      return WSAESHUTDOWN;
-
-    case STATUS_CONFLICTING_ADDRESSES:
-    case STATUS_INVALID_ADDRESS:
-    case STATUS_INVALID_ADDRESS_COMPONENT:
-      return WSAEADDRNOTAVAIL;
-
-    case STATUS_NOT_SUPPORTED:
-    case STATUS_NOT_IMPLEMENTED:
-      return WSAEOPNOTSUPP;
-
-    case STATUS_ACCESS_DENIED:
-      return WSAEACCES;
-
-    default:
-      if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) &&
-          (status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) {
-        /* It's a windows error that has been previously mapped to an ntstatus
-         * code. */
-        return (DWORD) (status & 0xffff);
-      } else {
-        /* The default fallback for unmappable ntstatus codes. */
-        return WSAEINVAL;
-      }
-  }
-}
-
-
-/*
- * This function provides a workaround for a bug in the winsock implementation
- * of WSARecv. The problem is that when SetFileCompletionNotificationModes is
- * used to avoid IOCP notifications of completed reads, WSARecv does not
- * reliably indicate whether we can expect a completion package to be posted
- * when the receive buffer is smaller than the received datagram.
- *
- * However it is desirable to use SetFileCompletionNotificationModes because
- * it yields a massive performance increase.
- *
- * This function provides a workaround for that bug, but it only works for the
- * specific case that we need it for. E.g. it assumes that the "avoid iocp"
- * bit has been set, and supports only overlapped operation. It also requires
- * the user to use the default msafd driver, doesn't work when other LSPs are
- * stacked on top of it.
- */
-int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers,
-    DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped,
-    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) {
-  NTSTATUS status;
-  void* apc_context;
-  IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal;
-  AFD_RECV_INFO info;
-  DWORD error;
-
-  if (overlapped == NULL || completion_routine != NULL) {
-    WSASetLastError(WSAEINVAL);
-    return SOCKET_ERROR;
-  }
-
-  info.BufferArray = buffers;
-  info.BufferCount = buffer_count;
-  info.AfdFlags = AFD_OVERLAPPED;
-  info.TdiFlags = TDI_RECEIVE_NORMAL;
-
-  if (*flags & MSG_PEEK) {
-    info.TdiFlags |= TDI_RECEIVE_PEEK;
-  }
-
-  if (*flags & MSG_PARTIAL) {
-    info.TdiFlags |= TDI_RECEIVE_PARTIAL;
-  }
-
-  if (!((intptr_t) overlapped->hEvent & 1)) {
-    apc_context = (void*) overlapped;
-  } else {
-    apc_context = NULL;
-  }
-
-  iosb->Status = STATUS_PENDING;
-  iosb->Pointer = 0;
-
-  status = pNtDeviceIoControlFile((HANDLE) socket,
-                                  overlapped->hEvent,
-                                  NULL,
-                                  apc_context,
-                                  iosb,
-                                  IOCTL_AFD_RECEIVE,
-                                  &info,
-                                  sizeof(info),
-                                  NULL,
-                                  0);
-
-  *flags = 0;
-  *bytes = (DWORD) iosb->Information;
-
-  switch (status) {
-    case STATUS_SUCCESS:
-      error = ERROR_SUCCESS;
-      break;
-
-    case STATUS_PENDING:
-      error = WSA_IO_PENDING;
-      break;
-
-    case STATUS_BUFFER_OVERFLOW:
-      error = WSAEMSGSIZE;
-      break;
-
-    case STATUS_RECEIVE_EXPEDITED:
-      error = ERROR_SUCCESS;
-      *flags = MSG_OOB;
-      break;
-
-    case STATUS_RECEIVE_PARTIAL_EXPEDITED:
-      error = ERROR_SUCCESS;
-      *flags = MSG_PARTIAL | MSG_OOB;
-      break;
-
-    case STATUS_RECEIVE_PARTIAL:
-      error = ERROR_SUCCESS;
-      *flags = MSG_PARTIAL;
-      break;
-
-    default:
-      error = uv_ntstatus_to_winsock_error(status);
-      break;
-  }
-
-  WSASetLastError(error);
-
-  if (error == ERROR_SUCCESS) {
-    return 0;
-  } else {
-    return SOCKET_ERROR;
-  }
-}
-
-
-/* See description of uv_wsarecv_workaround. */
-int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers,
-    DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr,
-    int* addr_len, WSAOVERLAPPED *overlapped,
-    LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) {
-  NTSTATUS status;
-  void* apc_context;
-  IO_STATUS_BLOCK* iosb = (IO_STATUS_BLOCK*) &overlapped->Internal;
-  AFD_RECV_DATAGRAM_INFO info;
-  DWORD error;
-
-  if (overlapped == NULL || addr == NULL || addr_len == NULL ||
-      completion_routine != NULL) {
-    WSASetLastError(WSAEINVAL);
-    return SOCKET_ERROR;
-  }
-
-  info.BufferArray = buffers;
-  info.BufferCount = buffer_count;
-  info.AfdFlags = AFD_OVERLAPPED;
-  info.TdiFlags = TDI_RECEIVE_NORMAL;
-  info.Address = addr;
-  info.AddressLength = addr_len;
-
-  if (*flags & MSG_PEEK) {
-    info.TdiFlags |= TDI_RECEIVE_PEEK;
-  }
-
-  if (*flags & MSG_PARTIAL) {
-    info.TdiFlags |= TDI_RECEIVE_PARTIAL;
-  }
-
-  if (!((intptr_t) overlapped->hEvent & 1)) {
-    apc_context = (void*) overlapped;
-  } else {
-    apc_context = NULL;
-  }
-
-  iosb->Status = STATUS_PENDING;
-  iosb->Pointer = 0;
-
-  status = pNtDeviceIoControlFile((HANDLE) socket,
-                                  overlapped->hEvent,
-                                  NULL,
-                                  apc_context,
-                                  iosb,
-                                  IOCTL_AFD_RECEIVE_DATAGRAM,
-                                  &info,
-                                  sizeof(info),
-                                  NULL,
-                                  0);
-
-  *flags = 0;
-  *bytes = (DWORD) iosb->Information;
-
-  switch (status) {
-    case STATUS_SUCCESS:
-      error = ERROR_SUCCESS;
-      break;
-
-    case STATUS_PENDING:
-      error = WSA_IO_PENDING;
-      break;
-
-    case STATUS_BUFFER_OVERFLOW:
-      error = WSAEMSGSIZE;
-      break;
-
-    case STATUS_RECEIVE_EXPEDITED:
-      error = ERROR_SUCCESS;
-      *flags = MSG_OOB;
-      break;
-
-    case STATUS_RECEIVE_PARTIAL_EXPEDITED:
-      error = ERROR_SUCCESS;
-      *flags = MSG_PARTIAL | MSG_OOB;
-      break;
-
-    case STATUS_RECEIVE_PARTIAL:
-      error = ERROR_SUCCESS;
-      *flags = MSG_PARTIAL;
-      break;
-
-    default:
-      error = uv_ntstatus_to_winsock_error(status);
-      break;
-  }
-
-  WSASetLastError(error);
-
-  if (error == ERROR_SUCCESS) {
-    return 0;
-  } else {
-    return SOCKET_ERROR;
-  }
-}
-
-
-int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
-    AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) {
-  IO_STATUS_BLOCK iosb;
-  IO_STATUS_BLOCK* iosb_ptr;
-  HANDLE event = NULL;
-  void* apc_context;
-  NTSTATUS status;
-  DWORD error;
-
-  if (overlapped != NULL) {
-    /* Overlapped operation. */
-    iosb_ptr = (IO_STATUS_BLOCK*) &overlapped->Internal;
-    event = overlapped->hEvent;
-
-    /* Do not report iocp completion if hEvent is tagged. */
-    if ((uintptr_t) event & 1) {
-      event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1);
-      apc_context = NULL;
-    } else {
-      apc_context = overlapped;
-    }
-
-  } else {
-    /* Blocking operation. */
-    iosb_ptr = &iosb;
-    event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (event == NULL) {
-      return SOCKET_ERROR;
-    }
-    apc_context = NULL;
-  }
-
-  iosb_ptr->Status = STATUS_PENDING;
-  status = pNtDeviceIoControlFile((HANDLE) socket,
-                                  event,
-                                  NULL,
-                                  apc_context,
-                                  iosb_ptr,
-                                  IOCTL_AFD_POLL,
-                                  info_in,
-                                  sizeof *info_in,
-                                  info_out,
-                                  sizeof *info_out);
-
-  if (overlapped == NULL) {
-    /* If this is a blocking operation, wait for the event to become signaled,
-     * and then grab the real status from the io status block. */
-    if (status == STATUS_PENDING) {
-      DWORD r = WaitForSingleObject(event, INFINITE);
-
-      if (r == WAIT_FAILED) {
-        DWORD saved_error = GetLastError();
-        CloseHandle(event);
-        WSASetLastError(saved_error);
-        return SOCKET_ERROR;
-      }
-
-      status = iosb.Status;
-    }
-
-    CloseHandle(event);
-  }
-
-  switch (status) {
-    case STATUS_SUCCESS:
-      error = ERROR_SUCCESS;
-      break;
-
-    case STATUS_PENDING:
-      error = WSA_IO_PENDING;
-      break;
-
-    default:
-      error = uv_ntstatus_to_winsock_error(status);
-      break;
-  }
-
-  WSASetLastError(error);
-
-  if (error == ERROR_SUCCESS) {
-    return 0;
-  } else {
-    return SOCKET_ERROR;
-  }
-}
-
-int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
-                                            struct sockaddr_storage* storage) {
-  struct sockaddr_in* dest4;
-  struct sockaddr_in6* dest6;
-
-  if (addr == NULL)
-    return UV_EINVAL;
-
-  switch (addr->sa_family) {
-  case AF_INET:
-    dest4 = (struct sockaddr_in*) storage;
-    memcpy(dest4, addr, sizeof(*dest4));
-    if (dest4->sin_addr.s_addr == 0)
-      dest4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-    return 0;
-  case AF_INET6:
-    dest6 = (struct sockaddr_in6*) storage;
-    memcpy(dest6, addr, sizeof(*dest6));
-    if (memcmp(&dest6->sin6_addr,
-               &uv_addr_ip6_any_.sin6_addr,
-               sizeof(uv_addr_ip6_any_.sin6_addr)) == 0) {
-      struct in6_addr init_sin6_addr = IN6ADDR_LOOPBACK_INIT;
-      dest6->sin6_addr = init_sin6_addr;
-    }
-    return 0;
-  default:
-    return UV_EINVAL;
-  }
-}
diff --git a/wpiutil/src/main/native/libuv/src/win/winsock.h b/wpiutil/src/main/native/libuv/src/win/winsock.h
deleted file mode 100644
index 7ecb755..0000000
--- a/wpiutil/src/main/native/libuv/src/win/winsock.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef UV_WIN_WINSOCK_H_
-#define UV_WIN_WINSOCK_H_
-
-#include <winsock2.h>
-#include <iptypes.h>
-#include <mswsock.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-
-#include "winapi.h"
-
-
-/*
- * MinGW is missing these too
- */
-#ifndef SO_UPDATE_CONNECT_CONTEXT
-# define SO_UPDATE_CONNECT_CONTEXT 0x7010
-#endif
-
-#ifndef TCP_KEEPALIVE
-# define TCP_KEEPALIVE 3
-#endif
-
-#ifndef IPV6_V6ONLY
-# define IPV6_V6ONLY 27
-#endif
-
-#ifndef IPV6_HOPLIMIT
-# define IPV6_HOPLIMIT 21
-#endif
-
-#ifndef SIO_BASE_HANDLE
-# define SIO_BASE_HANDLE 0x48000022
-#endif
-
-/*
- * TDI defines that are only in the DDK.
- * We only need receive flags so far.
- */
-#ifndef TDI_RECEIVE_NORMAL
-  #define TDI_RECEIVE_BROADCAST           0x00000004
-  #define TDI_RECEIVE_MULTICAST           0x00000008
-  #define TDI_RECEIVE_PARTIAL             0x00000010
-  #define TDI_RECEIVE_NORMAL              0x00000020
-  #define TDI_RECEIVE_EXPEDITED           0x00000040
-  #define TDI_RECEIVE_PEEK                0x00000080
-  #define TDI_RECEIVE_NO_RESPONSE_EXP     0x00000100
-  #define TDI_RECEIVE_COPY_LOOKAHEAD      0x00000200
-  #define TDI_RECEIVE_ENTIRE_MESSAGE      0x00000400
-  #define TDI_RECEIVE_AT_DISPATCH_LEVEL   0x00000800
-  #define TDI_RECEIVE_CONTROL_INFO        0x00001000
-  #define TDI_RECEIVE_FORCE_INDICATION    0x00002000
-  #define TDI_RECEIVE_NO_PUSH             0x00004000
-#endif
-
-/*
- * The "Auxiliary Function Driver" is the windows kernel-mode driver that does
- * TCP, UDP etc. Winsock is just a layer that dispatches requests to it.
- * Having these definitions allows us to bypass winsock and make an AFD kernel
- * call directly, avoiding a bug in winsock's recvfrom implementation.
- */
-
-#define AFD_NO_FAST_IO   0x00000001
-#define AFD_OVERLAPPED   0x00000002
-#define AFD_IMMEDIATE    0x00000004
-
-#define AFD_POLL_RECEIVE_BIT            0
-#define AFD_POLL_RECEIVE                (1 << AFD_POLL_RECEIVE_BIT)
-#define AFD_POLL_RECEIVE_EXPEDITED_BIT  1
-#define AFD_POLL_RECEIVE_EXPEDITED      (1 << AFD_POLL_RECEIVE_EXPEDITED_BIT)
-#define AFD_POLL_SEND_BIT               2
-#define AFD_POLL_SEND                   (1 << AFD_POLL_SEND_BIT)
-#define AFD_POLL_DISCONNECT_BIT         3
-#define AFD_POLL_DISCONNECT             (1 << AFD_POLL_DISCONNECT_BIT)
-#define AFD_POLL_ABORT_BIT              4
-#define AFD_POLL_ABORT                  (1 << AFD_POLL_ABORT_BIT)
-#define AFD_POLL_LOCAL_CLOSE_BIT        5
-#define AFD_POLL_LOCAL_CLOSE            (1 << AFD_POLL_LOCAL_CLOSE_BIT)
-#define AFD_POLL_CONNECT_BIT            6
-#define AFD_POLL_CONNECT                (1 << AFD_POLL_CONNECT_BIT)
-#define AFD_POLL_ACCEPT_BIT             7
-#define AFD_POLL_ACCEPT                 (1 << AFD_POLL_ACCEPT_BIT)
-#define AFD_POLL_CONNECT_FAIL_BIT       8
-#define AFD_POLL_CONNECT_FAIL           (1 << AFD_POLL_CONNECT_FAIL_BIT)
-#define AFD_POLL_QOS_BIT                9
-#define AFD_POLL_QOS                    (1 << AFD_POLL_QOS_BIT)
-#define AFD_POLL_GROUP_QOS_BIT          10
-#define AFD_POLL_GROUP_QOS              (1 << AFD_POLL_GROUP_QOS_BIT)
-
-#define AFD_NUM_POLL_EVENTS             11
-#define AFD_POLL_ALL                    ((1 << AFD_NUM_POLL_EVENTS) - 1)
-
-typedef struct _AFD_RECV_DATAGRAM_INFO {
-    LPWSABUF BufferArray;
-    ULONG BufferCount;
-    ULONG AfdFlags;
-    ULONG TdiFlags;
-    struct sockaddr* Address;
-    int* AddressLength;
-} AFD_RECV_DATAGRAM_INFO, *PAFD_RECV_DATAGRAM_INFO;
-
-typedef struct _AFD_RECV_INFO {
-    LPWSABUF BufferArray;
-    ULONG BufferCount;
-    ULONG AfdFlags;
-    ULONG TdiFlags;
-} AFD_RECV_INFO, *PAFD_RECV_INFO;
-
-
-#define _AFD_CONTROL_CODE(operation, method) \
-    ((FSCTL_AFD_BASE) << 12 | (operation << 2) | method)
-
-#define FSCTL_AFD_BASE FILE_DEVICE_NETWORK
-
-#define AFD_RECEIVE            5
-#define AFD_RECEIVE_DATAGRAM   6
-#define AFD_POLL               9
-
-#define IOCTL_AFD_RECEIVE \
-    _AFD_CONTROL_CODE(AFD_RECEIVE, METHOD_NEITHER)
-
-#define IOCTL_AFD_RECEIVE_DATAGRAM \
-    _AFD_CONTROL_CODE(AFD_RECEIVE_DATAGRAM, METHOD_NEITHER)
-
-#define IOCTL_AFD_POLL \
-    _AFD_CONTROL_CODE(AFD_POLL, METHOD_BUFFERED)
-
-#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
-typedef struct _IP_ADAPTER_UNICAST_ADDRESS_XP {
-  /* FIXME: __C89_NAMELESS was removed */
-  /* __C89_NAMELESS */ union {
-    ULONGLONG Alignment;
-    /* __C89_NAMELESS */ struct {
-      ULONG Length;
-      DWORD Flags;
-    };
-  };
-  struct _IP_ADAPTER_UNICAST_ADDRESS_XP *Next;
-  SOCKET_ADDRESS Address;
-  IP_PREFIX_ORIGIN PrefixOrigin;
-  IP_SUFFIX_ORIGIN SuffixOrigin;
-  IP_DAD_STATE DadState;
-  ULONG ValidLifetime;
-  ULONG PreferredLifetime;
-  ULONG LeaseLifetime;
-} IP_ADAPTER_UNICAST_ADDRESS_XP,*PIP_ADAPTER_UNICAST_ADDRESS_XP;
-
-typedef struct _IP_ADAPTER_UNICAST_ADDRESS_LH {
-  union {
-    ULONGLONG Alignment;
-    struct {
-      ULONG Length;
-      DWORD Flags;
-    };
-  };
-  struct _IP_ADAPTER_UNICAST_ADDRESS_LH *Next;
-  SOCKET_ADDRESS Address;
-  IP_PREFIX_ORIGIN PrefixOrigin;
-  IP_SUFFIX_ORIGIN SuffixOrigin;
-  IP_DAD_STATE DadState;
-  ULONG ValidLifetime;
-  ULONG PreferredLifetime;
-  ULONG LeaseLifetime;
-  UINT8 OnLinkPrefixLength;
-} IP_ADAPTER_UNICAST_ADDRESS_LH,*PIP_ADAPTER_UNICAST_ADDRESS_LH;
-
-#endif
-
-int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
-                                            struct sockaddr_storage* storage);
-
-#endif /* UV_WIN_WINSOCK_H_ */
diff --git a/wpiutil/src/main/native/linux/AvahiClient.cpp b/wpiutil/src/main/native/linux/AvahiClient.cpp
deleted file mode 100644
index 6a17ea0..0000000
--- a/wpiutil/src/main/native/linux/AvahiClient.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "AvahiClient.h"
-
-#include <wpi/mutex.h>
-
-#include <thread>
-
-#include "dlfcn.h"
-
-using namespace wpi;
-
-#define AvahiFunctionLoad(snake_name)                                          \
-  do {                                                                         \
-    snake_name =                                                               \
-        reinterpret_cast<snake_name##_func>(dlsym(lib, "avahi_" #snake_name)); \
-    if (!snake_name) {                                                         \
-      return;                                                                  \
-    }                                                                          \
-  } while (false)
-
-AvahiFunctionTable::AvahiFunctionTable() {
-  void* lib = dlopen("libavahi-common.so.3", RTLD_LAZY);
-
-  valid = false;
-
-  if (lib == nullptr) {
-    return;
-  }
-
-  AvahiFunctionLoad(threaded_poll_new);
-  AvahiFunctionLoad(threaded_poll_free);
-  AvahiFunctionLoad(threaded_poll_get);
-  AvahiFunctionLoad(threaded_poll_start);
-  AvahiFunctionLoad(threaded_poll_stop);
-  AvahiFunctionLoad(threaded_poll_lock);
-  AvahiFunctionLoad(threaded_poll_unlock);
-  AvahiFunctionLoad(string_list_new_from_array);
-  AvahiFunctionLoad(string_list_free);
-  AvahiFunctionLoad(unescape_label);
-  AvahiFunctionLoad(alternative_service_name);
-  AvahiFunctionLoad(free);
-
-  lib = dlopen("libavahi-client.so.3", RTLD_LAZY);
-
-  if (lib == nullptr) {
-    return;
-  }
-
-  AvahiFunctionLoad(client_new);
-  AvahiFunctionLoad(client_free);
-  AvahiFunctionLoad(service_browser_new);
-  AvahiFunctionLoad(service_browser_get_client);
-  AvahiFunctionLoad(service_browser_free);
-  AvahiFunctionLoad(service_resolver_new);
-  AvahiFunctionLoad(service_resolver_free);
-  AvahiFunctionLoad(entry_group_new);
-  AvahiFunctionLoad(entry_group_free);
-  AvahiFunctionLoad(entry_group_add_service_strlst);
-  AvahiFunctionLoad(entry_group_reset);
-  AvahiFunctionLoad(entry_group_is_empty);
-  AvahiFunctionLoad(entry_group_commit);
-  AvahiFunctionLoad(entry_group_get_client);
-
-  valid = true;
-}
-
-AvahiFunctionTable& AvahiFunctionTable::Get() {
-  static AvahiFunctionTable table;
-  return table;
-}
-
-static wpi::mutex ThreadLoopLock;
-static std::weak_ptr<AvahiThread> ThreadLoop;
-
-std::shared_ptr<AvahiThread> AvahiThread::Get() {
-  std::scoped_lock lock{ThreadLoopLock};
-  auto locked = ThreadLoop.lock();
-  if (!locked) {
-    locked = std::make_unique<AvahiThread>(private_init{});
-    ThreadLoop = locked;
-  }
-  return locked;
-}
-
-AvahiThread::AvahiThread(const private_init&) {
-  if (!table.IsValid()) {
-    return;
-  }
-
-  threadedPoll = table.threaded_poll_new();
-  table.threaded_poll_start(threadedPoll);
-}
-
-AvahiThread::~AvahiThread() noexcept {
-  if (!table.IsValid()) {
-    return;
-  }
-
-  if (threadedPoll) {
-    table.threaded_poll_stop(threadedPoll);
-    table.threaded_poll_free(threadedPoll);
-  }
-}
-
-void AvahiThread::lock() {
-  table.threaded_poll_lock(threadedPoll);
-}
-
-void AvahiThread::unlock() {
-  table.threaded_poll_unlock(threadedPoll);
-}
-
-const AvahiPoll* AvahiThread::GetPoll() const {
-  return table.threaded_poll_get(threadedPoll);
-}
diff --git a/wpiutil/src/main/native/linux/AvahiClient.h b/wpiutil/src/main/native/linux/AvahiClient.h
deleted file mode 100644
index ca679bb..0000000
--- a/wpiutil/src/main/native/linux/AvahiClient.h
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <stdint.h>
-
-#include <memory>
-
-/***
-  This file is part of avahi.
-  avahi 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.1 of the
-  License, or (at your option) any later version.
-  avahi 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 avahi; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-  USA.
-***/
-
-typedef struct AvahiPoll AvahiPoll;
-
-typedef enum {
-  AVAHI_SERVER_INVALID,
-  AVAHI_SERVER_REGISTERING,
-  AVAHI_SERVER_RUNNING,
-  AVAHI_SERVER_COLLISION,
-  AVAHI_SERVER_FAILURE
-} AvahiServerState;
-
-typedef struct AvahiClient AvahiClient;
-
-typedef enum {
-  AVAHI_CLIENT_S_REGISTERING = AVAHI_SERVER_REGISTERING,
-  AVAHI_CLIENT_S_RUNNING = AVAHI_SERVER_RUNNING,
-  AVAHI_CLIENT_S_COLLISION = AVAHI_SERVER_COLLISION,
-  AVAHI_CLIENT_FAILURE = 100,
-  AVAHI_CLIENT_CONNECTING = 101
-} AvahiClientState;
-
-typedef enum {
-  AVAHI_CLIENT_IGNORE_USER_CONFIG = 1,
-  AVAHI_CLIENT_NO_FAIL = 2
-} AvahiClientFlags;
-
-typedef void (*AvahiClientCallback)(AvahiClient* s, AvahiClientState state,
-                                    void* userdata);
-
-typedef struct AvahiServiceBrowser AvahiServiceBrowser;
-
-typedef int AvahiProtocol;
-
-typedef int AvahiIfIndex;
-
-typedef enum {
-  AVAHI_BROWSER_NEW,
-  AVAHI_BROWSER_REMOVE,
-  AVAHI_BROWSER_CACHE_EXHAUSTED,
-  AVAHI_BROWSER_ALL_FOR_NOW,
-  AVAHI_BROWSER_FAILURE
-} AvahiBrowserEvent;
-
-typedef enum {
-  AVAHI_LOOKUP_RESULT_CACHED = 1,
-  AVAHI_LOOKUP_RESULT_WIDE_AREA = 2,
-  AVAHI_LOOKUP_RESULT_MULTICAST = 4,
-  AVAHI_LOOKUP_RESULT_LOCAL = 8,
-  AVAHI_LOOKUP_RESULT_OUR_OWN = 16,
-  AVAHI_LOOKUP_RESULT_STATIC = 32
-} AvahiLookupResultFlags;
-
-typedef void (*AvahiServiceBrowserCallback)(
-    AvahiServiceBrowser* b, AvahiIfIndex interface, AvahiProtocol protocol,
-    AvahiBrowserEvent event, const char* name, const char* type,
-    const char* domain, AvahiLookupResultFlags flags, void* userdata);
-
-typedef enum {
-  AVAHI_LOOKUP_USE_WIDE_AREA = 1,
-  AVAHI_LOOKUP_USE_MULTICAST = 2,
-
-  AVAHI_LOOKUP_NO_TXT = 4,
-  AVAHI_LOOKUP_NO_ADDRESS = 8
-} AvahiLookupFlags;
-
-typedef struct AvahiServiceResolver AvahiServiceResolver;
-
-typedef enum {
-  AVAHI_RESOLVER_FOUND,
-  AVAHI_RESOLVER_FAILURE
-} AvahiResolverEvent;
-
-typedef struct AvahiIPv4Address {
-  uint32_t address;
-} AvahiIPv4Address;
-
-typedef struct AvahiIPv6Address {
-  uint8_t address[16];
-} AvahiIPv6Address;
-
-typedef struct AvahiAddress {
-  AvahiProtocol proto;
-
-  union {
-    AvahiIPv6Address ipv6;
-    AvahiIPv4Address ipv4;
-    uint8_t data[1];
-  } data;
-} AvahiAddress;
-
-typedef struct AvahiStringList {
-  struct AvahiStringList* next;
-  size_t size;
-  uint8_t text[1];
-} AvahiStringList;
-
-typedef void (*AvahiServiceResolverCallback)(
-    AvahiServiceResolver* r, AvahiIfIndex interface, AvahiProtocol protocol,
-    AvahiResolverEvent event, const char* name, const char* type,
-    const char* domain, const char* host_name, const AvahiAddress* a,
-    uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags flags,
-    void* userdata);
-
-typedef struct AvahiThreadedPoll AvahiThreadedPoll;
-
-typedef struct AvahiEntryGroup AvahiEntryGroup;
-
-typedef enum {
-  AVAHI_ENTRY_GROUP_UNCOMMITED,
-  AVAHI_ENTRY_GROUP_REGISTERING,
-  AVAHI_ENTRY_GROUP_ESTABLISHED,
-  AVAHI_ENTRY_GROUP_COLLISION,
-  AVAHI_ENTRY_GROUP_FAILURE
-} AvahiEntryGroupState;
-
-typedef void (*AvahiEntryGroupCallback)(AvahiEntryGroup* g,
-                                        AvahiEntryGroupState state,
-                                        void* userdata);
-
-typedef enum {
-  AVAHI_PUBLISH_UNIQUE = 1,
-  AVAHI_PUBLISH_NO_PROBE = 2,
-  AVAHI_PUBLISH_NO_ANNOUNCE = 4,
-  AVAHI_PUBLISH_ALLOW_MULTIPLE = 8,
-
-  AVAHI_PUBLISH_NO_REVERSE = 16,
-  AVAHI_PUBLISH_NO_COOKIE = 32,
-  AVAHI_PUBLISH_UPDATE = 64,
-  AVAHI_PUBLISH_USE_WIDE_AREA = 128,
-  AVAHI_PUBLISH_USE_MULTICAST = 256
-} AvahiPublishFlags;
-
-enum { AVAHI_IF_UNSPEC = -1 };
-
-enum { AVAHI_PROTO_INET = 0, AVAHI_PROTO_INET6 = 1, AVAHI_PROTO_UNSPEC = -1 };
-
-enum {
-  AVAHI_OK = 0,
-  AVAHI_ERR_FAILURE = -1,
-  AVAHI_ERR_BAD_STATE = -2,
-  AVAHI_ERR_INVALID_HOST_NAME = -3,
-  AVAHI_ERR_INVALID_DOMAIN_NAME = -4,
-  AVAHI_ERR_NO_NETWORK = -5,
-  AVAHI_ERR_INVALID_TTL = -6,
-  AVAHI_ERR_IS_PATTERN = -7,
-  AVAHI_ERR_COLLISION = -8,
-  AVAHI_ERR_INVALID_RECORD = -9,
-
-  AVAHI_ERR_INVALID_SERVICE_NAME = -10,
-  AVAHI_ERR_INVALID_SERVICE_TYPE = -11,
-  AVAHI_ERR_INVALID_PORT = -12,
-  AVAHI_ERR_INVALID_KEY = -13,
-  AVAHI_ERR_INVALID_ADDRESS = -14,
-  AVAHI_ERR_TIMEOUT = -15,
-  AVAHI_ERR_TOO_MANY_CLIENTS = -16,
-  AVAHI_ERR_TOO_MANY_OBJECTS = -17,
-  AVAHI_ERR_TOO_MANY_ENTRIES = -18,
-  AVAHI_ERR_OS = -19,
-
-  AVAHI_ERR_ACCESS_DENIED = -20,
-  AVAHI_ERR_INVALID_OPERATION = -21,
-  AVAHI_ERR_DBUS_ERROR = -22,
-  AVAHI_ERR_DISCONNECTED = -23,
-  AVAHI_ERR_NO_MEMORY = -24,
-  AVAHI_ERR_INVALID_OBJECT = -25,
-  AVAHI_ERR_NO_DAEMON = -26,
-  AVAHI_ERR_INVALID_INTERFACE = -27,
-  AVAHI_ERR_INVALID_PROTOCOL = -28,
-  AVAHI_ERR_INVALID_FLAGS = -29,
-
-  AVAHI_ERR_NOT_FOUND = -30,
-  AVAHI_ERR_INVALID_CONFIG = -31,
-  AVAHI_ERR_VERSION_MISMATCH = -32,
-  AVAHI_ERR_INVALID_SERVICE_SUBTYPE = -33,
-  AVAHI_ERR_INVALID_PACKET = -34,
-  AVAHI_ERR_INVALID_DNS_ERROR = -35,
-  AVAHI_ERR_DNS_FORMERR = -36,
-  AVAHI_ERR_DNS_SERVFAIL = -37,
-  AVAHI_ERR_DNS_NXDOMAIN = -38,
-  AVAHI_ERR_DNS_NOTIMP = -39,
-
-  AVAHI_ERR_DNS_REFUSED = -40,
-  AVAHI_ERR_DNS_YXDOMAIN = -41,
-  AVAHI_ERR_DNS_YXRRSET = -42,
-  AVAHI_ERR_DNS_NXRRSET = -43,
-  AVAHI_ERR_DNS_NOTAUTH = -44,
-  AVAHI_ERR_DNS_NOTZONE = -45,
-  AVAHI_ERR_INVALID_RDATA = -46,
-  AVAHI_ERR_INVALID_DNS_CLASS = -47,
-  AVAHI_ERR_INVALID_DNS_TYPE = -48,
-  AVAHI_ERR_NOT_SUPPORTED = -49,
-
-  AVAHI_ERR_NOT_PERMITTED = -50,
-  AVAHI_ERR_INVALID_ARGUMENT = -51,
-  AVAHI_ERR_IS_EMPTY = -52,
-  AVAHI_ERR_NO_CHANGE = -53,
-
-  AVAHI_ERR_MAX = -54
-};
-
-namespace wpi {
-class AvahiFunctionTable {
- public:
-#define AvahiFunction(CapName, RetType, Parameters) \
-  using CapName##_func = RetType(*) Parameters;     \
-  CapName##_func CapName = nullptr
-
-  AvahiFunction(threaded_poll_new, AvahiThreadedPoll*, (void));
-  AvahiFunction(threaded_poll_free, void, (AvahiThreadedPoll*));
-  AvahiFunction(threaded_poll_get, const AvahiPoll*, (AvahiThreadedPoll*));
-  AvahiFunction(threaded_poll_start, int, (AvahiThreadedPoll*));
-  AvahiFunction(threaded_poll_stop, int, (AvahiThreadedPoll*));
-  AvahiFunction(threaded_poll_lock, int, (AvahiThreadedPoll*));
-  AvahiFunction(threaded_poll_unlock, int, (AvahiThreadedPoll*));
-
-  AvahiFunction(client_new, AvahiClient*,
-                (const AvahiPoll* poll_api, AvahiClientFlags flags,
-                 AvahiClientCallback callback, void* userdata, int* error));
-  AvahiFunction(client_free, void, (AvahiClient*));
-
-  AvahiFunction(service_browser_new, AvahiServiceBrowser*,
-                (AvahiClient * client, AvahiIfIndex interface,
-                 AvahiProtocol protocol, const char* type, const char* domain,
-                 AvahiLookupFlags flags, AvahiServiceBrowserCallback callback,
-                 void* userdata));
-
-  AvahiFunction(service_browser_free, int, (AvahiServiceBrowser*));
-
-  AvahiFunction(service_resolver_new, AvahiServiceResolver*,
-                (AvahiClient * client, AvahiIfIndex interface,
-                 AvahiProtocol protocol, const char* name, const char* type,
-                 const char* domain, AvahiProtocol aprotocol,
-                 AvahiLookupFlags flags, AvahiServiceResolverCallback callback,
-                 void* userdata));
-  AvahiFunction(service_resolver_free, int, (AvahiServiceResolver*));
-
-  AvahiFunction(entry_group_new, AvahiEntryGroup*,
-                (AvahiClient*, AvahiEntryGroupCallback, void*));
-  AvahiFunction(entry_group_free, int, (AvahiEntryGroup*));
-
-  AvahiFunction(entry_group_add_service_strlst, int,
-                (AvahiEntryGroup * group, AvahiIfIndex interface,
-                 AvahiProtocol protocol, AvahiPublishFlags flags,
-                 const char* name, const char* type, const char* domain,
-                 const char* host, uint16_t port, AvahiStringList*));
-
-  AvahiFunction(entry_group_reset, int, (AvahiEntryGroup*));
-  AvahiFunction(entry_group_is_empty, int, (AvahiEntryGroup*));
-  AvahiFunction(entry_group_commit, int, (AvahiEntryGroup*));
-  AvahiFunction(entry_group_get_client, AvahiClient*, (AvahiEntryGroup*));
-
-  AvahiFunction(string_list_new_from_array, AvahiStringList*,
-                (const char** array, int len));
-  AvahiFunction(string_list_free, void, (AvahiStringList*));
-
-  AvahiFunction(service_browser_get_client, AvahiClient*,
-                (AvahiServiceBrowser*));
-
-  AvahiFunction(unescape_label, char*, (const char**, char*, size_t));
-  AvahiFunction(alternative_service_name, char*, (const char*));
-  AvahiFunction(free, void, (void*));
-
-  bool IsValid() const { return valid; }
-
-  static AvahiFunctionTable& Get();
-
- private:
-  AvahiFunctionTable();
-  bool valid;
-};
-
-class AvahiThread {
- private:
-  struct private_init {};
-
- public:
-  explicit AvahiThread(const private_init&);
-  ~AvahiThread() noexcept;
-
-  void lock();
-  const AvahiPoll* GetPoll() const;
-  void unlock();
-
-  static std::shared_ptr<AvahiThread> Get();
-
- private:
-  AvahiThreadedPoll* threadedPoll;
-  AvahiFunctionTable& table = AvahiFunctionTable::Get();
-};
-
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/linux/MulticastServiceAnnouncer.cpp b/wpiutil/src/main/native/linux/MulticastServiceAnnouncer.cpp
deleted file mode 100644
index 1a7af39..0000000
--- a/wpiutil/src/main/native/linux/MulticastServiceAnnouncer.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/MulticastServiceAnnouncer.h"
-
-#include <vector>
-
-#include "AvahiClient.h"
-#include "fmt/format.h"
-#include "wpi/mutex.h"
-
-using namespace wpi;
-
-struct MulticastServiceAnnouncer::Impl {
-  AvahiFunctionTable& table = AvahiFunctionTable::Get();
-  std::shared_ptr<AvahiThread> thread = AvahiThread::Get();
-  AvahiClient* client;
-  AvahiEntryGroup* group = nullptr;
-  std::string serviceName;
-  std::string serviceType;
-  int port;
-  AvahiStringList* stringList = nullptr;
-
-  ~Impl() noexcept {
-    if (stringList != nullptr && table.IsValid()) {
-      table.string_list_free(stringList);
-    }
-  }
-
-  template <typename T>
-  Impl(std::string_view serviceName, std::string_view serviceType, int port,
-       wpi::span<const std::pair<T, T>> txt);
-};
-
-template <typename T>
-MulticastServiceAnnouncer::Impl::Impl(std::string_view serviceName,
-                                      std::string_view serviceType, int port,
-                                      wpi::span<const std::pair<T, T>> txt) {
-  if (!this->table.IsValid()) {
-    return;
-  }
-
-  this->serviceName = serviceName;
-  this->serviceType = serviceType;
-  this->port = port;
-
-  std::vector<std::string> txts;
-  for (auto&& i : txt) {
-    txts.push_back(fmt::format("{}={}", i.first, i.second));
-  }
-
-  std::vector<const char*> txtArr;
-  for (auto&& i : txts) {
-    txtArr.push_back(i.c_str());
-  }
-
-  this->stringList =
-      this->table.string_list_new_from_array(txtArr.data(), txtArr.size());
-}
-
-static void RegisterService(AvahiClient* client,
-                            MulticastServiceAnnouncer::Impl* impl);
-
-static void EntryGroupCallback(AvahiEntryGroup* group,
-                               AvahiEntryGroupState state, void* userdata) {
-  if (state == AVAHI_ENTRY_GROUP_COLLISION) {
-    // Remote collision
-    MulticastServiceAnnouncer::Impl* impl =
-        reinterpret_cast<MulticastServiceAnnouncer::Impl*>(userdata);
-    char* newName =
-        impl->table.alternative_service_name(impl->serviceName.c_str());
-    impl->serviceName = newName;
-    impl->table.free(newName);
-    RegisterService(impl->table.entry_group_get_client(group), impl);
-  }
-}
-
-static void RegisterService(AvahiClient* client,
-                            MulticastServiceAnnouncer::Impl* impl) {
-  if (impl->group == nullptr) {
-    impl->group = impl->table.entry_group_new(client, EntryGroupCallback, impl);
-  }
-
-  while (true) {
-    if (impl->table.entry_group_is_empty(impl->group)) {
-      auto ret = impl->table.entry_group_add_service_strlst(
-          impl->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
-          AVAHI_PUBLISH_USE_MULTICAST, impl->serviceName.c_str(),
-          impl->serviceType.c_str(), "local", nullptr, impl->port,
-          impl->stringList);
-      if (ret == AVAHI_ERR_COLLISION) {
-        // Local collision
-        char* newName =
-            impl->table.alternative_service_name(impl->serviceName.c_str());
-        impl->serviceName = newName;
-        impl->table.free(newName);
-        continue;
-      } else if (ret != AVAHI_OK) {
-        break;
-      }
-      impl->table.entry_group_commit(impl->group);
-      break;
-    }
-  }
-}
-
-static void ClientCallback(AvahiClient* client, AvahiClientState state,
-                           void* userdata) {
-  MulticastServiceAnnouncer::Impl* impl =
-      reinterpret_cast<MulticastServiceAnnouncer::Impl*>(userdata);
-
-  if (state == AVAHI_CLIENT_S_RUNNING) {
-    RegisterService(client, impl);
-  } else if (state == AVAHI_CLIENT_S_COLLISION ||
-             state == AVAHI_CLIENT_S_REGISTERING) {
-    if (impl->group) {
-      impl->table.entry_group_reset(impl->group);
-    }
-  }
-}
-
-MulticastServiceAnnouncer::MulticastServiceAnnouncer(
-    std::string_view serviceName, std::string_view serviceType, int port,
-    wpi::span<const std::pair<std::string, std::string>> txt) {
-  pImpl = std::make_unique<Impl>(serviceName, serviceType, port, txt);
-}
-
-MulticastServiceAnnouncer::MulticastServiceAnnouncer(
-    std::string_view serviceName, std::string_view serviceType, int port,
-    wpi::span<const std::pair<std::string_view, std::string_view>> txt) {
-  pImpl = std::make_unique<Impl>(serviceName, serviceType, port, txt);
-}
-
-MulticastServiceAnnouncer::~MulticastServiceAnnouncer() noexcept {
-  Stop();
-}
-
-bool MulticastServiceAnnouncer::HasImplementation() const {
-  return pImpl->table.IsValid();
-}
-
-void MulticastServiceAnnouncer::Start() {
-  if (!pImpl->table.IsValid()) {
-    return;
-  }
-  std::scoped_lock lock{*pImpl->thread};
-  if (pImpl->client) {
-    return;
-  }
-  pImpl->client =
-      pImpl->table.client_new(pImpl->thread->GetPoll(), AVAHI_CLIENT_NO_FAIL,
-                              ClientCallback, pImpl.get(), nullptr);
-}
-
-void MulticastServiceAnnouncer::Stop() {
-  if (!pImpl->table.IsValid()) {
-    return;
-  }
-  std::scoped_lock lock{*pImpl->thread};
-  if (pImpl->client) {
-    if (pImpl->group) {
-      pImpl->table.entry_group_free(pImpl->group);
-      pImpl->group = nullptr;
-    }
-    pImpl->table.client_free(pImpl->client);
-    pImpl->client = nullptr;
-  }
-}
diff --git a/wpiutil/src/main/native/linux/MulticastServiceResolver.cpp b/wpiutil/src/main/native/linux/MulticastServiceResolver.cpp
deleted file mode 100644
index 6585443..0000000
--- a/wpiutil/src/main/native/linux/MulticastServiceResolver.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/MulticastServiceResolver.h"
-
-#include "AvahiClient.h"
-#include "wpi/SmallString.h"
-#include "wpi/StringExtras.h"
-#include "wpi/mutex.h"
-
-using namespace wpi;
-
-struct MulticastServiceResolver::Impl {
-  AvahiFunctionTable& table = AvahiFunctionTable::Get();
-  std::shared_ptr<AvahiThread> thread = AvahiThread::Get();
-  AvahiClient* client;
-  AvahiServiceBrowser* browser;
-  std::string serviceType;
-  MulticastServiceResolver* resolver;
-
-  void onFound(ServiceData&& data) {
-    resolver->PushData(std::forward<ServiceData>(data));
-  }
-};
-
-MulticastServiceResolver::MulticastServiceResolver(
-    std::string_view serviceType) {
-  pImpl = std::make_unique<Impl>();
-  pImpl->serviceType = serviceType;
-  pImpl->resolver = this;
-}
-
-MulticastServiceResolver::~MulticastServiceResolver() noexcept {
-  Stop();
-}
-
-bool MulticastServiceResolver::HasImplementation() const {
-  return pImpl->table.IsValid();
-}
-
-static void ResolveCallback(AvahiServiceResolver* r, AvahiIfIndex interface,
-                            AvahiProtocol protocol, AvahiResolverEvent event,
-                            const char* name, const char* type,
-                            const char* domain, const char* host_name,
-                            const AvahiAddress* address, uint16_t port,
-                            AvahiStringList* txt, AvahiLookupResultFlags flags,
-                            void* userdata) {
-  MulticastServiceResolver::Impl* impl =
-      reinterpret_cast<MulticastServiceResolver::Impl*>(userdata);
-
-  if (event == AVAHI_RESOLVER_FOUND) {
-    if (address->proto == AVAHI_PROTO_INET) {
-      AvahiStringList* strLst = txt;
-      MulticastServiceResolver::ServiceData data;
-      while (strLst != nullptr) {
-        std::string_view value{reinterpret_cast<const char*>(strLst->text),
-                               strLst->size};
-        strLst = strLst->next;
-        size_t splitIndex = value.find('=');
-        if (splitIndex == value.npos) {
-          // Todo make this just do key
-          continue;
-        }
-        std::string_view key = wpi::substr(value, 0, splitIndex);
-        value =
-            wpi::substr(value, splitIndex + 1, value.size() - splitIndex - 1);
-        data.txt.emplace_back(std::pair<std::string, std::string>{key, value});
-      }
-      wpi::SmallString<256> outputHostName;
-      char label[256];
-      do {
-        impl->table.unescape_label(&host_name, label, sizeof(label));
-        if (label[0] == '\0') {
-          break;
-        }
-        outputHostName.append(label);
-        outputHostName.append(".");
-      } while (true);
-
-      data.ipv4Address = address->data.ipv4.address;
-      data.port = port;
-      data.serviceName = name;
-      data.hostName = outputHostName.string();
-
-      impl->onFound(std::move(data));
-    }
-  }
-
-  impl->table.service_resolver_free(r);
-}
-
-static void BrowseCallback(AvahiServiceBrowser* b, AvahiIfIndex interface,
-                           AvahiProtocol protocol, AvahiBrowserEvent event,
-                           const char* name, const char* type,
-                           const char* domain, AvahiLookupResultFlags flags,
-                           void* userdata) {
-  MulticastServiceResolver::Impl* impl =
-      reinterpret_cast<MulticastServiceResolver::Impl*>(userdata);
-
-  if (event == AVAHI_BROWSER_NEW) {
-    impl->table.service_resolver_new(
-        impl->table.service_browser_get_client(b), interface, protocol, name,
-        type, domain, AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_MULTICAST,
-        ResolveCallback, userdata);
-  }
-}
-
-static void ClientCallback(AvahiClient* client, AvahiClientState state,
-                           void* userdata) {
-  MulticastServiceResolver::Impl* impl =
-      reinterpret_cast<MulticastServiceResolver::Impl*>(userdata);
-
-  if (state == AVAHI_CLIENT_S_RUNNING) {
-    impl->browser = impl->table.service_browser_new(
-        client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, impl->serviceType.c_str(),
-        "local", AvahiLookupFlags::AVAHI_LOOKUP_USE_MULTICAST, BrowseCallback,
-        userdata);
-  }
-}
-
-void MulticastServiceResolver::Start() {
-  if (!pImpl->table.IsValid()) {
-    return;
-  }
-  std::scoped_lock lock{*pImpl->thread};
-  if (pImpl->client) {
-    return;
-  }
-
-  pImpl->client =
-      pImpl->table.client_new(pImpl->thread->GetPoll(), AVAHI_CLIENT_NO_FAIL,
-                              ClientCallback, pImpl.get(), nullptr);
-}
-
-void MulticastServiceResolver::Stop() {
-  if (!pImpl->table.IsValid()) {
-    return;
-  }
-  std::scoped_lock lock{*pImpl->thread};
-  if (pImpl->client) {
-    if (pImpl->browser) {
-      pImpl->table.service_browser_free(pImpl->browser);
-      pImpl->browser = nullptr;
-    }
-    pImpl->table.client_free(pImpl->client);
-    pImpl->client = nullptr;
-  }
-}
diff --git a/wpiutil/src/main/native/macOS/MulticastServiceAnnouncer.cpp b/wpiutil/src/main/native/macOS/MulticastServiceAnnouncer.cpp
deleted file mode 100644
index ad2ff48..0000000
--- a/wpiutil/src/main/native/macOS/MulticastServiceAnnouncer.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/MulticastServiceAnnouncer.h"
-
-#include <wpi/SmallString.h>
-
-#include "dns_sd.h"
-
-using namespace wpi;
-
-struct MulticastServiceAnnouncer::Impl {
-  std::string serviceName;
-  std::string serviceType;
-  int port;
-  DNSServiceRef serviceRef{nullptr};
-  TXTRecordRef txtRecord;
-
-  Impl() { TXTRecordCreate(&txtRecord, 0, nullptr); }
-
-  ~Impl() noexcept { TXTRecordDeallocate(&txtRecord); }
-};
-
-MulticastServiceAnnouncer::MulticastServiceAnnouncer(
-    std::string_view serviceName, std::string_view serviceType, int port,
-    wpi::span<const std::pair<std::string, std::string>> txt) {
-  pImpl = std::make_unique<Impl>();
-  pImpl->serviceName = serviceName;
-  pImpl->serviceType = serviceType;
-  pImpl->port = port;
-
-  for (auto&& i : txt) {
-    TXTRecordSetValue(&pImpl->txtRecord, i.first.c_str(), i.second.length(),
-                      i.second.c_str());
-  }
-}
-
-MulticastServiceAnnouncer::MulticastServiceAnnouncer(
-    std::string_view serviceName, std::string_view serviceType, int port,
-    wpi::span<const std::pair<std::string_view, std::string_view>> txt) {
-  pImpl = std::make_unique<Impl>();
-  pImpl->serviceName = serviceName;
-  pImpl->serviceType = serviceType;
-  pImpl->port = port;
-
-  wpi::SmallString<64> key;
-
-  for (auto&& i : txt) {
-    key.clear();
-    key.append(i.first);
-    key.emplace_back('\0');
-
-    TXTRecordSetValue(&pImpl->txtRecord, key.data(), i.second.length(),
-                      i.second.data());
-  }
-}
-
-MulticastServiceAnnouncer::~MulticastServiceAnnouncer() noexcept {
-  Stop();
-}
-
-bool MulticastServiceAnnouncer::HasImplementation() const {
-  return true;
-}
-
-void MulticastServiceAnnouncer::Start() {
-  if (pImpl->serviceRef) {
-    return;
-  }
-
-  uint16_t len = TXTRecordGetLength(&pImpl->txtRecord);
-  const void* ptr = TXTRecordGetBytesPtr(&pImpl->txtRecord);
-
-  (void)DNSServiceRegister(&pImpl->serviceRef, 0, 0, pImpl->serviceName.c_str(),
-                           pImpl->serviceType.c_str(), "local", nullptr,
-                           htons(pImpl->port), len, ptr, nullptr, nullptr);
-}
-
-void MulticastServiceAnnouncer::Stop() {
-  if (!pImpl->serviceRef) {
-    return;
-  }
-  DNSServiceRefDeallocate(pImpl->serviceRef);
-  pImpl->serviceRef = nullptr;
-}
diff --git a/wpiutil/src/main/native/macOS/MulticastServiceResolver.cpp b/wpiutil/src/main/native/macOS/MulticastServiceResolver.cpp
deleted file mode 100644
index 4af8cad..0000000
--- a/wpiutil/src/main/native/macOS/MulticastServiceResolver.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "wpi/MulticastServiceResolver.h"
-
-#include <netinet/in.h>
-#include <poll.h>
-
-#include <atomic>
-#include <thread>
-#include <vector>
-
-#include "ResolverThread.h"
-#include "dns_sd.h"
-#include "wpi/SmallVector.h"
-
-using namespace wpi;
-
-struct DnsResolveState {
-  DnsResolveState(MulticastServiceResolver::Impl* impl,
-                  std::string_view serviceNameView)
-      : pImpl{impl} {
-    data.serviceName = serviceNameView;
-  }
-
-  DNSServiceRef ResolveRef = nullptr;
-  MulticastServiceResolver::Impl* pImpl;
-
-  MulticastServiceResolver::ServiceData data;
-};
-
-struct MulticastServiceResolver::Impl {
-  std::string serviceType;
-  MulticastServiceResolver* resolver;
-  std::shared_ptr<ResolverThread> thread = ResolverThread::Get();
-  std::vector<std::unique_ptr<DnsResolveState>> ResolveStates;
-  DNSServiceRef serviceRef = nullptr;
-
-  void onFound(ServiceData&& data) {
-    resolver->PushData(std::forward<ServiceData>(data));
-  }
-};
-
-MulticastServiceResolver::MulticastServiceResolver(
-    std::string_view serviceType) {
-  pImpl = std::make_unique<Impl>();
-  pImpl->serviceType = serviceType;
-  pImpl->resolver = this;
-}
-
-MulticastServiceResolver::~MulticastServiceResolver() noexcept {
-  Stop();
-}
-
-void ServiceGetAddrInfoReply(DNSServiceRef sdRef, DNSServiceFlags flags,
-                             uint32_t interfaceIndex,
-                             DNSServiceErrorType errorCode,
-                             const char* hostname,
-                             const struct sockaddr* address, uint32_t ttl,
-                             void* context) {
-  if (errorCode != kDNSServiceErr_NoError) {
-    return;
-  }
-
-  DnsResolveState* resolveState = static_cast<DnsResolveState*>(context);
-
-  resolveState->data.hostName = hostname;
-  resolveState->data.ipv4Address =
-      reinterpret_cast<const struct sockaddr_in*>(address)->sin_addr.s_addr;
-
-  resolveState->pImpl->onFound(std::move(resolveState->data));
-
-  resolveState->pImpl->thread->RemoveServiceRefInThread(
-      resolveState->ResolveRef);
-
-  resolveState->pImpl->ResolveStates.erase(std::find_if(
-      resolveState->pImpl->ResolveStates.begin(),
-      resolveState->pImpl->ResolveStates.end(),
-      [resolveState](auto& a) { return a.get() == resolveState; }));
-}
-
-void ServiceResolveReply(DNSServiceRef sdRef, DNSServiceFlags flags,
-                         uint32_t interfaceIndex, DNSServiceErrorType errorCode,
-                         const char* fullname, const char* hosttarget,
-                         uint16_t port, /* In network byte order */
-                         uint16_t txtLen, const unsigned char* txtRecord,
-                         void* context) {
-  if (errorCode != kDNSServiceErr_NoError) {
-    return;
-  }
-
-  DnsResolveState* resolveState = static_cast<DnsResolveState*>(context);
-  resolveState->pImpl->thread->RemoveServiceRefInThread(
-      resolveState->ResolveRef);
-  DNSServiceRefDeallocate(resolveState->ResolveRef);
-  resolveState->ResolveRef = nullptr;
-  resolveState->data.port = ntohs(port);
-
-  int txtCount = TXTRecordGetCount(txtLen, txtRecord);
-  char keyBuf[256];
-  uint8_t valueLen;
-  const void* value;
-
-  for (int i = 0; i < txtCount; i++) {
-    errorCode = TXTRecordGetItemAtIndex(txtLen, txtRecord, i, sizeof(keyBuf),
-                                        keyBuf, &valueLen, &value);
-    if (errorCode == kDNSServiceErr_NoError) {
-      if (valueLen == 0) {
-        // No value
-        resolveState->data.txt.emplace_back(
-            std::pair<std::string, std::string>{std::string{keyBuf}, {}});
-      } else {
-        resolveState->data.txt.emplace_back(std::pair<std::string, std::string>{
-            std::string{keyBuf},
-            std::string{reinterpret_cast<const char*>(value), valueLen}});
-      }
-    }
-  }
-
-  errorCode = DNSServiceGetAddrInfo(
-      &resolveState->ResolveRef, flags, interfaceIndex,
-      kDNSServiceProtocol_IPv4, hosttarget, ServiceGetAddrInfoReply, context);
-
-  if (errorCode == kDNSServiceErr_NoError) {
-    dnssd_sock_t socket = DNSServiceRefSockFD(resolveState->ResolveRef);
-    resolveState->pImpl->thread->AddServiceRef(resolveState->ResolveRef,
-                                               socket);
-  } else {
-    resolveState->pImpl->thread->RemoveServiceRefInThread(
-        resolveState->ResolveRef);
-    resolveState->pImpl->ResolveStates.erase(std::find_if(
-        resolveState->pImpl->ResolveStates.begin(),
-        resolveState->pImpl->ResolveStates.end(),
-        [resolveState](auto& a) { return a.get() == resolveState; }));
-  }
-}
-
-static void DnsCompletion(DNSServiceRef sdRef, DNSServiceFlags flags,
-                          uint32_t interfaceIndex,
-                          DNSServiceErrorType errorCode,
-                          const char* serviceName, const char* regtype,
-                          const char* replyDomain, void* context) {
-  if (errorCode != kDNSServiceErr_NoError) {
-    return;
-  }
-  if (!(flags & kDNSServiceFlagsAdd)) {
-    return;
-  }
-
-  MulticastServiceResolver::Impl* impl =
-      static_cast<MulticastServiceResolver::Impl*>(context);
-  auto& resolveState = impl->ResolveStates.emplace_back(
-      std::make_unique<DnsResolveState>(impl, serviceName));
-
-  errorCode = DNSServiceResolve(&resolveState->ResolveRef, 0, interfaceIndex,
-                                serviceName, regtype, replyDomain,
-                                ServiceResolveReply, resolveState.get());
-
-  if (errorCode == kDNSServiceErr_NoError) {
-    dnssd_sock_t socket = DNSServiceRefSockFD(resolveState->ResolveRef);
-    resolveState->pImpl->thread->AddServiceRef(resolveState->ResolveRef,
-                                               socket);
-  } else {
-    resolveState->pImpl->ResolveStates.erase(std::find_if(
-        resolveState->pImpl->ResolveStates.begin(),
-        resolveState->pImpl->ResolveStates.end(),
-        [r = resolveState.get()](auto& a) { return a.get() == r; }));
-  }
-}
-
-bool MulticastServiceResolver::HasImplementation() const {
-  return true;
-}
-
-void MulticastServiceResolver::Start() {
-  if (pImpl->serviceRef) {
-    return;
-  }
-
-  DNSServiceErrorType status =
-      DNSServiceBrowse(&pImpl->serviceRef, 0, 0, pImpl->serviceType.c_str(),
-                       "local", DnsCompletion, pImpl.get());
-  if (status == kDNSServiceErr_NoError) {
-    dnssd_sock_t socket = DNSServiceRefSockFD(pImpl->serviceRef);
-    pImpl->thread->AddServiceRef(pImpl->serviceRef, socket);
-  }
-}
-
-void MulticastServiceResolver::Stop() {
-  if (!pImpl->serviceRef) {
-    return;
-  }
-  wpi::SmallVector<WPI_EventHandle, 8> cleanupEvents;
-  for (auto&& i : pImpl->ResolveStates) {
-    cleanupEvents.push_back(
-        pImpl->thread->RemoveServiceRefOutsideThread(i->ResolveRef));
-  }
-  cleanupEvents.push_back(
-      pImpl->thread->RemoveServiceRefOutsideThread(pImpl->serviceRef));
-  wpi::SmallVector<WPI_Handle, 8> signaledBuf;
-  signaledBuf.resize(cleanupEvents.size());
-  while (!cleanupEvents.empty()) {
-    auto signaled = wpi::WaitForObjects(cleanupEvents, signaledBuf);
-    for (auto&& s : signaled) {
-      cleanupEvents.erase(
-          std::find(cleanupEvents.begin(), cleanupEvents.end(), s));
-    }
-  }
-
-  pImpl->ResolveStates.clear();
-  pImpl->serviceRef = nullptr;
-}
diff --git a/wpiutil/src/main/native/macOS/ResolverThread.cpp b/wpiutil/src/main/native/macOS/ResolverThread.cpp
deleted file mode 100644
index b91d6b6..0000000
--- a/wpiutil/src/main/native/macOS/ResolverThread.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "ResolverThread.h"
-
-#include "wpi/mutex.h"
-
-using namespace wpi;
-
-ResolverThread::ResolverThread(const private_init&) {}
-
-ResolverThread::~ResolverThread() noexcept {
-  running = false;
-  if (thread.joinable()) {
-    thread.join();
-  }
-}
-
-void ResolverThread::AddServiceRef(DNSServiceRef serviceRef,
-                                   dnssd_sock_t socket) {
-  std::scoped_lock lock{serviceRefMutex};
-  serviceRefs.emplace_back(
-      std::pair<DNSServiceRef, dnssd_sock_t>{serviceRef, socket});
-  if (serviceRefs.size() == 1) {
-    running = false;
-    if (thread.joinable()) {
-      thread.join();
-    }
-    running = true;
-    thread = std::thread([=] { ThreadMain(); });
-  }
-}
-
-void ResolverThread::RemoveServiceRefInThread(DNSServiceRef serviceRef) {
-  std::scoped_lock lock{serviceRefMutex};
-  serviceRefs.erase(
-      std::find_if(serviceRefs.begin(), serviceRefs.end(),
-                   [=](auto& a) { return a.first == serviceRef; }));
-  DNSServiceRefDeallocate(serviceRef);
-}
-
-WPI_EventHandle ResolverThread::RemoveServiceRefOutsideThread(
-    DNSServiceRef serviceRef) {
-  std::scoped_lock lock{serviceRefMutex};
-  WPI_EventHandle handle = CreateEvent(true);
-  serviceRefsToRemove.push_back({serviceRef, handle});
-  return handle;
-}
-
-bool ResolverThread::CleanupRefs() {
-  std::scoped_lock lock{serviceRefMutex};
-  for (auto&& r : serviceRefsToRemove) {
-    serviceRefs.erase(
-        std::find_if(serviceRefs.begin(), serviceRefs.end(),
-                     [=](auto& a) { return a.first == r.first; }));
-    DNSServiceRefDeallocate(r.first);
-    wpi::SetEvent(r.second);
-  }
-  serviceRefsToRemove.clear();
-  return serviceRefs.empty();
-}
-
-void ResolverThread::ThreadMain() {
-  std::vector<pollfd> readSockets;
-  std::vector<DNSServiceRef> serviceRefs;
-
-  while (running) {
-    readSockets.clear();
-    serviceRefs.clear();
-
-    for (auto&& i : this->serviceRefs) {
-      readSockets.emplace_back(pollfd{i.second, POLLIN, 0});
-      serviceRefs.emplace_back(i.first);
-    }
-
-    int res = poll(readSockets.begin().base(), readSockets.size(), 100);
-
-    if (res > 0) {
-      for (size_t i = 0; i < readSockets.size(); i++) {
-        if (readSockets[i].revents == POLLIN) {
-          DNSServiceProcessResult(serviceRefs[i]);
-        }
-      }
-    } else if (res == 0) {
-      if (!running) {
-        CleanupRefs();
-        break;
-      }
-    }
-
-    if (CleanupRefs()) {
-      break;
-    }
-  }
-}
-
-static wpi::mutex ThreadLoopLock;
-static std::weak_ptr<ResolverThread> ThreadLoop;
-
-std::shared_ptr<ResolverThread> ResolverThread::Get() {
-  std::scoped_lock lock{ThreadLoopLock};
-  auto locked = ThreadLoop.lock();
-  if (!locked) {
-    locked = std::make_unique<ResolverThread>(private_init{});
-    ThreadLoop = locked;
-  }
-  return locked;
-}
diff --git a/wpiutil/src/main/native/macOS/ResolverThread.h b/wpiutil/src/main/native/macOS/ResolverThread.h
deleted file mode 100644
index 0162de5..0000000
--- a/wpiutil/src/main/native/macOS/ResolverThread.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#include <netinet/in.h>
-#include <poll.h>
-
-#include <atomic>
-#include <memory>
-#include <thread>
-#include <utility>
-#include <vector>
-
-#include "dns_sd.h"
-#include "wpi/Synchronization.h"
-#include "wpi/mutex.h"
-
-namespace wpi {
-class ResolverThread {
- private:
-  struct private_init {};
-
- public:
-  explicit ResolverThread(const private_init&);
-  ~ResolverThread() noexcept;
-
-  void AddServiceRef(DNSServiceRef serviceRef, dnssd_sock_t socket);
-  void RemoveServiceRefInThread(DNSServiceRef serviceRef);
-  WPI_EventHandle RemoveServiceRefOutsideThread(DNSServiceRef serviceRef);
-
-  static std::shared_ptr<ResolverThread> Get();
-
- private:
-  void ThreadMain();
-  bool CleanupRefs();
-
-  wpi::mutex serviceRefMutex;
-  std::vector<std::pair<DNSServiceRef, WPI_EventHandle>> serviceRefsToRemove;
-  std::vector<std::pair<DNSServiceRef, dnssd_sock_t>> serviceRefs;
-  std::thread thread;
-  std::atomic_bool running;
-};
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/resources/bootstrap-4.1.min.js.gz b/wpiutil/src/main/native/resources/bootstrap-4.1.min.js.gz
deleted file mode 100644
index a7797e1..0000000
--- a/wpiutil/src/main/native/resources/bootstrap-4.1.min.js.gz
+++ /dev/null
Binary files differ
diff --git a/wpiutil/src/main/native/resources/coreui-2.1.min.css.gz b/wpiutil/src/main/native/resources/coreui-2.1.min.css.gz
deleted file mode 100644
index d4f43ad..0000000
--- a/wpiutil/src/main/native/resources/coreui-2.1.min.css.gz
+++ /dev/null
Binary files differ
diff --git a/wpiutil/src/main/native/resources/coreui-2.1.min.js.gz b/wpiutil/src/main/native/resources/coreui-2.1.min.js.gz
deleted file mode 100644
index cf4ccb1..0000000
--- a/wpiutil/src/main/native/resources/coreui-2.1.min.js.gz
+++ /dev/null
Binary files differ
diff --git a/wpiutil/src/main/native/resources/feather-4.8.min.js.gz b/wpiutil/src/main/native/resources/feather-4.8.min.js.gz
deleted file mode 100644
index d275865..0000000
--- a/wpiutil/src/main/native/resources/feather-4.8.min.js.gz
+++ /dev/null
Binary files differ
diff --git a/wpiutil/src/main/native/resources/jquery-3.3.slim.min.js.gz b/wpiutil/src/main/native/resources/jquery-3.3.slim.min.js.gz
deleted file mode 100644
index 712e06c..0000000
--- a/wpiutil/src/main/native/resources/jquery-3.3.slim.min.js.gz
+++ /dev/null
Binary files differ
diff --git a/wpiutil/src/main/native/resources/popper-1.14.min.js.gz b/wpiutil/src/main/native/resources/popper-1.14.min.js.gz
deleted file mode 100644
index c6ebec8..0000000
--- a/wpiutil/src/main/native/resources/popper-1.14.min.js.gz
+++ /dev/null
Binary files differ
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/args.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/args.h
similarity index 95%
rename from wpiutil/src/main/native/fmtlib/include/fmt/args.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/args.h
index 9a8e4ed..a3966d1 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/args.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/args.h
@@ -95,10 +95,10 @@
   };
 
   template <typename T>
-  using stored_type = conditional_t<detail::is_string<T>::value &&
-                                        !has_formatter<T, Context>::value &&
-                                        !detail::is_reference_wrapper<T>::value,
-                                    std::basic_string<char_type>, T>;
+  using stored_type = conditional_t<
+      std::is_convertible<T, std::basic_string<char_type>>::value &&
+          !detail::is_reference_wrapper<T>::value,
+      std::basic_string<char_type>, T>;
 
   // Storage of basic_format_arg must be contiguous.
   std::vector<basic_format_arg<Context>> data_;
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/chrono.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/chrono.h
similarity index 95%
rename from wpiutil/src/main/native/fmtlib/include/fmt/chrono.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/chrono.h
index 682efd8..b112f76 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/chrono.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/chrono.h
@@ -10,6 +10,8 @@
 
 #include <algorithm>
 #include <chrono>
+#include <cmath>    // std::isfinite
+#include <cstring>  // std::memcpy
 #include <ctime>
 #include <iterator>
 #include <locale>
@@ -201,7 +203,7 @@
     }
     const auto min1 =
         (std::numeric_limits<IntermediateRep>::min)() / Factor::num;
-    if (count < min1) {
+    if (!std::is_unsigned<IntermediateRep>::value && count < min1) {
       ec = 1;
       return {};
     }
@@ -321,14 +323,13 @@
 template <typename CodeUnit>
 void write_codecvt(codecvt_result<CodeUnit>& out, string_view in_buf,
                    const std::locale& loc) {
-  using codecvt = std::codecvt<CodeUnit, char, std::mbstate_t>;
 #if FMT_CLANG_VERSION
 #  pragma clang diagnostic push
 #  pragma clang diagnostic ignored "-Wdeprecated"
-  auto& f = std::use_facet<codecvt>(loc);
+  auto& f = std::use_facet<std::codecvt<CodeUnit, char, std::mbstate_t>>(loc);
 #  pragma clang diagnostic pop
 #else
-  auto& f = std::use_facet<codecvt>(loc);
+  auto& f = std::use_facet<std::codecvt<CodeUnit, char, std::mbstate_t>>(loc);
 #endif
   auto mb = std::mbstate_t();
   const char* from_next = nullptr;
@@ -344,7 +345,7 @@
   if (detail::is_utf8() && loc != get_classic_locale()) {
     // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
     // gcc-4.
-#if FMT_MSC_VER != 0 || \
+#if FMT_MSC_VERSION != 0 || \
     (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
     // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
     // and newer.
@@ -468,7 +469,7 @@
 
     bool fallback(int res) { return res == 0; }
 
-#if !FMT_MSC_VER
+#if !FMT_MSC_VERSION
     bool fallback(detail::null<>) {
       using namespace fmt::detail;
       std::tm* tm = std::localtime(&time_);
@@ -514,7 +515,7 @@
 
     bool fallback(int res) { return res == 0; }
 
-#if !FMT_MSC_VER
+#if !FMT_MSC_VERSION
     bool fallback(detail::null<>) {
       std::tm* tm = std::gmtime(&time_);
       if (tm) tm_ = *tm;
@@ -562,10 +563,10 @@
   constexpr const size_t len = 8;
   if (const_check(is_big_endian())) {
     char tmp[len];
-    memcpy(tmp, &digits, len);
+    std::memcpy(tmp, &digits, len);
     std::reverse_copy(tmp, tmp + len, buf);
   } else {
-    memcpy(buf, &digits, len);
+    std::memcpy(buf, &digits, len);
   }
 }
 
@@ -1214,7 +1215,7 @@
     char buf[10];
     size_t offset = 0;
     if (year >= 0 && year < 10000) {
-      copy2(buf, digits2(to_unsigned(year / 100)));
+      copy2(buf, digits2(static_cast<size_t>(year / 100)));
     } else {
       offset = 4;
       write_year_extended(year);
@@ -1388,15 +1389,6 @@
 };
 
 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
-inline bool isnan(T) {
-  return false;
-}
-template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
-inline bool isnan(T value) {
-  return std::isnan(value);
-}
-
-template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
 inline bool isfinite(T) {
   return true;
 }
@@ -1404,7 +1396,8 @@
 // Converts value to Int and checks that it's in the range [0, upper).
 template <typename T, typename Int, FMT_ENABLE_IF(std::is_integral<T>::value)>
 inline Int to_nonnegative_int(T value, Int upper) {
-  FMT_ASSERT(value >= 0 && to_unsigned(value) <= to_unsigned(upper),
+  FMT_ASSERT(std::is_unsigned<Int>::value ||
+             (value >= 0 && to_unsigned(value) <= to_unsigned(upper)),
              "invalid value");
   (void)upper;
   return static_cast<Int>(value);
@@ -1470,14 +1463,22 @@
 #endif
 }
 
-// Returns the number of fractional digits in the range [0, 18] according to the
+// Counts the number of fractional digits in the range [0, 18] according to the
 // C++20 spec. If more than 18 fractional digits are required then returns 6 for
 // microseconds precision.
-constexpr int count_fractional_digits(long long num, long long den, int n = 0) {
-  return num % den == 0
-             ? n
-             : (n > 18 ? 6 : count_fractional_digits(num * 10, den, n + 1));
-}
+template <long long Num, long long Den, int N = 0,
+          bool Enabled = (N < 19) && (Num <= max_value<long long>() / 10)>
+struct count_fractional_digits {
+  static constexpr int value =
+      Num % Den == 0 ? N : count_fractional_digits<Num * 10, Den, N + 1>::value;
+};
+
+// Base case that doesn't instantiate any more templates
+// in order to avoid overflow.
+template <long long Num, long long Den, int N>
+struct count_fractional_digits<Num, Den, N, false> {
+  static constexpr int value = (Num % Den == 0) ? N : 6;
+};
 
 constexpr long long pow10(std::uint32_t n) {
   return n == 0 ? 1 : 10 * pow10(n - 1);
@@ -1663,9 +1664,11 @@
     out = format_decimal<char_type>(out, n, num_digits).end;
   }
 
-  template <class Duration> void write_fractional_seconds(Duration d) {
+  template <typename Duration> void write_fractional_seconds(Duration d) {
+    FMT_ASSERT(!std::is_floating_point<typename Duration::rep>::value, "");
     constexpr auto num_fractional_digits =
-        count_fractional_digits(Duration::period::num, Duration::period::den);
+        count_fractional_digits<Duration::period::num,
+                                Duration::period::den>::value;
 
     using subsecond_precision = std::chrono::duration<
         typename std::common_type<typename Duration::rep,
@@ -1674,12 +1677,9 @@
     if (std::ratio_less<typename subsecond_precision::period,
                         std::chrono::seconds::period>::value) {
       *out++ = '.';
-      // Don't convert long double to integer seconds to avoid overflow.
-      using sec = conditional_t<
-          std::is_same<typename Duration::rep, long double>::value,
-          std::chrono::duration<long double>, std::chrono::seconds>;
-      auto fractional = detail::abs(d) - std::chrono::duration_cast<sec>(d);
-      const auto subseconds =
+      auto fractional =
+          detail::abs(d) - std::chrono::duration_cast<std::chrono::seconds>(d);
+      auto subseconds =
           std::chrono::treat_as_floating_point<
               typename subsecond_precision::rep>::value
               ? fractional.count()
@@ -1770,8 +1770,22 @@
     if (handle_nan_inf()) return;
 
     if (ns == numeric_system::standard) {
-      write(second(), 2);
-      write_fractional_seconds(std::chrono::duration<rep, Period>{val});
+      if (std::is_floating_point<rep>::value) {
+        constexpr auto num_fractional_digits =
+            count_fractional_digits<Period::num, Period::den>::value;
+        auto buf = memory_buffer();
+        format_to(std::back_inserter(buf), runtime("{:.{}f}"),
+                  std::fmod(val * static_cast<rep>(Period::num) /
+                                static_cast<rep>(Period::den),
+                            static_cast<rep>(60)),
+                  num_fractional_digits);
+        if (negative) *out++ = '-';
+        if (buf.size() < 2 || buf[1] == '.') *out++ = '0';
+        out = std::copy(buf.begin(), buf.end(), out);
+      } else {
+        write(second(), 2);
+        write_fractional_seconds(std::chrono::duration<rep, Period>(val));
+      }
       return;
     }
     auto time = tm();
@@ -1988,13 +2002,9 @@
 struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
                  Char> : formatter<std::tm, Char> {
   FMT_CONSTEXPR formatter() {
-    this->do_parse(default_specs,
-                   default_specs + sizeof(default_specs) / sizeof(Char));
-  }
-
-  template <typename ParseContext>
-  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
-    return this->do_parse(ctx.begin(), ctx.end(), true);
+    basic_string_view<Char> default_specs =
+        detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{};
+    this->do_parse(default_specs.begin(), default_specs.end());
   }
 
   template <typename FormatContext>
@@ -2002,15 +2012,8 @@
               FormatContext& ctx) const -> decltype(ctx.out()) {
     return formatter<std::tm, Char>::format(localtime(val), ctx);
   }
-
-  static constexpr const Char default_specs[] = {'%', 'F', ' ', '%', 'T'};
 };
 
-template <typename Char, typename Duration>
-constexpr const Char
-    formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
-              Char>::default_specs[];
-
 template <typename Char> struct formatter<std::tm, Char> {
  private:
   enum class spec {
@@ -2022,13 +2025,18 @@
   basic_string_view<Char> specs;
 
  protected:
-  template <typename It>
-  FMT_CONSTEXPR auto do_parse(It begin, It end, bool with_default = false)
-      -> It {
+  template <typename It> FMT_CONSTEXPR auto do_parse(It begin, It end) -> It {
     if (begin != end && *begin == ':') ++begin;
     end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());
-    if (!with_default || end != begin)
-      specs = {begin, detail::to_unsigned(end - begin)};
+    // Replace default spec only if the new spec is not empty.
+    if (end != begin) specs = {begin, detail::to_unsigned(end - begin)};
+    return end;
+  }
+
+ public:
+  FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
+      -> decltype(ctx.begin()) {
+    auto end = this->do_parse(ctx.begin(), ctx.end());
     // basic_string_view<>::compare isn't constexpr before C++17.
     if (specs.size() == 2 && specs[0] == Char('%')) {
       if (specs[1] == Char('F'))
@@ -2039,12 +2047,6 @@
     return end;
   }
 
- public:
-  template <typename ParseContext>
-  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
-    return this->do_parse(ctx.begin(), ctx.end());
-  }
-
   template <typename FormatContext>
   auto format(const std::tm& tm, FormatContext& ctx) const
       -> decltype(ctx.out()) {
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/color.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/color.h
similarity index 80%
rename from wpiutil/src/main/native/fmtlib/include/fmt/color.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/color.h
index dfbe482..4c16327 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/color.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/color.h
@@ -10,13 +10,6 @@
 
 #include "format.h"
 
-// __declspec(deprecated) is broken in some MSVC versions.
-#if FMT_MSC_VER
-#  define FMT_DEPRECATED_NONMSVC
-#else
-#  define FMT_DEPRECATED_NONMSVC FMT_DEPRECATED
-#endif
-
 FMT_BEGIN_NAMESPACE
 FMT_MODULE_EXPORT_BEGIN
 
@@ -214,17 +207,16 @@
 
 // color is a struct of either a rgb color or a terminal color.
 struct color_type {
-  FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {}
-  FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true),
-                                                           value{} {
+  FMT_CONSTEXPR color_type() noexcept : is_rgb(), value{} {}
+  FMT_CONSTEXPR color_type(color rgb_color) noexcept : is_rgb(true), value{} {
     value.rgb_color = static_cast<uint32_t>(rgb_color);
   }
-  FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} {
+  FMT_CONSTEXPR color_type(rgb rgb_color) noexcept : is_rgb(true), value{} {
     value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) |
                       (static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b;
   }
-  FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(),
-                                                                     value{} {
+  FMT_CONSTEXPR color_type(terminal_color term_color) noexcept
+      : is_rgb(), value{} {
     value.term_color = static_cast<uint8_t>(term_color);
   }
   bool is_rgb;
@@ -239,10 +231,8 @@
 /** A text style consisting of foreground and background colors and emphasis. */
 class text_style {
  public:
-  FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT
-      : set_foreground_color(),
-        set_background_color(),
-        ems(em) {}
+  FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept
+      : set_foreground_color(), set_background_color(), ems(em) {}
 
   FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) {
     if (!set_foreground_color) {
@@ -273,44 +263,32 @@
     return lhs |= rhs;
   }
 
-  FMT_DEPRECATED_NONMSVC FMT_CONSTEXPR text_style& operator&=(
-      const text_style& rhs) {
-    return and_assign(rhs);
-  }
-
-  FMT_DEPRECATED_NONMSVC friend FMT_CONSTEXPR text_style
-  operator&(text_style lhs, const text_style& rhs) {
-    return lhs.and_assign(rhs);
-  }
-
-  FMT_CONSTEXPR bool has_foreground() const FMT_NOEXCEPT {
+  FMT_CONSTEXPR bool has_foreground() const noexcept {
     return set_foreground_color;
   }
-  FMT_CONSTEXPR bool has_background() const FMT_NOEXCEPT {
+  FMT_CONSTEXPR bool has_background() const noexcept {
     return set_background_color;
   }
-  FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT {
+  FMT_CONSTEXPR bool has_emphasis() const noexcept {
     return static_cast<uint8_t>(ems) != 0;
   }
-  FMT_CONSTEXPR detail::color_type get_foreground() const FMT_NOEXCEPT {
+  FMT_CONSTEXPR detail::color_type get_foreground() const noexcept {
     FMT_ASSERT(has_foreground(), "no foreground specified for this style");
     return foreground_color;
   }
-  FMT_CONSTEXPR detail::color_type get_background() const FMT_NOEXCEPT {
+  FMT_CONSTEXPR detail::color_type get_background() const noexcept {
     FMT_ASSERT(has_background(), "no background specified for this style");
     return background_color;
   }
-  FMT_CONSTEXPR emphasis get_emphasis() const FMT_NOEXCEPT {
+  FMT_CONSTEXPR emphasis get_emphasis() const noexcept {
     FMT_ASSERT(has_emphasis(), "no emphasis specified for this style");
     return ems;
   }
 
  private:
   FMT_CONSTEXPR text_style(bool is_foreground,
-                           detail::color_type text_color) FMT_NOEXCEPT
-      : set_foreground_color(),
-        set_background_color(),
-        ems() {
+                           detail::color_type text_color) noexcept
+      : set_foreground_color(), set_background_color(), ems() {
     if (is_foreground) {
       foreground_color = text_color;
       set_foreground_color = true;
@@ -320,36 +298,9 @@
     }
   }
 
-  // DEPRECATED!
-  FMT_CONSTEXPR text_style& and_assign(const text_style& rhs) {
-    if (!set_foreground_color) {
-      set_foreground_color = rhs.set_foreground_color;
-      foreground_color = rhs.foreground_color;
-    } else if (rhs.set_foreground_color) {
-      if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
-        FMT_THROW(format_error("can't AND a terminal color"));
-      foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color;
-    }
+  friend FMT_CONSTEXPR text_style fg(detail::color_type foreground) noexcept;
 
-    if (!set_background_color) {
-      set_background_color = rhs.set_background_color;
-      background_color = rhs.background_color;
-    } else if (rhs.set_background_color) {
-      if (!background_color.is_rgb || !rhs.background_color.is_rgb)
-        FMT_THROW(format_error("can't AND a terminal color"));
-      background_color.value.rgb_color &= rhs.background_color.value.rgb_color;
-    }
-
-    ems = static_cast<emphasis>(static_cast<uint8_t>(ems) &
-                                static_cast<uint8_t>(rhs.ems));
-    return *this;
-  }
-
-  friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground)
-      FMT_NOEXCEPT;
-
-  friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background)
-      FMT_NOEXCEPT;
+  friend FMT_CONSTEXPR text_style bg(detail::color_type background) noexcept;
 
   detail::color_type foreground_color;
   detail::color_type background_color;
@@ -359,17 +310,16 @@
 };
 
 /** Creates a text style from the foreground (text) color. */
-FMT_CONSTEXPR inline text_style fg(detail::color_type foreground) FMT_NOEXCEPT {
+FMT_CONSTEXPR inline text_style fg(detail::color_type foreground) noexcept {
   return text_style(true, foreground);
 }
 
 /** Creates a text style from the background color. */
-FMT_CONSTEXPR inline text_style bg(detail::color_type background) FMT_NOEXCEPT {
+FMT_CONSTEXPR inline text_style bg(detail::color_type background) noexcept {
   return text_style(false, background);
 }
 
-FMT_CONSTEXPR inline text_style operator|(emphasis lhs,
-                                          emphasis rhs) FMT_NOEXCEPT {
+FMT_CONSTEXPR inline text_style operator|(emphasis lhs, emphasis rhs) noexcept {
   return text_style(lhs) | rhs;
 }
 
@@ -377,7 +327,7 @@
 
 template <typename Char> struct ansi_color_escape {
   FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
-                                  const char* esc) FMT_NOEXCEPT {
+                                  const char* esc) noexcept {
     // If we have a terminal color, we need to output another escape code
     // sequence.
     if (!text_color.is_rgb) {
@@ -412,7 +362,7 @@
     to_esc(color.b, buffer + 15, 'm');
     buffer[19] = static_cast<Char>(0);
   }
-  FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_NOEXCEPT {
+  FMT_CONSTEXPR ansi_color_escape(emphasis em) noexcept {
     uint8_t em_codes[num_emphases] = {};
     if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1;
     if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2;
@@ -433,10 +383,10 @@
     }
     buffer[index++] = static_cast<Char>(0);
   }
-  FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; }
+  FMT_CONSTEXPR operator const Char*() const noexcept { return buffer; }
 
-  FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; }
-  FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const FMT_NOEXCEPT {
+  FMT_CONSTEXPR const Char* begin() const noexcept { return buffer; }
+  FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const noexcept {
     return buffer + std::char_traits<Char>::length(buffer);
   }
 
@@ -445,59 +395,64 @@
   Char buffer[7u + 3u * num_emphases + 1u];
 
   static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
-                                   char delimiter) FMT_NOEXCEPT {
+                                   char delimiter) noexcept {
     out[0] = static_cast<Char>('0' + c / 100);
     out[1] = static_cast<Char>('0' + c / 10 % 10);
     out[2] = static_cast<Char>('0' + c % 10);
     out[3] = static_cast<Char>(delimiter);
   }
-  static FMT_CONSTEXPR bool has_emphasis(emphasis em,
-                                         emphasis mask) FMT_NOEXCEPT {
+  static FMT_CONSTEXPR bool has_emphasis(emphasis em, emphasis mask) noexcept {
     return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask);
   }
 };
 
 template <typename Char>
 FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
-    detail::color_type foreground) FMT_NOEXCEPT {
+    detail::color_type foreground) noexcept {
   return ansi_color_escape<Char>(foreground, "\x1b[38;2;");
 }
 
 template <typename Char>
 FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
-    detail::color_type background) FMT_NOEXCEPT {
+    detail::color_type background) noexcept {
   return ansi_color_escape<Char>(background, "\x1b[48;2;");
 }
 
 template <typename Char>
-FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT {
+FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) noexcept {
   return ansi_color_escape<Char>(em);
 }
 
-template <typename Char>
-inline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT {
-  std::fputs(chars, stream);
+template <typename Char> inline void fputs(const Char* chars, FILE* stream) {
+  int result = std::fputs(chars, stream);
+  if (result < 0)
+    FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
 }
 
-template <>
-inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT {
-  std::fputws(chars, stream);
+template <> inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) {
+  int result = std::fputws(chars, stream);
+  if (result < 0)
+    FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
 }
 
-template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT {
+template <typename Char> inline void reset_color(FILE* stream) {
   fputs("\x1b[0m", stream);
 }
 
-template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
+template <> inline void reset_color<wchar_t>(FILE* stream) {
   fputs(L"\x1b[0m", stream);
 }
 
-template <typename Char>
-inline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT {
+template <typename Char> inline void reset_color(buffer<Char>& buffer) {
   auto reset_color = string_view("\x1b[0m");
   buffer.append(reset_color.begin(), reset_color.end());
 }
 
+template <typename T> struct styled_arg {
+  const T& value;
+  text_style style;
+};
+
 template <typename Char>
 void vformat_to(buffer<Char>& buf, const text_style& ts,
                 basic_string_view<Char> format_str,
@@ -528,9 +483,13 @@
 void vprint(std::FILE* f, const text_style& ts, const S& format,
             basic_format_args<buffer_context<type_identity_t<Char>>> args) {
   basic_memory_buffer<Char> buf;
-  detail::vformat_to(buf, ts, to_string_view(format), args);
-  buf.push_back(Char(0));
-  detail::fputs(buf.data(), f);
+  detail::vformat_to(buf, ts, detail::to_string_view(format), args);
+  if (detail::is_utf8()) {
+    detail::print(f, basic_string_view<Char>(buf.begin(), buf.size()));
+  } else {
+    buf.push_back(Char(0));
+    detail::fputs(buf.data(), f);
+  }
 }
 
 /**
@@ -549,7 +508,7 @@
 void print(std::FILE* f, const text_style& ts, const S& format_str,
            const Args&... args) {
   vprint(f, ts, format_str,
-         fmt::make_args_checked<Args...>(format_str, args...));
+         fmt::make_format_args<buffer_context<char_t<S>>>(args...));
 }
 
 /**
@@ -574,7 +533,7 @@
     const text_style& ts, const S& format_str,
     basic_format_args<buffer_context<type_identity_t<Char>>> args) {
   basic_memory_buffer<Char> buf;
-  detail::vformat_to(buf, ts, to_string_view(format_str), args);
+  detail::vformat_to(buf, ts, detail::to_string_view(format_str), args);
   return fmt::to_string(buf);
 }
 
@@ -593,8 +552,8 @@
 template <typename S, typename... Args, typename Char = char_t<S>>
 inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
                                       const Args&... args) {
-  return fmt::vformat(ts, to_string_view(format_str),
-                      fmt::make_args_checked<Args...>(format_str, args...));
+  return fmt::vformat(ts, detail::to_string_view(format_str),
+                      fmt::make_format_args<buffer_context<Char>>(args...));
 }
 
 /**
@@ -628,8 +587,62 @@
 inline auto format_to(OutputIt out, const text_style& ts, const S& format_str,
                       Args&&... args) ->
     typename std::enable_if<enable, OutputIt>::type {
-  return vformat_to(out, ts, to_string_view(format_str),
-                    fmt::make_args_checked<Args...>(format_str, args...));
+  return vformat_to(out, ts, detail::to_string_view(format_str),
+                    fmt::make_format_args<buffer_context<char_t<S>>>(args...));
+}
+
+template <typename T, typename Char>
+struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
+  template <typename FormatContext>
+  auto format(const detail::styled_arg<T>& arg, FormatContext& ctx) const
+      -> decltype(ctx.out()) {
+    const auto& ts = arg.style;
+    const auto& value = arg.value;
+    auto out = ctx.out();
+
+    bool has_style = false;
+    if (ts.has_emphasis()) {
+      has_style = true;
+      auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
+      out = std::copy(emphasis.begin(), emphasis.end(), out);
+    }
+    if (ts.has_foreground()) {
+      has_style = true;
+      auto foreground =
+          detail::make_foreground_color<Char>(ts.get_foreground());
+      out = std::copy(foreground.begin(), foreground.end(), out);
+    }
+    if (ts.has_background()) {
+      has_style = true;
+      auto background =
+          detail::make_background_color<Char>(ts.get_background());
+      out = std::copy(background.begin(), background.end(), out);
+    }
+    out = formatter<T, Char>::format(value, ctx);
+    if (has_style) {
+      auto reset_color = string_view("\x1b[0m");
+      out = std::copy(reset_color.begin(), reset_color.end(), out);
+    }
+    return out;
+  }
+};
+
+/**
+  \rst
+  Returns an argument that will be formatted using ANSI escape sequences,
+  to be used in a formatting function.
+
+  **Example**::
+
+    fmt::print("Elapsed time: {0:.2f} seconds",
+               fmt::styled(1.23, fmt::fg(fmt::color::green) |
+                                 fmt::bg(fmt::color::blue)));
+  \endrst
+ */
+template <typename T>
+FMT_CONSTEXPR auto styled(const T& value, text_style ts)
+    -> detail::styled_arg<remove_cvref_t<T>> {
+  return detail::styled_arg<remove_cvref_t<T>>{value, ts};
 }
 
 FMT_MODULE_EXPORT_END
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/compile.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/compile.h
similarity index 88%
rename from wpiutil/src/main/native/fmtlib/include/fmt/compile.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/compile.h
index 1dba3dd..933668c 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/compile.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/compile.h
@@ -13,48 +13,9 @@
 FMT_BEGIN_NAMESPACE
 namespace detail {
 
-// An output iterator that counts the number of objects written to it and
-// discards them.
-class counting_iterator {
- private:
-  size_t count_;
-
- public:
-  using iterator_category = std::output_iterator_tag;
-  using difference_type = std::ptrdiff_t;
-  using pointer = void;
-  using reference = void;
-  using _Unchecked_type = counting_iterator;  // Mark iterator as checked.
-
-  struct value_type {
-    template <typename T> void operator=(const T&) {}
-  };
-
-  counting_iterator() : count_(0) {}
-
-  size_t count() const { return count_; }
-
-  counting_iterator& operator++() {
-    ++count_;
-    return *this;
-  }
-  counting_iterator operator++(int) {
-    auto it = *this;
-    ++*this;
-    return it;
-  }
-
-  friend counting_iterator operator+(counting_iterator it, difference_type n) {
-    it.count_ += static_cast<size_t>(n);
-    return it;
-  }
-
-  value_type operator*() const { return {}; }
-};
-
 template <typename Char, typename InputIt>
-inline counting_iterator copy_str(InputIt begin, InputIt end,
-                                  counting_iterator it) {
+FMT_CONSTEXPR inline counting_iterator copy_str(InputIt begin, InputIt end,
+                                                counting_iterator it) {
   return it + (end - begin);
 }
 
@@ -75,8 +36,7 @@
   using difference_type = std::ptrdiff_t;
   using pointer = void;
   using reference = void;
-  using _Unchecked_type =
-      truncating_iterator_base;  // Mark iterator as checked.
+  FMT_UNCHECKED_ITERATOR(truncating_iterator_base);
 
   OutputIt base() const { return out_; }
   size_t count() const { return count_; }
@@ -163,12 +123,12 @@
 #  define FMT_COMPILE(s) FMT_STRING(s)
 #endif
 
-#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+#if FMT_USE_NONTYPE_TEMPLATE_ARGS
 template <typename Char, size_t N,
           fmt::detail_exported::fixed_string<Char, N> Str>
 struct udl_compiled_string : compiled_string {
   using char_type = Char;
-  constexpr operator basic_string_view<char_type>() const {
+  explicit constexpr operator basic_string_view<char_type>() const {
     return {Str.data, N - 1};
   }
 };
@@ -377,10 +337,11 @@
 constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str,
                                                   size_t pos, int next_arg_id) {
   str.remove_prefix(pos);
-  auto ctx = basic_format_parse_context<Char>(str, {}, next_arg_id);
+  auto ctx = compile_parse_context<Char>(str, max_value<int>(), nullptr, {},
+                                         next_arg_id);
   auto f = formatter<T, Char>();
   auto end = f.parse(ctx);
-  return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1,
+  return {f, pos + fmt::detail::to_unsigned(end - str.data()),
           next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()};
 }
 
@@ -436,13 +397,20 @@
     return parse_tail<Args, END_POS + 1, NEXT_ID>(
         field<char_type, typename field_type<T>::type, ARG_INDEX>(),
         format_str);
-  } else if constexpr (c == ':') {
+  } else if constexpr (c != ':') {
+    FMT_THROW(format_error("expected ':'"));
+  } else {
     constexpr auto result = parse_specs<typename field_type<T>::type>(
         str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID);
-    return parse_tail<Args, result.end, result.next_arg_id>(
-        spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
-            result.fmt},
-        format_str);
+    if constexpr (result.end >= str.size() || str[result.end] != '}') {
+      FMT_THROW(format_error("expected '}'"));
+      return 0;
+    } else {
+      return parse_tail<Args, result.end + 1, result.next_arg_id>(
+          spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
+              result.fmt},
+          format_str);
+    }
   }
 }
 
@@ -573,10 +541,11 @@
   constexpr auto compiled = detail::compile<Args...>(S());
   if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
                              detail::unknown_format>()) {
-    return format(static_cast<basic_string_view<typename S::char_type>>(S()),
-                  std::forward<Args>(args)...);
+    return fmt::format(
+        static_cast<basic_string_view<typename S::char_type>>(S()),
+        std::forward<Args>(args)...);
   } else {
-    return format(compiled, std::forward<Args>(args)...);
+    return fmt::format(compiled, std::forward<Args>(args)...);
   }
 }
 
@@ -586,11 +555,11 @@
   constexpr auto compiled = detail::compile<Args...>(S());
   if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
                              detail::unknown_format>()) {
-    return format_to(out,
-                     static_cast<basic_string_view<typename S::char_type>>(S()),
-                     std::forward<Args>(args)...);
+    return fmt::format_to(
+        out, static_cast<basic_string_view<typename S::char_type>>(S()),
+        std::forward<Args>(args)...);
   } else {
-    return format_to(out, compiled, std::forward<Args>(args)...);
+    return fmt::format_to(out, compiled, std::forward<Args>(args)...);
   }
 }
 #endif
@@ -599,22 +568,24 @@
           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
                                          const S& format_str, Args&&... args) {
-  auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), format_str,
-                      std::forward<Args>(args)...);
+  auto it = fmt::format_to(detail::truncating_iterator<OutputIt>(out, n),
+                           format_str, std::forward<Args>(args)...);
   return {it.base(), it.count()};
 }
 
 template <typename S, typename... Args,
           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
-size_t formatted_size(const S& format_str, const Args&... args) {
-  return format_to(detail::counting_iterator(), format_str, args...).count();
+FMT_CONSTEXPR20 size_t formatted_size(const S& format_str,
+                                      const Args&... args) {
+  return fmt::format_to(detail::counting_iterator(), format_str, args...)
+      .count();
 }
 
 template <typename S, typename... Args,
           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 void print(std::FILE* f, const S& format_str, const Args&... args) {
   memory_buffer buffer;
-  format_to(std::back_inserter(buffer), format_str, args...);
+  fmt::format_to(std::back_inserter(buffer), format_str, args...);
   detail::print(f, {buffer.data(), buffer.size()});
 }
 
@@ -624,14 +595,12 @@
   print(stdout, format_str, args...);
 }
 
-#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+#if FMT_USE_NONTYPE_TEMPLATE_ARGS
 inline namespace literals {
-template <detail_exported::fixed_string Str>
-constexpr detail::udl_compiled_string<
-    remove_cvref_t<decltype(Str.data[0])>,
-    sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str>
-operator""_cf() {
-  return {};
+template <detail_exported::fixed_string Str> constexpr auto operator""_cf() {
+  using char_t = remove_cvref_t<decltype(Str.data[0])>;
+  return detail::udl_compiled_string<char_t, sizeof(Str.data) / sizeof(char_t),
+                                     Str>();
 }
 }  // namespace literals
 #endif
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/core.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/core.h
similarity index 85%
rename from wpiutil/src/main/native/fmtlib/include/fmt/core.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/core.h
index 92a7aa1..5c210bc 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/core.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/core.h
@@ -10,14 +10,14 @@
 
 #include <cstddef>  // std::byte
 #include <cstdio>   // std::FILE
-#include <cstring>
+#include <cstring>  // std::strlen
 #include <iterator>
 #include <limits>
 #include <string>
 #include <type_traits>
 
 // The fmt library version in the form major * 10000 + minor * 100 + patch.
-#define FMT_VERSION 80101
+#define FMT_VERSION 90100
 
 #if defined(__clang__) && !defined(__ibmxl__)
 #  define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
@@ -49,29 +49,29 @@
 #  define FMT_ICC_VERSION 0
 #endif
 
-#ifdef __NVCC__
-#  define FMT_NVCC __NVCC__
-#else
-#  define FMT_NVCC 0
-#endif
-
 #ifdef _MSC_VER
-#  define FMT_MSC_VER _MSC_VER
+#  define FMT_MSC_VERSION _MSC_VER
 #  define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__))
 #else
-#  define FMT_MSC_VER 0
+#  define FMT_MSC_VERSION 0
 #  define FMT_MSC_WARNING(...)
 #endif
 
+#ifdef _MSVC_LANG
+#  define FMT_CPLUSPLUS _MSVC_LANG
+#else
+#  define FMT_CPLUSPLUS __cplusplus
+#endif
+
 #ifdef __has_feature
 #  define FMT_HAS_FEATURE(x) __has_feature(x)
 #else
 #  define FMT_HAS_FEATURE(x) 0
 #endif
 
-#if defined(__has_include) &&                             \
-    (!defined(__INTELLISENSE__) || FMT_MSC_VER > 1900) && \
-    (!FMT_ICC_VERSION || FMT_ICC_VERSION >= 1600)
+#if (defined(__has_include) || FMT_ICC_VERSION >= 1600 || \
+     FMT_MSC_VERSION > 1900) &&                           \
+    !defined(__INTELLISENSE__)
 #  define FMT_HAS_INCLUDE(x) __has_include(x)
 #else
 #  define FMT_HAS_INCLUDE(x) 0
@@ -83,12 +83,6 @@
 #  define FMT_HAS_CPP_ATTRIBUTE(x) 0
 #endif
 
-#ifdef _MSVC_LANG
-#  define FMT_CPLUSPLUS _MSVC_LANG
-#else
-#  define FMT_CPLUSPLUS __cplusplus
-#endif
-
 #define FMT_HAS_CPP14_ATTRIBUTE(attribute) \
   (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute))
 
@@ -98,37 +92,38 @@
 // Check if relaxed C++14 constexpr is supported.
 // GCC doesn't allow throw in constexpr until version 6 (bug 67371).
 #ifndef FMT_USE_CONSTEXPR
-#  define FMT_USE_CONSTEXPR                                           \
-    (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VER >= 1912 || \
-     (FMT_GCC_VERSION >= 600 && __cplusplus >= 201402L)) &&           \
-        !FMT_NVCC && !FMT_ICC_VERSION
+#  if (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912 || \
+       (FMT_GCC_VERSION >= 600 && FMT_CPLUSPLUS >= 201402L)) &&             \
+      !FMT_ICC_VERSION && !defined(__NVCC__)
+#    define FMT_USE_CONSTEXPR 1
+#  else
+#    define FMT_USE_CONSTEXPR 0
+#  endif
 #endif
 #if FMT_USE_CONSTEXPR
 #  define FMT_CONSTEXPR constexpr
-#  define FMT_CONSTEXPR_DECL constexpr
 #else
 #  define FMT_CONSTEXPR
-#  define FMT_CONSTEXPR_DECL
 #endif
 
-#if ((__cplusplus >= 202002L) &&                              \
+#if ((FMT_CPLUSPLUS >= 202002L) &&                            \
      (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE > 9)) || \
-    (__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002)
+    (FMT_CPLUSPLUS >= 201709L && FMT_GCC_VERSION >= 1002)
 #  define FMT_CONSTEXPR20 constexpr
 #else
 #  define FMT_CONSTEXPR20
 #endif
 
-// Check if constexpr std::char_traits<>::compare,length is supported.
+// Check if constexpr std::char_traits<>::{compare,length} are supported.
 #if defined(__GLIBCXX__)
-#  if __cplusplus >= 201703L && defined(_GLIBCXX_RELEASE) && \
+#  if FMT_CPLUSPLUS >= 201703L && defined(_GLIBCXX_RELEASE) && \
       _GLIBCXX_RELEASE >= 7  // GCC 7+ libstdc++ has _GLIBCXX_RELEASE.
 #    define FMT_CONSTEXPR_CHAR_TRAITS constexpr
 #  endif
-#elif defined(_LIBCPP_VERSION) && __cplusplus >= 201703L && \
+#elif defined(_LIBCPP_VERSION) && FMT_CPLUSPLUS >= 201703L && \
     _LIBCPP_VERSION >= 4000
 #  define FMT_CONSTEXPR_CHAR_TRAITS constexpr
-#elif FMT_MSC_VER >= 1914 && _MSVC_LANG >= 201703L
+#elif FMT_MSC_VERSION >= 1914 && FMT_CPLUSPLUS >= 201703L
 #  define FMT_CONSTEXPR_CHAR_TRAITS constexpr
 #endif
 #ifndef FMT_CONSTEXPR_CHAR_TRAITS
@@ -138,57 +133,43 @@
 // Check if exceptions are disabled.
 #ifndef FMT_EXCEPTIONS
 #  if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \
-      FMT_MSC_VER && !_HAS_EXCEPTIONS
+      (FMT_MSC_VERSION && !_HAS_EXCEPTIONS)
 #    define FMT_EXCEPTIONS 0
 #  else
 #    define FMT_EXCEPTIONS 1
 #  endif
 #endif
 
-// Define FMT_USE_NOEXCEPT to make fmt use noexcept (C++11 feature).
-#ifndef FMT_USE_NOEXCEPT
-#  define FMT_USE_NOEXCEPT 0
-#endif
-
-#if FMT_USE_NOEXCEPT || FMT_HAS_FEATURE(cxx_noexcept) || \
-    FMT_GCC_VERSION >= 408 || FMT_MSC_VER >= 1900
-#  define FMT_DETECTED_NOEXCEPT noexcept
-#  define FMT_HAS_CXX11_NOEXCEPT 1
-#else
-#  define FMT_DETECTED_NOEXCEPT throw()
-#  define FMT_HAS_CXX11_NOEXCEPT 0
-#endif
-
-#ifndef FMT_NOEXCEPT
-#  if FMT_EXCEPTIONS || FMT_HAS_CXX11_NOEXCEPT
-#    define FMT_NOEXCEPT FMT_DETECTED_NOEXCEPT
+#ifndef FMT_DEPRECATED
+#  if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VERSION >= 1900
+#    define FMT_DEPRECATED [[deprecated]]
 #  else
-#    define FMT_NOEXCEPT
+#    if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
+#      define FMT_DEPRECATED __attribute__((deprecated))
+#    elif FMT_MSC_VERSION
+#      define FMT_DEPRECATED __declspec(deprecated)
+#    else
+#      define FMT_DEPRECATED /* deprecated */
+#    endif
 #  endif
 #endif
 
 // [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code
 // warnings.
-#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VER && \
-    !FMT_NVCC
+#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && \
+    !defined(__NVCC__)
 #  define FMT_NORETURN [[noreturn]]
 #else
 #  define FMT_NORETURN
 #endif
 
-#if __cplusplus == 201103L || __cplusplus == 201402L
-#  if defined(__INTEL_COMPILER) || defined(__PGI)
-#    define FMT_FALLTHROUGH
-#  elif defined(__clang__)
-#    define FMT_FALLTHROUGH [[clang::fallthrough]]
-#  elif FMT_GCC_VERSION >= 700 && \
-      (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
-#    define FMT_FALLTHROUGH [[gnu::fallthrough]]
-#  else
-#    define FMT_FALLTHROUGH
-#  endif
-#elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
+#if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
 #  define FMT_FALLTHROUGH [[fallthrough]]
+#elif defined(__clang__)
+#  define FMT_FALLTHROUGH [[clang::fallthrough]]
+#elif FMT_GCC_VERSION >= 700 && \
+    (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
+#  define FMT_FALLTHROUGH [[gnu::fallthrough]]
 #else
 #  define FMT_FALLTHROUGH
 #endif
@@ -219,24 +200,20 @@
 #  endif
 #endif
 
-#ifndef FMT_DEPRECATED
-#  if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900
-#    define FMT_DEPRECATED [[deprecated]]
-#  else
-#    if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
-#      define FMT_DEPRECATED __attribute__((deprecated))
-#    elif FMT_MSC_VER
-#      define FMT_DEPRECATED __declspec(deprecated)
-#    else
-#      define FMT_DEPRECATED /* deprecated */
-#    endif
-#  endif
+// An inline std::forward replacement.
+#define FMT_FORWARD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)
+
+#ifdef _MSC_VER
+#  define FMT_UNCHECKED_ITERATOR(It) \
+    using _Unchecked_type = It  // Mark iterator as checked.
+#else
+#  define FMT_UNCHECKED_ITERATOR(It) using unchecked_type = It
 #endif
 
 #ifndef FMT_BEGIN_NAMESPACE
 #  define FMT_BEGIN_NAMESPACE \
     namespace fmt {           \
-    inline namespace v8 {
+    inline namespace v9 {
 #  define FMT_END_NAMESPACE \
     }                       \
     }
@@ -270,25 +247,24 @@
 #endif
 
 // libc++ supports string_view in pre-c++17.
-#if (FMT_HAS_INCLUDE(<string_view>) &&                       \
-     (__cplusplus > 201402L || defined(_LIBCPP_VERSION))) || \
-    (defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
+#if FMT_HAS_INCLUDE(<string_view>) && \
+    (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION))
 #  include <string_view>
 #  define FMT_USE_STRING_VIEW
-#elif FMT_HAS_INCLUDE("experimental/string_view") && __cplusplus >= 201402L
+#elif FMT_HAS_INCLUDE("experimental/string_view") && FMT_CPLUSPLUS >= 201402L
 #  include <experimental/string_view>
 #  define FMT_USE_EXPERIMENTAL_STRING_VIEW
 #endif
 
 #ifndef FMT_UNICODE
-#  define FMT_UNICODE !FMT_MSC_VER
+#  define FMT_UNICODE !FMT_MSC_VERSION
 #endif
 
 #ifndef FMT_CONSTEVAL
-#  if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) &&      \
-       __cplusplus > 201703L && !defined(__apple_build_version__)) || \
-      (defined(__cpp_consteval) &&                                    \
-       (!FMT_MSC_VER || _MSC_FULL_VER >= 193030704))
+#  if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) &&         \
+       FMT_CPLUSPLUS >= 202002L && !defined(__apple_build_version__)) || \
+      (defined(__cpp_consteval) &&                                       \
+       (!FMT_MSC_VERSION || _MSC_FULL_VER >= 193030704))
 // consteval is broken in MSVC before VS2022 and Apple clang 13.
 #    define FMT_CONSTEVAL consteval
 #    define FMT_HAS_CONSTEVAL
@@ -297,19 +273,20 @@
 #  endif
 #endif
 
-#ifndef FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
-#  if defined(__cpp_nontype_template_args) &&                \
-      ((FMT_GCC_VERSION >= 903 && __cplusplus >= 201709L) || \
-       __cpp_nontype_template_args >= 201911L)
-#    define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1
+#ifndef FMT_USE_NONTYPE_TEMPLATE_ARGS
+#  if defined(__cpp_nontype_template_args) &&                  \
+      ((FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L) || \
+       __cpp_nontype_template_args >= 201911L) &&              \
+      !defined(__NVCOMPILER)
+#    define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
 #  else
-#    define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0
+#    define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
 #  endif
 #endif
 
 // Enable minimal optimizations for more compact code in debug mode.
 FMT_GCC_PRAGMA("GCC push_options")
-#ifndef __OPTIMIZE__
+#if !defined(__OPTIMIZE__) && !defined(__NVCOMPILER)
 FMT_GCC_PRAGMA("GCC optimize(\"Og\")")
 #endif
 
@@ -330,6 +307,20 @@
 using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
 template <typename T> struct type_identity { using type = T; };
 template <typename T> using type_identity_t = typename type_identity<T>::type;
+template <typename T>
+using underlying_t = typename std::underlying_type<T>::type;
+
+template <typename...> struct disjunction : std::false_type {};
+template <typename P> struct disjunction<P> : P {};
+template <typename P1, typename... Pn>
+struct disjunction<P1, Pn...>
+    : conditional_t<bool(P1::value), P1, disjunction<Pn...>> {};
+
+template <typename...> struct conjunction : std::true_type {};
+template <typename P> struct conjunction<P> : P {};
+template <typename P1, typename... Pn>
+struct conjunction<P1, Pn...>
+    : conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
 
 struct monostate {
   constexpr monostate() {}
@@ -346,13 +337,13 @@
 
 FMT_BEGIN_DETAIL_NAMESPACE
 
-// Suppress "unused variable" warnings with the method described in
+// Suppresses "unused variable" warnings with the method described in
 // https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
 // (void)var does not work on many Intel compilers.
 template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
 
-constexpr FMT_INLINE auto is_constant_evaluated(bool default_value = false)
-    FMT_NOEXCEPT -> bool {
+constexpr FMT_INLINE auto is_constant_evaluated(
+    bool default_value = false) noexcept -> bool {
 #ifdef __cpp_lib_is_constant_evaluated
   ignore_unused(default_value);
   return std::is_constant_evaluated();
@@ -361,7 +352,7 @@
 #endif
 }
 
-// A function to suppress "conditional expression is constant" warnings.
+// Suppresses "conditional expression is constant" warnings.
 template <typename T> constexpr FMT_INLINE auto const_check(T value) -> T {
   return value;
 }
@@ -371,7 +362,7 @@
 
 #ifndef FMT_ASSERT
 #  ifdef NDEBUG
-// FMT_ASSERT is not empty to avoid -Werror=empty-body.
+// FMT_ASSERT is not empty to avoid -Wempty-body.
 #    define FMT_ASSERT(condition, message) \
       ::fmt::detail::ignore_unused((condition), (message))
 #  else
@@ -382,12 +373,6 @@
 #  endif
 #endif
 
-#ifdef __cpp_lib_byte
-using byte = std::byte;
-#else
-enum class byte : unsigned char {};
-#endif
-
 #if defined(FMT_USE_STRING_VIEW)
 template <typename Char> using std_string_view = std::basic_string_view<Char>;
 #elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
@@ -399,11 +384,11 @@
 
 #ifdef FMT_USE_INT128
 // Do nothing.
-#elif defined(__SIZEOF_INT128__) && !FMT_NVCC && \
-    !(FMT_CLANG_VERSION && FMT_MSC_VER)
+#elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \
+    !(FMT_CLANG_VERSION && FMT_MSC_VERSION)
 #  define FMT_USE_INT128 1
-using int128_t = __int128_t;
-using uint128_t = __uint128_t;
+using int128_opt = __int128_t;  // An optional native 128-bit integer.
+using uint128_opt = __uint128_t;
 template <typename T> inline auto convert_for_visit(T value) -> T {
   return value;
 }
@@ -411,27 +396,24 @@
 #  define FMT_USE_INT128 0
 #endif
 #if !FMT_USE_INT128
-enum class int128_t {};
-enum class uint128_t {};
+enum class int128_opt {};
+enum class uint128_opt {};
 // Reduce template instantiations.
-template <typename T> inline auto convert_for_visit(T) -> monostate {
-  return {};
-}
+template <typename T> auto convert_for_visit(T) -> monostate { return {}; }
 #endif
 
 // Casts a nonnegative integer to unsigned.
 template <typename Int>
 FMT_CONSTEXPR auto to_unsigned(Int value) ->
     typename std::make_unsigned<Int>::type {
-  FMT_ASSERT(value >= 0, "negative value");
+  FMT_ASSERT(std::is_unsigned<Int>::value || value >= 0, "negative value");
   return static_cast<typename std::make_unsigned<Int>::type>(value);
 }
 
 FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char micro[] = "\u00B5";
 
 constexpr auto is_utf8() -> bool {
-  // Avoid buggy sign extensions in MSVC's constant evaluation mode.
-  // https://developercommunity.visualstudio.com/t/C-difference-in-behavior-for-unsigned/1233612
+  // Avoid buggy sign extensions in MSVC's constant evaluation mode (#2297).
   using uchar = unsigned char;
   return FMT_UNICODE || (sizeof(micro) == 3 && uchar(micro[0]) == 0xC2 &&
                          uchar(micro[1]) == 0xB5);
@@ -454,12 +436,11 @@
   using value_type = Char;
   using iterator = const Char*;
 
-  constexpr basic_string_view() FMT_NOEXCEPT : data_(nullptr), size_(0) {}
+  constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {}
 
   /** Constructs a string reference object from a C string and a size. */
-  constexpr basic_string_view(const Char* s, size_t count) FMT_NOEXCEPT
-      : data_(s),
-        size_(count) {}
+  constexpr basic_string_view(const Char* s, size_t count) noexcept
+      : data_(s), size_(count) {}
 
   /**
     \rst
@@ -479,29 +460,28 @@
   /** Constructs a string reference from a ``std::basic_string`` object. */
   template <typename Traits, typename Alloc>
   FMT_CONSTEXPR basic_string_view(
-      const std::basic_string<Char, Traits, Alloc>& s) FMT_NOEXCEPT
-      : data_(s.data()),
-        size_(s.size()) {}
+      const std::basic_string<Char, Traits, Alloc>& s) noexcept
+      : data_(s.data()), size_(s.size()) {}
 
   template <typename S, FMT_ENABLE_IF(std::is_same<
                                       S, detail::std_string_view<Char>>::value)>
-  FMT_CONSTEXPR basic_string_view(S s) FMT_NOEXCEPT : data_(s.data()),
-                                                      size_(s.size()) {}
+  FMT_CONSTEXPR basic_string_view(S s) noexcept
+      : data_(s.data()), size_(s.size()) {}
 
   /** Returns a pointer to the string data. */
-  constexpr auto data() const FMT_NOEXCEPT -> const Char* { return data_; }
+  constexpr auto data() const noexcept -> const Char* { return data_; }
 
   /** Returns the string size. */
-  constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; }
+  constexpr auto size() const noexcept -> size_t { return size_; }
 
-  constexpr auto begin() const FMT_NOEXCEPT -> iterator { return data_; }
-  constexpr auto end() const FMT_NOEXCEPT -> iterator { return data_ + size_; }
+  constexpr auto begin() const noexcept -> iterator { return data_; }
+  constexpr auto end() const noexcept -> iterator { return data_ + size_; }
 
-  constexpr auto operator[](size_t pos) const FMT_NOEXCEPT -> const Char& {
+  constexpr auto operator[](size_t pos) const noexcept -> const Char& {
     return data_[pos];
   }
 
-  FMT_CONSTEXPR void remove_prefix(size_t n) FMT_NOEXCEPT {
+  FMT_CONSTEXPR void remove_prefix(size_t n) noexcept {
     data_ += n;
     size_ -= n;
   }
@@ -543,6 +523,14 @@
 template <typename T> struct is_char : std::false_type {};
 template <> struct is_char<char> : std::true_type {};
 
+FMT_BEGIN_DETAIL_NAMESPACE
+
+// A base class for compile-time strings.
+struct compile_string {};
+
+template <typename S>
+struct is_compile_string : std::is_base_of<compile_string, S> {};
+
 // Returns a string view of `s`.
 template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>
 FMT_INLINE auto to_string_view(const Char* s) -> basic_string_view<Char> {
@@ -559,33 +547,21 @@
   return s;
 }
 template <typename Char,
-          FMT_ENABLE_IF(!std::is_empty<detail::std_string_view<Char>>::value)>
-inline auto to_string_view(detail::std_string_view<Char> s)
-    -> basic_string_view<Char> {
+          FMT_ENABLE_IF(!std::is_empty<std_string_view<Char>>::value)>
+inline auto to_string_view(std_string_view<Char> s) -> basic_string_view<Char> {
   return s;
 }
-
-// A base class for compile-time strings. It is defined in the fmt namespace to
-// make formatting functions visible via ADL, e.g. format(FMT_STRING("{}"), 42).
-struct compile_string {};
-
-template <typename S>
-struct is_compile_string : std::is_base_of<compile_string, S> {};
-
 template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
 constexpr auto to_string_view(const S& s)
     -> basic_string_view<typename S::char_type> {
   return basic_string_view<typename S::char_type>(s);
 }
-
-FMT_BEGIN_DETAIL_NAMESPACE
-
 void to_string_view(...);
-using fmt::to_string_view;
 
 // Specifies whether S is a string type convertible to fmt::basic_string_view.
 // It should be a constexpr function but MSVC 2017 fails to compile it in
 // enable_if and MSVC 2015 fails to compile it as an alias template.
+// ADL invocation of to_string_view is DEPRECATED!
 template <typename S>
 struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))> {
 };
@@ -596,17 +572,60 @@
   using type = typename result::value_type;
 };
 
-// Reports a compile-time error if S is not a valid format string.
-template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
-FMT_INLINE void check_format_string(const S&) {
-#ifdef FMT_ENFORCE_COMPILE_STRING
-  static_assert(is_compile_string<S>::value,
-                "FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
-                "FMT_STRING.");
-#endif
+enum class type {
+  none_type,
+  // Integer types should go first,
+  int_type,
+  uint_type,
+  long_long_type,
+  ulong_long_type,
+  int128_type,
+  uint128_type,
+  bool_type,
+  char_type,
+  last_integer_type = char_type,
+  // followed by floating-point types.
+  float_type,
+  double_type,
+  long_double_type,
+  last_numeric_type = long_double_type,
+  cstring_type,
+  string_type,
+  pointer_type,
+  custom_type
+};
+
+// Maps core type T to the corresponding type enum constant.
+template <typename T, typename Char>
+struct type_constant : std::integral_constant<type, type::custom_type> {};
+
+#define FMT_TYPE_CONSTANT(Type, constant) \
+  template <typename Char>                \
+  struct type_constant<Type, Char>        \
+      : std::integral_constant<type, type::constant> {}
+
+FMT_TYPE_CONSTANT(int, int_type);
+FMT_TYPE_CONSTANT(unsigned, uint_type);
+FMT_TYPE_CONSTANT(long long, long_long_type);
+FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
+FMT_TYPE_CONSTANT(int128_opt, int128_type);
+FMT_TYPE_CONSTANT(uint128_opt, uint128_type);
+FMT_TYPE_CONSTANT(bool, bool_type);
+FMT_TYPE_CONSTANT(Char, char_type);
+FMT_TYPE_CONSTANT(float, float_type);
+FMT_TYPE_CONSTANT(double, double_type);
+FMT_TYPE_CONSTANT(long double, long_double_type);
+FMT_TYPE_CONSTANT(const Char*, cstring_type);
+FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);
+FMT_TYPE_CONSTANT(const void*, pointer_type);
+
+constexpr bool is_integral_type(type t) {
+  return t > type::none_type && t <= type::last_integer_type;
 }
-template <typename..., typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
-void check_format_string(S);
+
+constexpr bool is_arithmetic_type(type t) {
+  return t > type::none_type && t <= type::last_numeric_type;
+}
 
 FMT_NORETURN FMT_API void throw_format_error(const char* message);
 
@@ -615,7 +634,9 @@
   constexpr error_handler(const error_handler&) = default;
 
   // This function is intentionally not constexpr to give a compile-time error.
-  FMT_NORETURN FMT_API void on_error(const char* message);
+  FMT_NORETURN void on_error(const char* message) {
+    throw_format_error(message);
+  }
 };
 FMT_END_DETAIL_NAMESPACE
 
@@ -635,6 +656,8 @@
   basic_string_view<Char> format_str_;
   int next_arg_id_;
 
+  FMT_CONSTEXPR void do_check_arg_id(int id);
+
  public:
   using char_type = Char;
   using iterator = typename basic_string_view<Char>::iterator;
@@ -648,16 +671,14 @@
     Returns an iterator to the beginning of the format string range being
     parsed.
    */
-  constexpr auto begin() const FMT_NOEXCEPT -> iterator {
+  constexpr auto begin() const noexcept -> iterator {
     return format_str_.begin();
   }
 
   /**
     Returns an iterator past the end of the format string range being parsed.
    */
-  constexpr auto end() const FMT_NOEXCEPT -> iterator {
-    return format_str_.end();
-  }
+  constexpr auto end() const noexcept -> iterator { return format_str_.end(); }
 
   /** Advances the begin iterator to ``it``. */
   FMT_CONSTEXPR void advance_to(iterator it) {
@@ -669,25 +690,29 @@
     the next argument index and switches to the automatic indexing.
    */
   FMT_CONSTEXPR auto next_arg_id() -> int {
-    // Don't check if the argument id is valid to avoid overhead and because it
-    // will be checked during formatting anyway.
-    if (next_arg_id_ >= 0) return next_arg_id_++;
-    on_error("cannot switch from manual to automatic argument indexing");
-    return 0;
+    if (next_arg_id_ < 0) {
+      on_error("cannot switch from manual to automatic argument indexing");
+      return 0;
+    }
+    int id = next_arg_id_++;
+    do_check_arg_id(id);
+    return id;
   }
 
   /**
     Reports an error if using the automatic argument indexing; otherwise
     switches to the manual indexing.
    */
-  FMT_CONSTEXPR void check_arg_id(int) {
-    if (next_arg_id_ > 0)
+  FMT_CONSTEXPR void check_arg_id(int id) {
+    if (next_arg_id_ > 0) {
       on_error("cannot switch from automatic to manual argument indexing");
-    else
-      next_arg_id_ = -1;
+      return;
+    }
+    next_arg_id_ = -1;
+    do_check_arg_id(id);
   }
-
   FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {}
+  FMT_CONSTEXPR void check_dynamic_spec(int arg_id);
 
   FMT_CONSTEXPR void on_error(const char* message) {
     ErrorHandler::on_error(message);
@@ -698,6 +723,65 @@
 
 using format_parse_context = basic_format_parse_context<char>;
 
+FMT_BEGIN_DETAIL_NAMESPACE
+// A parse context with extra data used only in compile-time checks.
+template <typename Char, typename ErrorHandler = detail::error_handler>
+class compile_parse_context
+    : public basic_format_parse_context<Char, ErrorHandler> {
+ private:
+  int num_args_;
+  const type* types_;
+  using base = basic_format_parse_context<Char, ErrorHandler>;
+
+ public:
+  explicit FMT_CONSTEXPR compile_parse_context(
+      basic_string_view<Char> format_str, int num_args, const type* types,
+      ErrorHandler eh = {}, int next_arg_id = 0)
+      : base(format_str, eh, next_arg_id), num_args_(num_args), types_(types) {}
+
+  constexpr auto num_args() const -> int { return num_args_; }
+  constexpr auto arg_type(int id) const -> type { return types_[id]; }
+
+  FMT_CONSTEXPR auto next_arg_id() -> int {
+    int id = base::next_arg_id();
+    if (id >= num_args_) this->on_error("argument not found");
+    return id;
+  }
+
+  FMT_CONSTEXPR void check_arg_id(int id) {
+    base::check_arg_id(id);
+    if (id >= num_args_) this->on_error("argument not found");
+  }
+  using base::check_arg_id;
+
+  FMT_CONSTEXPR void check_dynamic_spec(int arg_id) {
+    if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id]))
+      this->on_error("width/precision is not integer");
+  }
+};
+FMT_END_DETAIL_NAMESPACE
+
+template <typename Char, typename ErrorHandler>
+FMT_CONSTEXPR void
+basic_format_parse_context<Char, ErrorHandler>::do_check_arg_id(int id) {
+  // Argument id is only checked at compile-time during parsing because
+  // formatting has its own validation.
+  if (detail::is_constant_evaluated() && FMT_GCC_VERSION >= 1200) {
+    using context = detail::compile_parse_context<Char, ErrorHandler>;
+    if (id >= static_cast<context*>(this)->num_args())
+      on_error("argument not found");
+  }
+}
+
+template <typename Char, typename ErrorHandler>
+FMT_CONSTEXPR void
+basic_format_parse_context<Char, ErrorHandler>::check_dynamic_spec(int arg_id) {
+  if (detail::is_constant_evaluated()) {
+    using context = detail::compile_parse_context<Char, ErrorHandler>;
+    static_cast<context*>(this)->check_dynamic_spec(arg_id);
+  }
+}
+
 template <typename Context> class basic_format_arg;
 template <typename Context> class basic_format_args;
 template <typename Context> class dynamic_format_arg_store;
@@ -744,10 +828,10 @@
 template <typename Container>
 inline auto get_container(std::back_insert_iterator<Container> it)
     -> Container& {
-  using bi_iterator = std::back_insert_iterator<Container>;
-  struct accessor : bi_iterator {
-    accessor(bi_iterator iter) : bi_iterator(iter) {}
-    using bi_iterator::container;
+  using base = std::back_insert_iterator<Container>;
+  struct accessor : base {
+    accessor(base b) : base(b) {}
+    using base::container;
   };
   return *accessor(it).container;
 }
@@ -784,18 +868,16 @@
  protected:
   // Don't initialize ptr_ since it is not accessed to save a few cycles.
   FMT_MSC_WARNING(suppress : 26495)
-  buffer(size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
+  buffer(size_t sz) noexcept : size_(sz), capacity_(sz) {}
 
-  FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0,
-                         size_t cap = 0) FMT_NOEXCEPT : ptr_(p),
-                                                        size_(sz),
-                                                        capacity_(cap) {}
+  FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) noexcept
+      : ptr_(p), size_(sz), capacity_(cap) {}
 
   FMT_CONSTEXPR20 ~buffer() = default;
   buffer(buffer&&) = default;
 
   /** Sets the buffer data and capacity. */
-  FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) FMT_NOEXCEPT {
+  FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept {
     ptr_ = buf_data;
     capacity_ = buf_capacity;
   }
@@ -810,23 +892,23 @@
   buffer(const buffer&) = delete;
   void operator=(const buffer&) = delete;
 
-  auto begin() FMT_NOEXCEPT -> T* { return ptr_; }
-  auto end() FMT_NOEXCEPT -> T* { return ptr_ + size_; }
+  auto begin() noexcept -> T* { return ptr_; }
+  auto end() noexcept -> T* { return ptr_ + size_; }
 
-  auto begin() const FMT_NOEXCEPT -> const T* { return ptr_; }
-  auto end() const FMT_NOEXCEPT -> const T* { return ptr_ + size_; }
+  auto begin() const noexcept -> const T* { return ptr_; }
+  auto end() const noexcept -> const T* { return ptr_ + size_; }
 
   /** Returns the size of this buffer. */
-  constexpr auto size() const FMT_NOEXCEPT -> size_t { return size_; }
+  constexpr auto size() const noexcept -> size_t { return size_; }
 
   /** Returns the capacity of this buffer. */
-  constexpr auto capacity() const FMT_NOEXCEPT -> size_t { return capacity_; }
+  constexpr auto capacity() const noexcept -> size_t { return capacity_; }
 
   /** Returns a pointer to the buffer data. */
-  FMT_CONSTEXPR auto data() FMT_NOEXCEPT -> T* { return ptr_; }
+  FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; }
 
   /** Returns a pointer to the buffer data. */
-  FMT_CONSTEXPR auto data() const FMT_NOEXCEPT -> const T* { return ptr_; }
+  FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }
 
   /** Clears this buffer. */
   void clear() { size_ = 0; }
@@ -854,11 +936,11 @@
   /** Appends data to the end of the buffer. */
   template <typename U> void append(const U* begin, const U* end);
 
-  template <typename I> FMT_CONSTEXPR auto operator[](I index) -> T& {
+  template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
     return ptr_[index];
   }
-  template <typename I>
-  FMT_CONSTEXPR auto operator[](I index) const -> const T& {
+  template <typename Idx>
+  FMT_CONSTEXPR auto operator[](Idx index) const -> const T& {
     return ptr_[index];
   }
 };
@@ -993,6 +1075,7 @@
       : buffer<typename Container::value_type>(c.size()), container_(c) {}
   explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)
       : iterator_buffer(get_container(out)) {}
+
   auto out() -> std::back_insert_iterator<Container> {
     return std::back_inserter(container_);
   }
@@ -1044,7 +1127,11 @@
 // Specifies if T has an enabled fallback_formatter specialization.
 template <typename T, typename Char>
 using has_fallback_formatter =
+#ifdef FMT_DEPRECATED_OSTREAM
     std::is_constructible<fallback_formatter<T, Char>>;
+#else
+    std::false_type;
+#endif
 
 struct view {};
 
@@ -1128,61 +1215,6 @@
   return count<is_statically_named_arg<Args>::value...>();
 }
 
-enum class type {
-  none_type,
-  // Integer types should go first,
-  int_type,
-  uint_type,
-  long_long_type,
-  ulong_long_type,
-  int128_type,
-  uint128_type,
-  bool_type,
-  char_type,
-  last_integer_type = char_type,
-  // followed by floating-point types.
-  float_type,
-  double_type,
-  long_double_type,
-  last_numeric_type = long_double_type,
-  cstring_type,
-  string_type,
-  pointer_type,
-  custom_type
-};
-
-// Maps core type T to the corresponding type enum constant.
-template <typename T, typename Char>
-struct type_constant : std::integral_constant<type, type::custom_type> {};
-
-#define FMT_TYPE_CONSTANT(Type, constant) \
-  template <typename Char>                \
-  struct type_constant<Type, Char>        \
-      : std::integral_constant<type, type::constant> {}
-
-FMT_TYPE_CONSTANT(int, int_type);
-FMT_TYPE_CONSTANT(unsigned, uint_type);
-FMT_TYPE_CONSTANT(long long, long_long_type);
-FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
-FMT_TYPE_CONSTANT(int128_t, int128_type);
-FMT_TYPE_CONSTANT(uint128_t, uint128_type);
-FMT_TYPE_CONSTANT(bool, bool_type);
-FMT_TYPE_CONSTANT(Char, char_type);
-FMT_TYPE_CONSTANT(float, float_type);
-FMT_TYPE_CONSTANT(double, double_type);
-FMT_TYPE_CONSTANT(long double, long_double_type);
-FMT_TYPE_CONSTANT(const Char*, cstring_type);
-FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);
-FMT_TYPE_CONSTANT(const void*, pointer_type);
-
-constexpr bool is_integral_type(type t) {
-  return t > type::none_type && t <= type::last_integer_type;
-}
-
-constexpr bool is_arithmetic_type(type t) {
-  return t > type::none_type && t <= type::last_numeric_type;
-}
-
 struct unformattable {};
 struct unformattable_char : unformattable {};
 struct unformattable_const : unformattable {};
@@ -1215,8 +1247,8 @@
     unsigned uint_value;
     long long long_long_value;
     unsigned long long ulong_long_value;
-    int128_t int128_value;
-    uint128_t uint128_value;
+    int128_opt int128_value;
+    uint128_opt uint128_value;
     bool bool_value;
     char_type char_value;
     float float_value;
@@ -1233,8 +1265,8 @@
   constexpr FMT_INLINE value(unsigned val) : uint_value(val) {}
   constexpr FMT_INLINE value(long long val) : long_long_value(val) {}
   constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {}
-  FMT_INLINE value(int128_t val) : int128_value(val) {}
-  FMT_INLINE value(uint128_t val) : uint128_value(val) {}
+  FMT_INLINE value(int128_opt val) : int128_value(val) {}
+  FMT_INLINE value(uint128_opt val) : uint128_value(val) {}
   constexpr FMT_INLINE value(float val) : float_value(val) {}
   constexpr FMT_INLINE value(double val) : double_value(val) {}
   FMT_INLINE value(long double val) : long_double_value(val) {}
@@ -1284,7 +1316,7 @@
 };
 
 template <typename Context, typename T>
-FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context>;
+FMT_CONSTEXPR auto make_arg(T&& value) -> basic_format_arg<Context>;
 
 // To minimize the number of types we need to deal with, long is translated
 // either to int or to long long depending on its size.
@@ -1292,6 +1324,21 @@
 using long_type = conditional_t<long_short, int, long long>;
 using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
 
+#ifdef __cpp_lib_byte
+inline auto format_as(std::byte b) -> unsigned char {
+  return static_cast<unsigned char>(b);
+}
+#endif
+
+template <typename T> struct has_format_as {
+  template <typename U, typename V = decltype(format_as(U())),
+            FMT_ENABLE_IF(std::is_enum<U>::value&& std::is_integral<V>::value)>
+  static auto check(U*) -> std::true_type;
+  static auto check(...) -> std::false_type;
+
+  enum { value = decltype(check(static_cast<T*>(nullptr)))::value };
+};
+
 // Maps formatting arguments to core types.
 // arg_mapper reports errors by returning unformattable instead of using
 // static_assert because it's used in the is_formattable trait.
@@ -1317,8 +1364,12 @@
       -> unsigned long long {
     return val;
   }
-  FMT_CONSTEXPR FMT_INLINE auto map(int128_t val) -> int128_t { return val; }
-  FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; }
+  FMT_CONSTEXPR FMT_INLINE auto map(int128_opt val) -> int128_opt {
+    return val;
+  }
+  FMT_CONSTEXPR FMT_INLINE auto map(uint128_opt val) -> uint128_opt {
+    return val;
+  }
   FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; }
 
   template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value ||
@@ -1365,45 +1416,24 @@
   }
   template <typename T,
             FMT_ENABLE_IF(
-                std::is_constructible<basic_string_view<char_type>, T>::value &&
+                std::is_convertible<T, basic_string_view<char_type>>::value &&
                 !is_string<T>::value && !has_formatter<T, Context>::value &&
                 !has_fallback_formatter<T, char_type>::value)>
   FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
       -> basic_string_view<char_type> {
     return basic_string_view<char_type>(val);
   }
-  template <
-      typename T,
-      FMT_ENABLE_IF(
-          std::is_constructible<std_string_view<char_type>, T>::value &&
-          !std::is_constructible<basic_string_view<char_type>, T>::value &&
-          !is_string<T>::value && !has_formatter<T, Context>::value &&
-          !has_fallback_formatter<T, char_type>::value)>
+  template <typename T,
+            FMT_ENABLE_IF(
+                std::is_convertible<T, std_string_view<char_type>>::value &&
+                !std::is_convertible<T, basic_string_view<char_type>>::value &&
+                !is_string<T>::value && !has_formatter<T, Context>::value &&
+                !has_fallback_formatter<T, char_type>::value)>
   FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
       -> basic_string_view<char_type> {
     return std_string_view<char_type>(val);
   }
 
-  using cstring_result = conditional_t<std::is_same<char_type, char>::value,
-                                       const char*, unformattable_pointer>;
-
-  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const signed char* val)
-      -> cstring_result {
-    return map(reinterpret_cast<const char*>(val));
-  }
-  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const unsigned char* val)
-      -> cstring_result {
-    return map(reinterpret_cast<const char*>(val));
-  }
-  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(signed char* val)
-      -> cstring_result {
-    return map(reinterpret_cast<const char*>(val));
-  }
-  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(unsigned char* val)
-      -> cstring_result {
-    return map(reinterpret_cast<const char*>(val));
-  }
-
   FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; }
   FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void* {
     return val;
@@ -1417,10 +1447,11 @@
   template <
       typename T,
       FMT_ENABLE_IF(
-          std::is_member_pointer<T>::value ||
+          std::is_pointer<T>::value || std::is_member_pointer<T>::value ||
           std::is_function<typename std::remove_pointer<T>::type>::value ||
           (std::is_convertible<const T&, const void*>::value &&
-           !std::is_convertible<const T&, const char_type*>::value))>
+           !std::is_convertible<const T&, const char_type*>::value &&
+           !has_formatter<T, Context>::value))>
   FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {
     return {};
   }
@@ -1434,16 +1465,19 @@
   template <typename T,
             FMT_ENABLE_IF(
                 std::is_enum<T>::value&& std::is_convertible<T, int>::value &&
-                !has_formatter<T, Context>::value &&
+                !has_format_as<T>::value && !has_formatter<T, Context>::value &&
                 !has_fallback_formatter<T, char_type>::value)>
-  FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
+  FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
       -> decltype(std::declval<arg_mapper>().map(
-          static_cast<typename std::underlying_type<T>::type>(val))) {
-    return map(static_cast<typename std::underlying_type<T>::type>(val));
+          static_cast<underlying_t<T>>(val))) {
+    return map(static_cast<underlying_t<T>>(val));
   }
 
-  FMT_CONSTEXPR FMT_INLINE auto map(detail::byte val) -> unsigned {
-    return map(static_cast<unsigned char>(val));
+  template <typename T, FMT_ENABLE_IF(has_format_as<T>::value &&
+                                      !has_formatter<T, Context>::value)>
+  FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
+      -> decltype(std::declval<arg_mapper>().map(format_as(T()))) {
+    return map(format_as(val));
   }
 
   template <typename T, typename U = remove_cvref_t<T>>
@@ -1452,8 +1486,9 @@
                       !std::is_const<remove_reference_t<T>>::value ||
                       has_fallback_formatter<U, char_type>::value> {};
 
-#if FMT_MSC_VER != 0 && FMT_MSC_VER < 1910
-  // Workaround a bug in MSVC.
+#if (FMT_MSC_VERSION != 0 && FMT_MSC_VERSION < 1910) || \
+    FMT_ICC_VERSION != 0 || defined(__NVCC__)
+  // Workaround a bug in MSVC and Intel (Issue 2746).
   template <typename T> FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& {
     return val;
   }
@@ -1471,6 +1506,8 @@
   template <typename T, typename U = remove_cvref_t<T>,
             FMT_ENABLE_IF(!is_string<U>::value && !is_char<U>::value &&
                           !std::is_array<U>::value &&
+                          !std::is_pointer<U>::value &&
+                          !has_format_as<U>::value &&
                           (has_formatter<U, Context>::value ||
                            has_fallback_formatter<U, char_type>::value))>
   FMT_CONSTEXPR FMT_INLINE auto map(T&& val)
@@ -1513,12 +1550,11 @@
 
  public:
   using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator;
-  appender(base it) FMT_NOEXCEPT : base(it) {}
-  using _Unchecked_type = appender;  // Mark iterator as checked.
+  appender(base it) noexcept : base(it) {}
+  FMT_UNCHECKED_ITERATOR(appender);
 
-  auto operator++() FMT_NOEXCEPT -> appender& { return *this; }
-
-  auto operator++(int) FMT_NOEXCEPT -> appender { return *this; }
+  auto operator++() noexcept -> appender& { return *this; }
+  auto operator++(int) noexcept -> appender { return *this; }
 };
 
 // A formatting argument. It is a trivially copyable/constructible type to
@@ -1529,7 +1565,7 @@
   detail::type type_;
 
   template <typename ContextType, typename T>
-  friend FMT_CONSTEXPR auto detail::make_arg(const T& value)
+  friend FMT_CONSTEXPR auto detail::make_arg(T&& value)
       -> basic_format_arg<ContextType>;
 
   template <typename Visitor, typename Ctx>
@@ -1564,7 +1600,7 @@
 
   constexpr basic_format_arg() : type_(detail::type::none_type) {}
 
-  constexpr explicit operator bool() const FMT_NOEXCEPT {
+  constexpr explicit operator bool() const noexcept {
     return type_ != detail::type::none_type;
   }
 
@@ -1632,6 +1668,11 @@
   return out;
 }
 
+template <typename Char, typename R, typename OutputIt>
+FMT_CONSTEXPR auto copy_str(R&& rng, OutputIt out) -> OutputIt {
+  return detail::copy_str<Char>(rng.begin(), rng.end(), out);
+}
+
 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
 // A workaround for gcc 4.8 to make void_t work in a SFINAE context.
 template <typename... Ts> struct void_t_impl { using type = void; };
@@ -1665,7 +1706,7 @@
 template <>
 struct is_contiguous_back_insert_iterator<appender> : std::true_type {};
 
-// A type-erased reference to an std::locale to avoid heavy <locale> include.
+// A type-erased reference to an std::locale to avoid a heavy <locale> include.
 class locale_ref {
  private:
   const void* locale_;  // A type-erased pointer to std::locale.
@@ -1674,7 +1715,7 @@
   constexpr locale_ref() : locale_(nullptr) {}
   template <typename Locale> explicit locale_ref(const Locale& loc);
 
-  explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; }
+  explicit operator bool() const noexcept { return locale_ != nullptr; }
 
   template <typename Locale> auto get() const -> Locale;
 };
@@ -1690,20 +1731,8 @@
 }
 
 template <typename Context, typename T>
-FMT_CONSTEXPR auto make_arg(const T& value) -> basic_format_arg<Context> {
-  basic_format_arg<Context> arg;
-  arg.type_ = mapped_type_constant<T, Context>::value;
-  arg.value_ = arg_mapper<Context>().map(value);
-  return arg;
-}
-
-// The type template parameter is there to avoid an ODR violation when using
-// a fallback formatter in one translation unit and an implicit conversion in
-// another (not recommended).
-template <bool IS_PACKED, typename Context, type, typename T,
-          FMT_ENABLE_IF(IS_PACKED)>
-FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
-  const auto& arg = arg_mapper<Context>().map(std::forward<T>(val));
+FMT_CONSTEXPR FMT_INLINE auto make_value(T&& val) -> value<Context> {
+  const auto& arg = arg_mapper<Context>().map(FMT_FORWARD(val));
 
   constexpr bool formattable_char =
       !std::is_same<decltype(arg), const unformattable_char&>::value;
@@ -1731,9 +1760,26 @@
   return {arg};
 }
 
+template <typename Context, typename T>
+FMT_CONSTEXPR auto make_arg(T&& value) -> basic_format_arg<Context> {
+  basic_format_arg<Context> arg;
+  arg.type_ = mapped_type_constant<T, Context>::value;
+  arg.value_ = make_value<Context>(value);
+  return arg;
+}
+
+// The type template parameter is there to avoid an ODR violation when using
+// a fallback formatter in one translation unit and an implicit conversion in
+// another (not recommended).
+template <bool IS_PACKED, typename Context, type, typename T,
+          FMT_ENABLE_IF(IS_PACKED)>
+FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
+  return make_value<Context>(val);
+}
+
 template <bool IS_PACKED, typename Context, type, typename T,
           FMT_ENABLE_IF(!IS_PACKED)>
-inline auto make_arg(const T& value) -> basic_format_arg<Context> {
+FMT_CONSTEXPR inline auto make_arg(T&& value) -> basic_format_arg<Context> {
   return make_arg<Context>(value);
 }
 FMT_END_DETAIL_NAMESPACE
@@ -1853,7 +1899,7 @@
         data_{detail::make_arg<
             is_packed, Context,
             detail::mapped_type_constant<remove_cvref_t<T>, Context>::value>(
-            std::forward<T>(args))...} {
+            FMT_FORWARD(args))...} {
     detail::init_named_args(data_.named_args(), 0, 0, args...);
   }
 };
@@ -1869,7 +1915,7 @@
 template <typename Context = format_context, typename... Args>
 constexpr auto make_format_args(Args&&... args)
     -> format_arg_store<Context, remove_cvref_t<Args>...> {
-  return {std::forward<Args>(args)...};
+  return {FMT_FORWARD(args)...};
 }
 
 /**
@@ -2015,14 +2061,22 @@
 // between clang and gcc on ARM (#1919).
 using format_args = basic_format_args<format_context>;
 
-// We cannot use enum classes as bit fields because of a gcc bug
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
+// We cannot use enum classes as bit fields because of a gcc bug, so we put them
+// in namespaces instead (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414).
+// Additionally, if an underlying type is specified, older gcc incorrectly warns
+// that the type is too small. Both bugs are fixed in gcc 9.3.
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903
+#  define FMT_ENUM_UNDERLYING_TYPE(type)
+#else
+#  define FMT_ENUM_UNDERLYING_TYPE(type) : type
+#endif
 namespace align {
-enum type { none, left, right, center, numeric };
+enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, left, right, center,
+                                                  numeric};
 }
 using align_t = align::type;
 namespace sign {
-enum type { none, minus, plus, space };
+enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, minus, plus, space};
 }
 using sign_t = sign::type;
 
@@ -2072,7 +2126,8 @@
   general_upper,   // 'G'
   chr,             // 'c'
   string,          // 's'
-  pointer          // 'p'
+  pointer,         // 'p'
+  debug            // '?'
 };
 
 // Format specifiers for built-in and string types.
@@ -2209,11 +2264,14 @@
 
   FMT_CONSTEXPR auto make_arg_ref(int arg_id) -> arg_ref_type {
     context_.check_arg_id(arg_id);
+    context_.check_dynamic_spec(arg_id);
     return arg_ref_type(arg_id);
   }
 
   FMT_CONSTEXPR auto make_arg_ref(auto_id) -> arg_ref_type {
-    return arg_ref_type(context_.next_arg_id());
+    int arg_id = context_.next_arg_id();
+    context_.check_dynamic_spec(arg_id);
+    return arg_ref_type(arg_id);
   }
 
   FMT_CONSTEXPR auto make_arg_ref(basic_string_view<char_type> arg_id)
@@ -2231,21 +2289,23 @@
 
 // Converts a character to ASCII. Returns a number > 127 on conversion failure.
 template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
-constexpr auto to_ascii(Char value) -> Char {
-  return value;
+constexpr auto to_ascii(Char c) -> Char {
+  return c;
 }
 template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>
-constexpr auto to_ascii(Char value) ->
-    typename std::underlying_type<Char>::type {
-  return value;
+constexpr auto to_ascii(Char c) -> underlying_t<Char> {
+  return c;
+}
+
+FMT_CONSTEXPR inline auto code_point_length_impl(char c) -> int {
+  return "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4"
+      [static_cast<unsigned char>(c) >> 3];
 }
 
 template <typename Char>
 FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int {
   if (const_check(sizeof(Char) != 1)) return 1;
-  auto lengths =
-      "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4";
-  int len = lengths[static_cast<unsigned char>(*begin) >> 3];
+  int len = code_point_length_impl(static_cast<char>(*begin));
 
   // Compute the pointer to the next character early so that the next
   // iteration can start working on the next character. Neither Clang
@@ -2302,7 +2362,7 @@
   FMT_ASSERT(begin != end, "");
   auto align = align::none;
   auto p = begin + code_point_length(begin);
-  if (p >= end) p = begin;
+  if (end - p <= 0) p = begin;
   for (;;) {
     switch (to_ascii(*p)) {
     case '<':
@@ -2488,6 +2548,8 @@
     return presentation_type::string;
   case 'p':
     return presentation_type::pointer;
+  case '?':
+    return presentation_type::debug;
   default:
     return presentation_type::none;
   }
@@ -2635,21 +2697,21 @@
     return;
   }
   struct writer {
-    FMT_CONSTEXPR void operator()(const Char* pbegin, const Char* pend) {
-      if (pbegin == pend) return;
+    FMT_CONSTEXPR void operator()(const Char* from, const Char* to) {
+      if (from == to) return;
       for (;;) {
         const Char* p = nullptr;
-        if (!find<IS_CONSTEXPR>(pbegin, pend, Char('}'), p))
-          return handler_.on_text(pbegin, pend);
+        if (!find<IS_CONSTEXPR>(from, to, Char('}'), p))
+          return handler_.on_text(from, to);
         ++p;
-        if (p == pend || *p != '}')
+        if (p == to || *p != '}')
           return handler_.on_error("unmatched '}' in format string");
-        handler_.on_text(pbegin, p);
-        pbegin = p + 1;
+        handler_.on_text(from, p);
+        from = p + 1;
       }
     }
     Handler& handler_;
-  } write{handler};
+  } write = {handler};
   while (begin != end) {
     // Doing two passes with memchr (one for '{' and another for '}') is up to
     // 2.5x faster than the naive one-pass implementation on big format strings.
@@ -2661,50 +2723,29 @@
   }
 }
 
+template <typename T, bool = is_named_arg<T>::value> struct strip_named_arg {
+  using type = T;
+};
+template <typename T> struct strip_named_arg<T, true> {
+  using type = remove_cvref_t<decltype(T::value)>;
+};
+
 template <typename T, typename ParseContext>
 FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)
     -> decltype(ctx.begin()) {
   using char_type = typename ParseContext::char_type;
   using context = buffer_context<char_type>;
+  using stripped_type = typename strip_named_arg<T>::type;
   using mapped_type = conditional_t<
       mapped_type_constant<T, context>::value != type::custom_type,
-      decltype(arg_mapper<context>().map(std::declval<const T&>())), T>;
+      decltype(arg_mapper<context>().map(std::declval<const T&>())),
+      stripped_type>;
   auto f = conditional_t<has_formatter<mapped_type, context>::value,
                          formatter<mapped_type, char_type>,
-                         fallback_formatter<T, char_type>>();
+                         fallback_formatter<stripped_type, char_type>>();
   return f.parse(ctx);
 }
 
-// A parse context with extra argument id checks. It is only used at compile
-// time because adding checks at runtime would introduce substantial overhead
-// and would be redundant since argument ids are checked when arguments are
-// retrieved anyway.
-template <typename Char, typename ErrorHandler = error_handler>
-class compile_parse_context
-    : public basic_format_parse_context<Char, ErrorHandler> {
- private:
-  int num_args_;
-  using base = basic_format_parse_context<Char, ErrorHandler>;
-
- public:
-  explicit FMT_CONSTEXPR compile_parse_context(
-      basic_string_view<Char> format_str,
-      int num_args = (std::numeric_limits<int>::max)(), ErrorHandler eh = {})
-      : base(format_str, eh), num_args_(num_args) {}
-
-  FMT_CONSTEXPR auto next_arg_id() -> int {
-    int id = base::next_arg_id();
-    if (id >= num_args_) this->on_error("argument not found");
-    return id;
-  }
-
-  FMT_CONSTEXPR void check_arg_id(int id) {
-    base::check_arg_id(id);
-    if (id >= num_args_) this->on_error("argument not found");
-  }
-  using base::check_arg_id;
-};
-
 template <typename ErrorHandler>
 FMT_CONSTEXPR void check_int_type_spec(presentation_type type,
                                        ErrorHandler&& eh) {
@@ -2717,7 +2758,8 @@
 FMT_CONSTEXPR auto check_char_specs(const basic_format_specs<Char>& specs,
                                     ErrorHandler&& eh = {}) -> bool {
   if (specs.type != presentation_type::none &&
-      specs.type != presentation_type::chr) {
+      specs.type != presentation_type::chr &&
+      specs.type != presentation_type::debug) {
     check_int_type_spec(specs.type, eh);
     return false;
   }
@@ -2741,7 +2783,6 @@
   bool upper : 1;
   bool locale : 1;
   bool binary32 : 1;
-  bool fallback : 1;
   bool showpoint : 1;
 };
 
@@ -2792,7 +2833,8 @@
 template <typename ErrorHandler = error_handler>
 FMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type,
                                            ErrorHandler&& eh = {}) -> bool {
-  if (type == presentation_type::none || type == presentation_type::string)
+  if (type == presentation_type::none || type == presentation_type::string ||
+      type == presentation_type::debug)
     return true;
   if (type != presentation_type::pointer) eh.on_error("invalid type specifier");
   return false;
@@ -2801,7 +2843,8 @@
 template <typename ErrorHandler = error_handler>
 FMT_CONSTEXPR void check_string_type_spec(presentation_type type,
                                           ErrorHandler&& eh = {}) {
-  if (type != presentation_type::none && type != presentation_type::string)
+  if (type != presentation_type::none && type != presentation_type::string &&
+      type != presentation_type::debug)
     eh.on_error("invalid type specifier");
 }
 
@@ -2835,7 +2878,8 @@
   FMT_CONSTEXPR void on_sign(sign_t s) {
     require_numeric_argument();
     if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
-        arg_type_ != type::long_long_type && arg_type_ != type::char_type) {
+        arg_type_ != type::long_long_type && arg_type_ != type::int128_type &&
+        arg_type_ != type::char_type) {
       this->on_error("format specifier requires signed argument");
     }
     Handler::on_sign(s);
@@ -2864,7 +2908,7 @@
 
 constexpr int invalid_arg_index = -1;
 
-#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+#if FMT_USE_NONTYPE_TEMPLATE_ARGS
 template <int N, typename T, typename... Args, typename Char>
 constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
   if constexpr (detail::is_statically_named_arg<T>()) {
@@ -2879,7 +2923,7 @@
 
 template <typename... Args, typename Char>
 FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
-#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+#if FMT_USE_NONTYPE_TEMPLATE_ARGS
   if constexpr (sizeof...(Args) > 0)
     return get_arg_index_by_name<0, Args...>(name);
 #endif
@@ -2890,20 +2934,28 @@
 template <typename Char, typename ErrorHandler, typename... Args>
 class format_string_checker {
  private:
+  // In the future basic_format_parse_context will replace compile_parse_context
+  // here and will use is_constant_evaluated and downcasting to access the data
+  // needed for compile-time checks: https://godbolt.org/z/GvWzcTjh1.
   using parse_context_type = compile_parse_context<Char, ErrorHandler>;
-  enum { num_args = sizeof...(Args) };
+  static constexpr int num_args = sizeof...(Args);
 
   // Format specifier parsing function.
   using parse_func = const Char* (*)(parse_context_type&);
 
   parse_context_type context_;
-  parse_func parse_funcs_[num_args > 0 ? num_args : 1];
+  parse_func parse_funcs_[num_args > 0 ? static_cast<size_t>(num_args) : 1];
+  type types_[num_args > 0 ? static_cast<size_t>(num_args) : 1];
 
  public:
   explicit FMT_CONSTEXPR format_string_checker(
       basic_string_view<Char> format_str, ErrorHandler eh)
-      : context_(format_str, num_args, eh),
-        parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
+      : context_(format_str, num_args, types_, eh),
+        parse_funcs_{&parse_format_specs<Args, parse_context_type>...},
+        types_{  // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject)
+            mapped_type_constant<Args,
+                                 basic_format_context<Char*, Char>>::value...} {
+  }
 
   FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
 
@@ -2912,7 +2964,7 @@
     return context_.check_arg_id(id), id;
   }
   FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
-#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+#if FMT_USE_NONTYPE_TEMPLATE_ARGS
     auto index = get_arg_index_by_name<Args...>(id);
     if (index == invalid_arg_index) on_error("named argument is not found");
     return context_.check_arg_id(index), index;
@@ -2937,10 +2989,19 @@
   }
 };
 
+// Reports a compile-time error if S is not a valid format string.
+template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
+FMT_INLINE void check_format_string(const S&) {
+#ifdef FMT_ENFORCE_COMPILE_STRING
+  static_assert(is_compile_string<S>::value,
+                "FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
+                "FMT_STRING.");
+#endif
+}
 template <typename... Args, typename S,
-          enable_if_t<(is_compile_string<S>::value), int>>
+          FMT_ENABLE_IF(is_compile_string<S>::value)>
 void check_format_string(S format_str) {
-  FMT_CONSTEXPR auto s = to_string_view(format_str);
+  FMT_CONSTEXPR auto s = basic_string_view<typename S::char_type>(format_str);
   using checker = format_string_checker<typename S::char_type, error_handler,
                                         remove_cvref_t<Args>...>;
   FMT_CONSTEXPR bool invalid_format =
@@ -3038,11 +3099,41 @@
     return it;
   }
 
+  template <detail::type U = detail::type_constant<T, Char>::value,
+            enable_if_t<(U == detail::type::string_type ||
+                         U == detail::type::cstring_type ||
+                         U == detail::type::char_type),
+                        int> = 0>
+  FMT_CONSTEXPR void set_debug_format() {
+    specs_.type = presentation_type::debug;
+  }
+
   template <typename FormatContext>
   FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
       -> decltype(ctx.out());
 };
 
+#define FMT_FORMAT_AS(Type, Base)                                        \
+  template <typename Char>                                               \
+  struct formatter<Type, Char> : formatter<Base, Char> {                 \
+    template <typename FormatContext>                                    \
+    auto format(Type const& val, FormatContext& ctx) const               \
+        -> decltype(ctx.out()) {                                         \
+      return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \
+    }                                                                    \
+  }
+
+FMT_FORMAT_AS(signed char, int);
+FMT_FORMAT_AS(unsigned char, unsigned);
+FMT_FORMAT_AS(short, int);
+FMT_FORMAT_AS(unsigned short, unsigned);
+FMT_FORMAT_AS(long, long long);
+FMT_FORMAT_AS(unsigned long, unsigned long long);
+FMT_FORMAT_AS(Char*, const Char*);
+FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
+FMT_FORMAT_AS(std::nullptr_t, const void*);
+FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
+
 template <typename Char> struct basic_runtime { basic_string_view<Char> str; };
 
 /** A compile-time format string. */
@@ -3078,10 +3169,8 @@
 
 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
 // Workaround broken conversion on older gcc.
-template <typename... Args> using format_string = string_view;
-template <typename S> auto runtime(const S& s) -> basic_string_view<char_t<S>> {
-  return s;
-}
+template <typename...> using format_string = string_view;
+inline auto runtime(string_view s) -> string_view { return s; }
 #else
 template <typename... Args>
 using format_string = basic_format_string<char, type_identity_t<Args>...>;
@@ -3095,9 +3184,7 @@
     fmt::print(fmt::runtime("{:d}"), "I am not a number");
   \endrst
  */
-template <typename S> auto runtime(const S& s) -> basic_runtime<char_t<S>> {
-  return {{s}};
-}
+inline auto runtime(string_view s) -> basic_runtime<char> { return {{s}}; }
 #endif
 
 FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format-inl.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format-inl.h
new file mode 100644
index 0000000..abe4ff1
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format-inl.h
@@ -0,0 +1,1721 @@
+// Formatting library for C++ - implementation
+//
+// Copyright (c) 2012 - 2016, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#ifndef FMT_FORMAT_INL_H_
+#define FMT_FORMAT_INL_H_
+
+#include <algorithm>
+#include <cctype>
+#include <cerrno>  // errno
+#include <climits>
+#include <cmath>
+#include <cstdarg>
+#include <cstring>  // std::memmove
+#include <cwchar>
+#include <exception>
+
+#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
+#  include <locale>
+#endif
+
+#ifdef _WIN32
+#  include <io.h>  // _isatty
+#endif
+
+#include "format.h"
+
+FMT_BEGIN_NAMESPACE
+namespace detail {
+
+FMT_FUNC void assert_fail(const char* file, int line, const char* message) {
+  // Use unchecked std::fprintf to avoid triggering another assertion when
+  // writing to stderr fails
+  std::fprintf(stderr, "%s:%d: assertion failed: %s", file, line, message);
+  // Chosen instead of std::abort to satisfy Clang in CUDA mode during device
+  // code pass.
+  std::terminate();
+}
+
+FMT_FUNC void throw_format_error(const char* message) {
+  FMT_THROW(format_error(message));
+}
+
+FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code,
+                                string_view message) noexcept {
+  // Report error code making sure that the output fits into
+  // inline_buffer_size to avoid dynamic memory allocation and potential
+  // bad_alloc.
+  out.try_resize(0);
+  static const char SEP[] = ": ";
+  static const char ERROR_STR[] = "error ";
+  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
+  size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
+  auto abs_value = static_cast<uint32_or_64_or_128_t<int>>(error_code);
+  if (detail::is_negative(error_code)) {
+    abs_value = 0 - abs_value;
+    ++error_code_size;
+  }
+  error_code_size += detail::to_unsigned(detail::count_digits(abs_value));
+  auto it = buffer_appender<char>(out);
+  if (message.size() <= inline_buffer_size - error_code_size)
+    format_to(it, FMT_STRING("{}{}"), message, SEP);
+  format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code);
+  FMT_ASSERT(out.size() <= inline_buffer_size, "");
+}
+
+FMT_FUNC void report_error(format_func func, int error_code,
+                           const char* message) noexcept {
+  memory_buffer full_message;
+  func(full_message, error_code, message);
+  // Don't use fwrite_fully because the latter may throw.
+  if (std::fwrite(full_message.data(), full_message.size(), 1, stderr) > 0)
+    std::fputc('\n', stderr);
+}
+
+// A wrapper around fwrite that throws on error.
+inline void fwrite_fully(const void* ptr, size_t size, size_t count,
+                         FILE* stream) {
+  std::fwrite(ptr, size, count, stream);
+}
+
+#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
+template <typename Locale>
+locale_ref::locale_ref(const Locale& loc) : locale_(&loc) {
+  static_assert(std::is_same<Locale, std::locale>::value, "");
+}
+
+template <typename Locale> Locale locale_ref::get() const {
+  static_assert(std::is_same<Locale, std::locale>::value, "");
+  return locale_ ? *static_cast<const std::locale*>(locale_) : std::locale();
+}
+
+template <typename Char>
+FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char> {
+  auto& facet = std::use_facet<std::numpunct<Char>>(loc.get<std::locale>());
+  auto grouping = facet.grouping();
+  auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep();
+  return {std::move(grouping), thousands_sep};
+}
+template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) {
+  return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>())
+      .decimal_point();
+}
+#else
+template <typename Char>
+FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result<Char> {
+  return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR};
+}
+template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) {
+  return '.';
+}
+#endif
+}  // namespace detail
+
+#if !FMT_MSC_VERSION
+FMT_API FMT_FUNC format_error::~format_error() noexcept = default;
+#endif
+
+FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str,
+                                         format_args args) {
+  auto ec = std::error_code(error_code, std::generic_category());
+  return std::system_error(ec, vformat(format_str, args));
+}
+
+namespace detail {
+
+template <typename F> inline bool operator==(basic_fp<F> x, basic_fp<F> y) {
+  return x.f == y.f && x.e == y.e;
+}
+
+// Compilers should be able to optimize this into the ror instruction.
+FMT_CONSTEXPR inline uint32_t rotr(uint32_t n, uint32_t r) noexcept {
+  r &= 31;
+  return (n >> r) | (n << (32 - r));
+}
+FMT_CONSTEXPR inline uint64_t rotr(uint64_t n, uint32_t r) noexcept {
+  r &= 63;
+  return (n >> r) | (n << (64 - r));
+}
+
+// Computes 128-bit result of multiplication of two 64-bit unsigned integers.
+inline uint128_fallback umul128(uint64_t x, uint64_t y) noexcept {
+#if FMT_USE_INT128
+  auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
+  return {static_cast<uint64_t>(p >> 64), static_cast<uint64_t>(p)};
+#elif defined(_MSC_VER) && defined(_M_X64)
+  auto result = uint128_fallback();
+  result.lo_ = _umul128(x, y, &result.hi_);
+  return result;
+#else
+  const uint64_t mask = static_cast<uint64_t>(max_value<uint32_t>());
+
+  uint64_t a = x >> 32;
+  uint64_t b = x & mask;
+  uint64_t c = y >> 32;
+  uint64_t d = y & mask;
+
+  uint64_t ac = a * c;
+  uint64_t bc = b * c;
+  uint64_t ad = a * d;
+  uint64_t bd = b * d;
+
+  uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
+
+  return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
+          (intermediate << 32) + (bd & mask)};
+#endif
+}
+
+// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox.
+namespace dragonbox {
+// Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
+inline uint64_t umul128_upper64(uint64_t x, uint64_t y) noexcept {
+#if FMT_USE_INT128
+  auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
+  return static_cast<uint64_t>(p >> 64);
+#elif defined(_MSC_VER) && defined(_M_X64)
+  return __umulh(x, y);
+#else
+  return umul128(x, y).high();
+#endif
+}
+
+// Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a
+// 128-bit unsigned integer.
+inline uint128_fallback umul192_upper128(uint64_t x,
+                                         uint128_fallback y) noexcept {
+  uint128_fallback r = umul128(x, y.high());
+  r += umul128_upper64(x, y.low());
+  return r;
+}
+
+// Computes upper 64 bits of multiplication of a 32-bit unsigned integer and a
+// 64-bit unsigned integer.
+inline uint64_t umul96_upper64(uint32_t x, uint64_t y) noexcept {
+  return umul128_upper64(static_cast<uint64_t>(x) << 32, y);
+}
+
+// Computes lower 128 bits of multiplication of a 64-bit unsigned integer and a
+// 128-bit unsigned integer.
+inline uint128_fallback umul192_lower128(uint64_t x,
+                                         uint128_fallback y) noexcept {
+  uint64_t high = x * y.high();
+  uint128_fallback high_low = umul128(x, y.low());
+  return {high + high_low.high(), high_low.low()};
+}
+
+// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a
+// 64-bit unsigned integer.
+inline uint64_t umul96_lower64(uint32_t x, uint64_t y) noexcept {
+  return x * y;
+}
+
+// Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from
+// https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1.
+inline int floor_log10_pow2(int e) noexcept {
+  FMT_ASSERT(e <= 2620 && e >= -2620, "too large exponent");
+  static_assert((-1 >> 1) == -1, "right shift is not arithmetic");
+  return (e * 315653) >> 20;
+}
+
+// Various fast log computations.
+inline int floor_log2_pow10(int e) noexcept {
+  FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent");
+  return (e * 1741647) >> 19;
+}
+inline int floor_log10_pow2_minus_log10_4_over_3(int e) noexcept {
+  FMT_ASSERT(e <= 2936 && e >= -2985, "too large exponent");
+  return (e * 631305 - 261663) >> 21;
+}
+
+static constexpr struct {
+  uint32_t divisor;
+  int shift_amount;
+} div_small_pow10_infos[] = {{10, 16}, {100, 16}};
+
+// Replaces n by floor(n / pow(10, N)) returning true if and only if n is
+// divisible by pow(10, N).
+// Precondition: n <= pow(10, N + 1).
+template <int N>
+bool check_divisibility_and_divide_by_pow10(uint32_t& n) noexcept {
+  // The numbers below are chosen such that:
+  //   1. floor(n/d) = floor(nm / 2^k) where d=10 or d=100,
+  //   2. nm mod 2^k < m if and only if n is divisible by d,
+  // where m is magic_number, k is shift_amount
+  // and d is divisor.
+  //
+  // Item 1 is a common technique of replacing division by a constant with
+  // multiplication, see e.g. "Division by Invariant Integers Using
+  // Multiplication" by Granlund and Montgomery (1994). magic_number (m) is set
+  // to ceil(2^k/d) for large enough k.
+  // The idea for item 2 originates from Schubfach.
+  constexpr auto info = div_small_pow10_infos[N - 1];
+  FMT_ASSERT(n <= info.divisor * 10, "n is too large");
+  constexpr uint32_t magic_number =
+      (1u << info.shift_amount) / info.divisor + 1;
+  n *= magic_number;
+  const uint32_t comparison_mask = (1u << info.shift_amount) - 1;
+  bool result = (n & comparison_mask) < magic_number;
+  n >>= info.shift_amount;
+  return result;
+}
+
+// Computes floor(n / pow(10, N)) for small n and N.
+// Precondition: n <= pow(10, N + 1).
+template <int N> uint32_t small_division_by_pow10(uint32_t n) noexcept {
+  constexpr auto info = div_small_pow10_infos[N - 1];
+  FMT_ASSERT(n <= info.divisor * 10, "n is too large");
+  constexpr uint32_t magic_number =
+      (1u << info.shift_amount) / info.divisor + 1;
+  return (n * magic_number) >> info.shift_amount;
+}
+
+// Computes floor(n / 10^(kappa + 1)) (float)
+inline uint32_t divide_by_10_to_kappa_plus_1(uint32_t n) noexcept {
+  // 1374389535 = ceil(2^37/100)
+  return static_cast<uint32_t>((static_cast<uint64_t>(n) * 1374389535) >> 37);
+}
+// Computes floor(n / 10^(kappa + 1)) (double)
+inline uint64_t divide_by_10_to_kappa_plus_1(uint64_t n) noexcept {
+  // 2361183241434822607 = ceil(2^(64+7)/1000)
+  return umul128_upper64(n, 2361183241434822607ull) >> 7;
+}
+
+// Various subroutines using pow10 cache
+template <class T> struct cache_accessor;
+
+template <> struct cache_accessor<float> {
+  using carrier_uint = float_info<float>::carrier_uint;
+  using cache_entry_type = uint64_t;
+
+  static uint64_t get_cached_power(int k) noexcept {
+    FMT_ASSERT(k >= float_info<float>::min_k && k <= float_info<float>::max_k,
+               "k is out of range");
+    static constexpr const uint64_t pow10_significands[] = {
+        0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f,
+        0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb,
+        0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28,
+        0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb,
+        0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a,
+        0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810,
+        0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff,
+        0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd,
+        0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424,
+        0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b,
+        0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000,
+        0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000,
+        0xc350000000000000, 0xf424000000000000, 0x9896800000000000,
+        0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000,
+        0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000,
+        0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000,
+        0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000,
+        0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000,
+        0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0,
+        0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940985,
+        0xa18f07d736b90be6, 0xc9f2c9cd04674edf, 0xfc6f7c4045812297,
+        0x9dc5ada82b70b59e, 0xc5371912364ce306, 0xf684df56c3e01bc7,
+        0x9a130b963a6c115d, 0xc097ce7bc90715b4, 0xf0bdc21abb48db21,
+        0x96769950b50d88f5, 0xbc143fa4e250eb32, 0xeb194f8e1ae525fe,
+        0x92efd1b8d0cf37bf, 0xb7abc627050305ae, 0xe596b7b0c643c71a,
+        0x8f7e32ce7bea5c70, 0xb35dbf821ae4f38c, 0xe0352f62a19e306f};
+    return pow10_significands[k - float_info<float>::min_k];
+  }
+
+  struct compute_mul_result {
+    carrier_uint result;
+    bool is_integer;
+  };
+  struct compute_mul_parity_result {
+    bool parity;
+    bool is_integer;
+  };
+
+  static compute_mul_result compute_mul(
+      carrier_uint u, const cache_entry_type& cache) noexcept {
+    auto r = umul96_upper64(u, cache);
+    return {static_cast<carrier_uint>(r >> 32),
+            static_cast<carrier_uint>(r) == 0};
+  }
+
+  static uint32_t compute_delta(const cache_entry_type& cache,
+                                int beta) noexcept {
+    return static_cast<uint32_t>(cache >> (64 - 1 - beta));
+  }
+
+  static compute_mul_parity_result compute_mul_parity(
+      carrier_uint two_f, const cache_entry_type& cache, int beta) noexcept {
+    FMT_ASSERT(beta >= 1, "");
+    FMT_ASSERT(beta < 64, "");
+
+    auto r = umul96_lower64(two_f, cache);
+    return {((r >> (64 - beta)) & 1) != 0,
+            static_cast<uint32_t>(r >> (32 - beta)) == 0};
+  }
+
+  static carrier_uint compute_left_endpoint_for_shorter_interval_case(
+      const cache_entry_type& cache, int beta) noexcept {
+    return static_cast<carrier_uint>(
+        (cache - (cache >> (num_significand_bits<float>() + 2))) >>
+        (64 - num_significand_bits<float>() - 1 - beta));
+  }
+
+  static carrier_uint compute_right_endpoint_for_shorter_interval_case(
+      const cache_entry_type& cache, int beta) noexcept {
+    return static_cast<carrier_uint>(
+        (cache + (cache >> (num_significand_bits<float>() + 1))) >>
+        (64 - num_significand_bits<float>() - 1 - beta));
+  }
+
+  static carrier_uint compute_round_up_for_shorter_interval_case(
+      const cache_entry_type& cache, int beta) noexcept {
+    return (static_cast<carrier_uint>(
+                cache >> (64 - num_significand_bits<float>() - 2 - beta)) +
+            1) /
+           2;
+  }
+};
+
+template <> struct cache_accessor<double> {
+  using carrier_uint = float_info<double>::carrier_uint;
+  using cache_entry_type = uint128_fallback;
+
+  static uint128_fallback get_cached_power(int k) noexcept {
+    FMT_ASSERT(k >= float_info<double>::min_k && k <= float_info<double>::max_k,
+               "k is out of range");
+
+    static constexpr const uint128_fallback pow10_significands[] = {
+#if FMT_USE_FULL_CACHE_DRAGONBOX
+      {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},
+      {0x9faacf3df73609b1, 0x77b191618c54e9ad},
+      {0xc795830d75038c1d, 0xd59df5b9ef6a2418},
+      {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e},
+      {0x9becce62836ac577, 0x4ee367f9430aec33},
+      {0xc2e801fb244576d5, 0x229c41f793cda740},
+      {0xf3a20279ed56d48a, 0x6b43527578c11110},
+      {0x9845418c345644d6, 0x830a13896b78aaaa},
+      {0xbe5691ef416bd60c, 0x23cc986bc656d554},
+      {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9},
+      {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa},
+      {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54},
+      {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69},
+      {0x91376c36d99995be, 0x23100809b9c21fa2},
+      {0xb58547448ffffb2d, 0xabd40a0c2832a78b},
+      {0xe2e69915b3fff9f9, 0x16c90c8f323f516d},
+      {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4},
+      {0xb1442798f49ffb4a, 0x99cd11cfdf41779d},
+      {0xdd95317f31c7fa1d, 0x40405643d711d584},
+      {0x8a7d3eef7f1cfc52, 0x482835ea666b2573},
+      {0xad1c8eab5ee43b66, 0xda3243650005eed0},
+      {0xd863b256369d4a40, 0x90bed43e40076a83},
+      {0x873e4f75e2224e68, 0x5a7744a6e804a292},
+      {0xa90de3535aaae202, 0x711515d0a205cb37},
+      {0xd3515c2831559a83, 0x0d5a5b44ca873e04},
+      {0x8412d9991ed58091, 0xe858790afe9486c3},
+      {0xa5178fff668ae0b6, 0x626e974dbe39a873},
+      {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
+      {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a},
+      {0xa139029f6a239f72, 0x1c1fffc1ebc44e81},
+      {0xc987434744ac874e, 0xa327ffb266b56221},
+      {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9},
+      {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa},
+      {0xc4ce17b399107c22, 0xcb550fb4384d21d4},
+      {0xf6019da07f549b2b, 0x7e2a53a146606a49},
+      {0x99c102844f94e0fb, 0x2eda7444cbfc426e},
+      {0xc0314325637a1939, 0xfa911155fefb5309},
+      {0xf03d93eebc589f88, 0x793555ab7eba27cb},
+      {0x96267c7535b763b5, 0x4bc1558b2f3458df},
+      {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17},
+      {0xea9c227723ee8bcb, 0x465e15a979c1cadd},
+      {0x92a1958a7675175f, 0x0bfacd89ec191eca},
+      {0xb749faed14125d36, 0xcef980ec671f667c},
+      {0xe51c79a85916f484, 0x82b7e12780e7401b},
+      {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811},
+      {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16},
+      {0xdfbdcece67006ac9, 0x67a791e093e1d49b},
+      {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1},
+      {0xaecc49914078536d, 0x58fae9f773886e19},
+      {0xda7f5bf590966848, 0xaf39a475506a899f},
+      {0x888f99797a5e012d, 0x6d8406c952429604},
+      {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84},
+      {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65},
+      {0x855c3be0a17fcd26, 0x5cf2eea09a550680},
+      {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f},
+      {0xd0601d8efc57b08b, 0xf13b94daf124da27},
+      {0x823c12795db6ce57, 0x76c53d08d6b70859},
+      {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f},
+      {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a},
+      {0xfe5d54150b090b02, 0xd3f93b35435d7c4d},
+      {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0},
+      {0xc6b8e9b0709f109a, 0x359ab6419ca1091c},
+      {0xf867241c8cc6d4c0, 0xc30163d203c94b63},
+      {0x9b407691d7fc44f8, 0x79e0de63425dcf1e},
+      {0xc21094364dfb5636, 0x985915fc12f542e5},
+      {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e},
+      {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43},
+      {0xbd8430bd08277231, 0x50c6ff782a838354},
+      {0xece53cec4a314ebd, 0xa4f8bf5635246429},
+      {0x940f4613ae5ed136, 0x871b7795e136be9a},
+      {0xb913179899f68584, 0x28e2557b59846e40},
+      {0xe757dd7ec07426e5, 0x331aeada2fe589d0},
+      {0x9096ea6f3848984f, 0x3ff0d2c85def7622},
+      {0xb4bca50b065abe63, 0x0fed077a756b53aa},
+      {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895},
+      {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d},
+      {0xb080392cc4349dec, 0xbd8d794d96aacfb4},
+      {0xdca04777f541c567, 0xecf0d7a0fc5583a1},
+      {0x89e42caaf9491b60, 0xf41686c49db57245},
+      {0xac5d37d5b79b6239, 0x311c2875c522ced6},
+      {0xd77485cb25823ac7, 0x7d633293366b828c},
+      {0x86a8d39ef77164bc, 0xae5dff9c02033198},
+      {0xa8530886b54dbdeb, 0xd9f57f830283fdfd},
+      {0xd267caa862a12d66, 0xd072df63c324fd7c},
+      {0x8380dea93da4bc60, 0x4247cb9e59f71e6e},
+      {0xa46116538d0deb78, 0x52d9be85f074e609},
+      {0xcd795be870516656, 0x67902e276c921f8c},
+      {0x806bd9714632dff6, 0x00ba1cd8a3db53b7},
+      {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5},
+      {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce},
+      {0xfad2a4b13d1b5d6c, 0x796b805720085f82},
+      {0x9cc3a6eec6311a63, 0xcbe3303674053bb1},
+      {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d},
+      {0xf4f1b4d515acb93b, 0xee92fb5515482d45},
+      {0x991711052d8bf3c5, 0x751bdd152d4d1c4b},
+      {0xbf5cd54678eef0b6, 0xd262d45a78a0635e},
+      {0xef340a98172aace4, 0x86fb897116c87c35},
+      {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1},
+      {0xbae0a846d2195712, 0x8974836059cca10a},
+      {0xe998d258869facd7, 0x2bd1a438703fc94c},
+      {0x91ff83775423cc06, 0x7b6306a34627ddd0},
+      {0xb67f6455292cbf08, 0x1a3bc84c17b1d543},
+      {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94},
+      {0x8e938662882af53e, 0x547eb47b7282ee9d},
+      {0xb23867fb2a35b28d, 0xe99e619a4f23aa44},
+      {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5},
+      {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05},
+      {0xae0b158b4738705e, 0x9624ab50b148d446},
+      {0xd98ddaee19068c76, 0x3badd624dd9b0958},
+      {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7},
+      {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d},
+      {0xd47487cc8470652b, 0x7647c32000696720},
+      {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074},
+      {0xa5fb0a17c777cf09, 0xf468107100525891},
+      {0xcf79cc9db955c2cc, 0x7182148d4066eeb5},
+      {0x81ac1fe293d599bf, 0xc6f14cd848405531},
+      {0xa21727db38cb002f, 0xb8ada00e5a506a7d},
+      {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d},
+      {0xfd442e4688bd304a, 0x908f4a166d1da664},
+      {0x9e4a9cec15763e2e, 0x9a598e4e043287ff},
+      {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe},
+      {0xf7549530e188c128, 0xd12bee59e68ef47d},
+      {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf},
+      {0xc13a148e3032d6e7, 0xe36a52363c1faf02},
+      {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2},
+      {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba},
+      {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8},
+      {0xebdf661791d60f56, 0x111b495b3464ad22},
+      {0x936b9fcebb25c995, 0xcab10dd900beec35},
+      {0xb84687c269ef3bfb, 0x3d5d514f40eea743},
+      {0xe65829b3046b0afa, 0x0cb4a5a3112a5113},
+      {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac},
+      {0xb3f4e093db73a093, 0x59ed216765690f57},
+      {0xe0f218b8d25088b8, 0x306869c13ec3532d},
+      {0x8c974f7383725573, 0x1e414218c73a13fc},
+      {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
+      {0xdbac6c247d62a583, 0xdf45f746b74abf3a},
+      {0x894bc396ce5da772, 0x6b8bba8c328eb784},
+      {0xab9eb47c81f5114f, 0x066ea92f3f326565},
+      {0xd686619ba27255a2, 0xc80a537b0efefebe},
+      {0x8613fd0145877585, 0xbd06742ce95f5f37},
+      {0xa798fc4196e952e7, 0x2c48113823b73705},
+      {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6},
+      {0x82ef85133de648c4, 0x9a984d73dbe722fc},
+      {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb},
+      {0xcc963fee10b7d1b3, 0x318df905079926a9},
+      {0xffbbcfe994e5c61f, 0xfdf17746497f7053},
+      {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634},
+      {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1},
+      {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1},
+      {0x9c1661a651213e2d, 0x06bea10ca65c084f},
+      {0xc31bfa0fe5698db8, 0x486e494fcff30a63},
+      {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb},
+      {0x986ddb5c6b3a76b7, 0xf89629465a75e01d},
+      {0xbe89523386091465, 0xf6bbb397f1135824},
+      {0xee2ba6c0678b597f, 0x746aa07ded582e2d},
+      {0x94db483840b717ef, 0xa8c2a44eb4571cdd},
+      {0xba121a4650e4ddeb, 0x92f34d62616ce414},
+      {0xe896a0d7e51e1566, 0x77b020baf9c81d18},
+      {0x915e2486ef32cd60, 0x0ace1474dc1d122f},
+      {0xb5b5ada8aaff80b8, 0x0d819992132456bb},
+      {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a},
+      {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2},
+      {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3},
+      {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf},
+      {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c},
+      {0xad4ab7112eb3929d, 0x86c16c98d2c953c7},
+      {0xd89d64d57a607744, 0xe871c7bf077ba8b8},
+      {0x87625f056c7c4a8b, 0x11471cd764ad4973},
+      {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0},
+      {0xd389b47879823479, 0x4aff1d108d4ec2c4},
+      {0x843610cb4bf160cb, 0xcedf722a585139bb},
+      {0xa54394fe1eedb8fe, 0xc2974eb4ee658829},
+      {0xce947a3da6a9273e, 0x733d226229feea33},
+      {0x811ccc668829b887, 0x0806357d5a3f5260},
+      {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8},
+      {0xc9bcff6034c13052, 0xfc89b393dd02f0b6},
+      {0xfc2c3f3841f17c67, 0xbbac2078d443ace3},
+      {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e},
+      {0xc5029163f384a931, 0x0a9e795e65d4df12},
+      {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6},
+      {0x99ea0196163fa42e, 0x504bced1bf8e4e46},
+      {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7},
+      {0xf07da27a82c37088, 0x5d767327bb4e5a4d},
+      {0x964e858c91ba2655, 0x3a6a07f8d510f870},
+      {0xbbe226efb628afea, 0x890489f70a55368c},
+      {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f},
+      {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e},
+      {0xb77ada0617e3bbcb, 0x09ce6ebb40173745},
+      {0xe55990879ddcaabd, 0xcc420a6a101d0516},
+      {0x8f57fa54c2a9eab6, 0x9fa946824a12232e},
+      {0xb32df8e9f3546564, 0x47939822dc96abfa},
+      {0xdff9772470297ebd, 0x59787e2b93bc56f8},
+      {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b},
+      {0xaefae51477a06b03, 0xede622920b6b23f2},
+      {0xdab99e59958885c4, 0xe95fab368e45ecee},
+      {0x88b402f7fd75539b, 0x11dbcb0218ebb415},
+      {0xaae103b5fcd2a881, 0xd652bdc29f26a11a},
+      {0xd59944a37c0752a2, 0x4be76d3346f04960},
+      {0x857fcae62d8493a5, 0x6f70a4400c562ddc},
+      {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953},
+      {0xd097ad07a71f26b2, 0x7e2000a41346a7a8},
+      {0x825ecc24c873782f, 0x8ed400668c0c28c9},
+      {0xa2f67f2dfa90563b, 0x728900802f0f32fb},
+      {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba},
+      {0xfea126b7d78186bc, 0xe2f610c84987bfa9},
+      {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca},
+      {0xc6ede63fa05d3143, 0x91503d1c79720dbc},
+      {0xf8a95fcf88747d94, 0x75a44c6397ce912b},
+      {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb},
+      {0xc24452da229b021b, 0xfbe85badce996169},
+      {0xf2d56790ab41c2a2, 0xfae27299423fb9c4},
+      {0x97c560ba6b0919a5, 0xdccd879fc967d41b},
+      {0xbdb6b8e905cb600f, 0x5400e987bbc1c921},
+      {0xed246723473e3813, 0x290123e9aab23b69},
+      {0x9436c0760c86e30b, 0xf9a0b6720aaf6522},
+      {0xb94470938fa89bce, 0xf808e40e8d5b3e6a},
+      {0xe7958cb87392c2c2, 0xb60b1d1230b20e05},
+      {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3},
+      {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4},
+      {0xe2280b6c20dd5232, 0x25c6da63c38de1b1},
+      {0x8d590723948a535f, 0x579c487e5a38ad0f},
+      {0xb0af48ec79ace837, 0x2d835a9df0c6d852},
+      {0xdcdb1b2798182244, 0xf8e431456cf88e66},
+      {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900},
+      {0xac8b2d36eed2dac5, 0xe272467e3d222f40},
+      {0xd7adf884aa879177, 0x5b0ed81dcc6abb10},
+      {0x86ccbb52ea94baea, 0x98e947129fc2b4ea},
+      {0xa87fea27a539e9a5, 0x3f2398d747b36225},
+      {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae},
+      {0x83a3eeeef9153e89, 0x1953cf68300424ad},
+      {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8},
+      {0xcdb02555653131b6, 0x3792f412cb06794e},
+      {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1},
+      {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5},
+      {0xc8de047564d20a8b, 0xf245825a5a445276},
+      {0xfb158592be068d2e, 0xeed6e2f0f0d56713},
+      {0x9ced737bb6c4183d, 0x55464dd69685606c},
+      {0xc428d05aa4751e4c, 0xaa97e14c3c26b887},
+      {0xf53304714d9265df, 0xd53dd99f4b3066a9},
+      {0x993fe2c6d07b7fab, 0xe546a8038efe402a},
+      {0xbf8fdb78849a5f96, 0xde98520472bdd034},
+      {0xef73d256a5c0f77c, 0x963e66858f6d4441},
+      {0x95a8637627989aad, 0xdde7001379a44aa9},
+      {0xbb127c53b17ec159, 0x5560c018580d5d53},
+      {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7},
+      {0x9226712162ab070d, 0xcab3961304ca70e9},
+      {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23},
+      {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b},
+      {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243},
+      {0xb267ed1940f1c61c, 0x55f038b237591ed4},
+      {0xdf01e85f912e37a3, 0x6b6c46dec52f6689},
+      {0x8b61313bbabce2c6, 0x2323ac4b3b3da016},
+      {0xae397d8aa96c1b77, 0xabec975e0a0d081b},
+      {0xd9c7dced53c72255, 0x96e7bd358c904a22},
+      {0x881cea14545c7575, 0x7e50d64177da2e55},
+      {0xaa242499697392d2, 0xdde50bd1d5d0b9ea},
+      {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865},
+      {0x84ec3c97da624ab4, 0xbd5af13bef0b113f},
+      {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f},
+      {0xcfb11ead453994ba, 0x67de18eda5814af3},
+      {0x81ceb32c4b43fcf4, 0x80eacf948770ced8},
+      {0xa2425ff75e14fc31, 0xa1258379a94d028e},
+      {0xcad2f7f5359a3b3e, 0x096ee45813a04331},
+      {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd},
+      {0x9e74d1b791e07e48, 0x775ea264cf55347e},
+      {0xc612062576589dda, 0x95364afe032a819e},
+      {0xf79687aed3eec551, 0x3a83ddbd83f52205},
+      {0x9abe14cd44753b52, 0xc4926a9672793543},
+      {0xc16d9a0095928a27, 0x75b7053c0f178294},
+      {0xf1c90080baf72cb1, 0x5324c68b12dd6339},
+      {0x971da05074da7bee, 0xd3f6fc16ebca5e04},
+      {0xbce5086492111aea, 0x88f4bb1ca6bcf585},
+      {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6},
+      {0x9392ee8e921d5d07, 0x3aff322e62439fd0},
+      {0xb877aa3236a4b449, 0x09befeb9fad487c3},
+      {0xe69594bec44de15b, 0x4c2ebe687989a9b4},
+      {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11},
+      {0xb424dc35095cd80f, 0x538484c19ef38c95},
+      {0xe12e13424bb40e13, 0x2865a5f206b06fba},
+      {0x8cbccc096f5088cb, 0xf93f87b7442e45d4},
+      {0xafebff0bcb24aafe, 0xf78f69a51539d749},
+      {0xdbe6fecebdedd5be, 0xb573440e5a884d1c},
+      {0x89705f4136b4a597, 0x31680a88f8953031},
+      {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e},
+      {0xd6bf94d5e57a42bc, 0x3d32907604691b4d},
+      {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110},
+      {0xa7c5ac471b478423, 0x0fcf80dc33721d54},
+      {0xd1b71758e219652b, 0xd3c36113404ea4a9},
+      {0x83126e978d4fdf3b, 0x645a1cac083126ea},
+      {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4},
+      {0xcccccccccccccccc, 0xcccccccccccccccd},
+      {0x8000000000000000, 0x0000000000000000},
+      {0xa000000000000000, 0x0000000000000000},
+      {0xc800000000000000, 0x0000000000000000},
+      {0xfa00000000000000, 0x0000000000000000},
+      {0x9c40000000000000, 0x0000000000000000},
+      {0xc350000000000000, 0x0000000000000000},
+      {0xf424000000000000, 0x0000000000000000},
+      {0x9896800000000000, 0x0000000000000000},
+      {0xbebc200000000000, 0x0000000000000000},
+      {0xee6b280000000000, 0x0000000000000000},
+      {0x9502f90000000000, 0x0000000000000000},
+      {0xba43b74000000000, 0x0000000000000000},
+      {0xe8d4a51000000000, 0x0000000000000000},
+      {0x9184e72a00000000, 0x0000000000000000},
+      {0xb5e620f480000000, 0x0000000000000000},
+      {0xe35fa931a0000000, 0x0000000000000000},
+      {0x8e1bc9bf04000000, 0x0000000000000000},
+      {0xb1a2bc2ec5000000, 0x0000000000000000},
+      {0xde0b6b3a76400000, 0x0000000000000000},
+      {0x8ac7230489e80000, 0x0000000000000000},
+      {0xad78ebc5ac620000, 0x0000000000000000},
+      {0xd8d726b7177a8000, 0x0000000000000000},
+      {0x878678326eac9000, 0x0000000000000000},
+      {0xa968163f0a57b400, 0x0000000000000000},
+      {0xd3c21bcecceda100, 0x0000000000000000},
+      {0x84595161401484a0, 0x0000000000000000},
+      {0xa56fa5b99019a5c8, 0x0000000000000000},
+      {0xcecb8f27f4200f3a, 0x0000000000000000},
+      {0x813f3978f8940984, 0x4000000000000000},
+      {0xa18f07d736b90be5, 0x5000000000000000},
+      {0xc9f2c9cd04674ede, 0xa400000000000000},
+      {0xfc6f7c4045812296, 0x4d00000000000000},
+      {0x9dc5ada82b70b59d, 0xf020000000000000},
+      {0xc5371912364ce305, 0x6c28000000000000},
+      {0xf684df56c3e01bc6, 0xc732000000000000},
+      {0x9a130b963a6c115c, 0x3c7f400000000000},
+      {0xc097ce7bc90715b3, 0x4b9f100000000000},
+      {0xf0bdc21abb48db20, 0x1e86d40000000000},
+      {0x96769950b50d88f4, 0x1314448000000000},
+      {0xbc143fa4e250eb31, 0x17d955a000000000},
+      {0xeb194f8e1ae525fd, 0x5dcfab0800000000},
+      {0x92efd1b8d0cf37be, 0x5aa1cae500000000},
+      {0xb7abc627050305ad, 0xf14a3d9e40000000},
+      {0xe596b7b0c643c719, 0x6d9ccd05d0000000},
+      {0x8f7e32ce7bea5c6f, 0xe4820023a2000000},
+      {0xb35dbf821ae4f38b, 0xdda2802c8a800000},
+      {0xe0352f62a19e306e, 0xd50b2037ad200000},
+      {0x8c213d9da502de45, 0x4526f422cc340000},
+      {0xaf298d050e4395d6, 0x9670b12b7f410000},
+      {0xdaf3f04651d47b4c, 0x3c0cdd765f114000},
+      {0x88d8762bf324cd0f, 0xa5880a69fb6ac800},
+      {0xab0e93b6efee0053, 0x8eea0d047a457a00},
+      {0xd5d238a4abe98068, 0x72a4904598d6d880},
+      {0x85a36366eb71f041, 0x47a6da2b7f864750},
+      {0xa70c3c40a64e6c51, 0x999090b65f67d924},
+      {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d},
+      {0x82818f1281ed449f, 0xbff8f10e7a8921a5},
+      {0xa321f2d7226895c7, 0xaff72d52192b6a0e},
+      {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764491},
+      {0xfee50b7025c36a08, 0x02f236d04753d5b5},
+      {0x9f4f2726179a2245, 0x01d762422c946591},
+      {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef6},
+      {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb3},
+      {0x9b934c3b330c8577, 0x63cc55f49f88eb30},
+      {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fc},
+      {0xf316271c7fc3908a, 0x8bef464e3945ef7b},
+      {0x97edd871cfda3a56, 0x97758bf0e3cbb5ad},
+      {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea318},
+      {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bde},
+      {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6b},
+      {0xb975d6b6ee39e436, 0xb3e2fd538e122b45},
+      {0xe7d34c64a9c85d44, 0x60dbbca87196b617},
+      {0x90e40fbeea1d3a4a, 0xbc8955e946fe31ce},
+      {0xb51d13aea4a488dd, 0x6babab6398bdbe42},
+      {0xe264589a4dcdab14, 0xc696963c7eed2dd2},
+      {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca3},
+      {0xb0de65388cc8ada8, 0x3b25a55f43294bcc},
+      {0xdd15fe86affad912, 0x49ef0eb713f39ebf},
+      {0x8a2dbf142dfcc7ab, 0x6e3569326c784338},
+      {0xacb92ed9397bf996, 0x49c2c37f07965405},
+      {0xd7e77a8f87daf7fb, 0xdc33745ec97be907},
+      {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a4},
+      {0xa8acd7c0222311bc, 0xc40832ea0d68ce0d},
+      {0xd2d80db02aabd62b, 0xf50a3fa490c30191},
+      {0x83c7088e1aab65db, 0x792667c6da79e0fb},
+      {0xa4b8cab1a1563f52, 0x577001b891185939},
+      {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87},
+      {0x80b05e5ac60b6178, 0x544f8158315b05b5},
+      {0xa0dc75f1778e39d6, 0x696361ae3db1c722},
+      {0xc913936dd571c84c, 0x03bc3a19cd1e38ea},
+      {0xfb5878494ace3a5f, 0x04ab48a04065c724},
+      {0x9d174b2dcec0e47b, 0x62eb0d64283f9c77},
+      {0xc45d1df942711d9a, 0x3ba5d0bd324f8395},
+      {0xf5746577930d6500, 0xca8f44ec7ee3647a},
+      {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecc},
+      {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67f},
+      {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101f},
+      {0x95d04aee3b80ece5, 0xbba1f1d158724a13},
+      {0xbb445da9ca61281f, 0x2a8a6e45ae8edc98},
+      {0xea1575143cf97226, 0xf52d09d71a3293be},
+      {0x924d692ca61be758, 0x593c2626705f9c57},
+      {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836d},
+      {0xe498f455c38b997a, 0x0b6dfb9c0f956448},
+      {0x8edf98b59a373fec, 0x4724bd4189bd5ead},
+      {0xb2977ee300c50fe7, 0x58edec91ec2cb658},
+      {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ee},
+      {0x8b865b215899f46c, 0xbd79e0d20082ee75},
+      {0xae67f1e9aec07187, 0xecd8590680a3aa12},
+      {0xda01ee641a708de9, 0xe80e6f4820cc9496},
+      {0x884134fe908658b2, 0x3109058d147fdcde},
+      {0xaa51823e34a7eede, 0xbd4b46f0599fd416},
+      {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91b},
+      {0x850fadc09923329e, 0x03e2cf6bc604ddb1},
+      {0xa6539930bf6bff45, 0x84db8346b786151d},
+      {0xcfe87f7cef46ff16, 0xe612641865679a64},
+      {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07f},
+      {0xa26da3999aef7749, 0xe3be5e330f38f09e},
+      {0xcb090c8001ab551c, 0x5cadf5bfd3072cc6},
+      {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f7},
+      {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afb},
+      {0xc646d63501a1511d, 0xb281e1fd541501b9},
+      {0xf7d88bc24209a565, 0x1f225a7ca91a4227},
+      {0x9ae757596946075f, 0x3375788de9b06959},
+      {0xc1a12d2fc3978937, 0x0052d6b1641c83af},
+      {0xf209787bb47d6b84, 0xc0678c5dbd23a49b},
+      {0x9745eb4d50ce6332, 0xf840b7ba963646e1},
+      {0xbd176620a501fbff, 0xb650e5a93bc3d899},
+      {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebf},
+      {0x93ba47c980e98cdf, 0xc66f336c36b10138},
+      {0xb8a8d9bbe123f017, 0xb80b0047445d4185},
+      {0xe6d3102ad96cec1d, 0xa60dc059157491e6},
+      {0x9043ea1ac7e41392, 0x87c89837ad68db30},
+      {0xb454e4a179dd1877, 0x29babe4598c311fc},
+      {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67b},
+      {0x8ce2529e2734bb1d, 0x1899e4a65f58660d},
+      {0xb01ae745b101e9e4, 0x5ec05dcff72e7f90},
+      {0xdc21a1171d42645d, 0x76707543f4fa1f74},
+      {0x899504ae72497eba, 0x6a06494a791c53a9},
+      {0xabfa45da0edbde69, 0x0487db9d17636893},
+      {0xd6f8d7509292d603, 0x45a9d2845d3c42b7},
+      {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3},
+      {0xa7f26836f282b732, 0x8e6cac7768d7141f},
+      {0xd1ef0244af2364ff, 0x3207d795430cd927},
+      {0x8335616aed761f1f, 0x7f44e6bd49e807b9},
+      {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a7},
+      {0xcd036837130890a1, 0x36dba887c37a8c10},
+      {0x802221226be55a64, 0xc2494954da2c978a},
+      {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6d},
+      {0xc83553c5c8965d3d, 0x6f92829494e5acc8},
+      {0xfa42a8b73abbf48c, 0xcb772339ba1f17fa},
+      {0x9c69a97284b578d7, 0xff2a760414536efc},
+      {0xc38413cf25e2d70d, 0xfef5138519684abb},
+      {0xf46518c2ef5b8cd1, 0x7eb258665fc25d6a},
+      {0x98bf2f79d5993802, 0xef2f773ffbd97a62},
+      {0xbeeefb584aff8603, 0xaafb550ffacfd8fb},
+      {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf39},
+      {0x952ab45cfa97a0b2, 0xdd945a747bf26184},
+      {0xba756174393d88df, 0x94f971119aeef9e5},
+      {0xe912b9d1478ceb17, 0x7a37cd5601aab85e},
+      {0x91abb422ccb812ee, 0xac62e055c10ab33b},
+      {0xb616a12b7fe617aa, 0x577b986b314d600a},
+      {0xe39c49765fdf9d94, 0xed5a7e85fda0b80c},
+      {0x8e41ade9fbebc27d, 0x14588f13be847308},
+      {0xb1d219647ae6b31c, 0x596eb2d8ae258fc9},
+      {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bc},
+      {0x8aec23d680043bee, 0x25de7bb9480d5855},
+      {0xada72ccc20054ae9, 0xaf561aa79a10ae6b},
+      {0xd910f7ff28069da4, 0x1b2ba1518094da05},
+      {0x87aa9aff79042286, 0x90fb44d2f05d0843},
+      {0xa99541bf57452b28, 0x353a1607ac744a54},
+      {0xd3fa922f2d1675f2, 0x42889b8997915ce9},
+      {0x847c9b5d7c2e09b7, 0x69956135febada12},
+      {0xa59bc234db398c25, 0x43fab9837e699096},
+      {0xcf02b2c21207ef2e, 0x94f967e45e03f4bc},
+      {0x8161afb94b44f57d, 0x1d1be0eebac278f6},
+      {0xa1ba1ba79e1632dc, 0x6462d92a69731733},
+      {0xca28a291859bbf93, 0x7d7b8f7503cfdcff},
+      {0xfcb2cb35e702af78, 0x5cda735244c3d43f},
+      {0x9defbf01b061adab, 0x3a0888136afa64a8},
+      {0xc56baec21c7a1916, 0x088aaa1845b8fdd1},
+      {0xf6c69a72a3989f5b, 0x8aad549e57273d46},
+      {0x9a3c2087a63f6399, 0x36ac54e2f678864c},
+      {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7de},
+      {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d6},
+      {0x969eb7c47859e743, 0x9f644ae5a4b1b326},
+      {0xbc4665b596706114, 0x873d5d9f0dde1fef},
+      {0xeb57ff22fc0c7959, 0xa90cb506d155a7eb},
+      {0x9316ff75dd87cbd8, 0x09a7f12442d588f3},
+      {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb30},
+      {0xe5d3ef282a242e81, 0x8f1668c8a86da5fb},
+      {0x8fa475791a569d10, 0xf96e017d694487bd},
+      {0xb38d92d760ec4455, 0x37c981dcc395a9ad},
+      {0xe070f78d3927556a, 0x85bbe253f47b1418},
+      {0x8c469ab843b89562, 0x93956d7478ccec8f},
+      {0xaf58416654a6babb, 0x387ac8d1970027b3},
+      {0xdb2e51bfe9d0696a, 0x06997b05fcc0319f},
+      {0x88fcf317f22241e2, 0x441fece3bdf81f04},
+      {0xab3c2fddeeaad25a, 0xd527e81cad7626c4},
+      {0xd60b3bd56a5586f1, 0x8a71e223d8d3b075},
+      {0x85c7056562757456, 0xf6872d5667844e4a},
+      {0xa738c6bebb12d16c, 0xb428f8ac016561dc},
+      {0xd106f86e69d785c7, 0xe13336d701beba53},
+      {0x82a45b450226b39c, 0xecc0024661173474},
+      {0xa34d721642b06084, 0x27f002d7f95d0191},
+      {0xcc20ce9bd35c78a5, 0x31ec038df7b441f5},
+      {0xff290242c83396ce, 0x7e67047175a15272},
+      {0x9f79a169bd203e41, 0x0f0062c6e984d387},
+      {0xc75809c42c684dd1, 0x52c07b78a3e60869},
+      {0xf92e0c3537826145, 0xa7709a56ccdf8a83},
+      {0x9bbcc7a142b17ccb, 0x88a66076400bb692},
+      {0xc2abf989935ddbfe, 0x6acff893d00ea436},
+      {0xf356f7ebf83552fe, 0x0583f6b8c4124d44},
+      {0x98165af37b2153de, 0xc3727a337a8b704b},
+      {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5d},
+      {0xeda2ee1c7064130c, 0x1162def06f79df74},
+      {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba9},
+      {0xb9a74a0637ce2ee1, 0x6d953e2bd7173693},
+      {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0438},
+      {0x910ab1d4db9914a0, 0x1d9c9892400a22a3},
+      {0xb54d5e4a127f59c8, 0x2503beb6d00cab4c},
+      {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e},
+      {0x8da471a9de737e24, 0x5ceaecfed289e5d3},
+      {0xb10d8e1456105dad, 0x7425a83e872c5f48},
+      {0xdd50f1996b947518, 0xd12f124e28f7771a},
+      {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa70},
+      {0xace73cbfdc0bfb7b, 0x636cc64d1001550c},
+      {0xd8210befd30efa5a, 0x3c47f7e05401aa4f},
+      {0x8714a775e3e95c78, 0x65acfaec34810a72},
+      {0xa8d9d1535ce3b396, 0x7f1839a741a14d0e},
+      {0xd31045a8341ca07c, 0x1ede48111209a051},
+      {0x83ea2b892091e44d, 0x934aed0aab460433},
+      {0xa4e4b66b68b65d60, 0xf81da84d56178540},
+      {0xce1de40642e3f4b9, 0x36251260ab9d668f},
+      {0x80d2ae83e9ce78f3, 0xc1d72b7c6b42601a},
+      {0xa1075a24e4421730, 0xb24cf65b8612f820},
+      {0xc94930ae1d529cfc, 0xdee033f26797b628},
+      {0xfb9b7cd9a4a7443c, 0x169840ef017da3b2},
+      {0x9d412e0806e88aa5, 0x8e1f289560ee864f},
+      {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e3},
+      {0xf5b5d7ec8acb58a2, 0xae10af696774b1dc},
+      {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef2a},
+      {0xbff610b0cc6edd3f, 0x17fd090a58d32af4},
+      {0xeff394dcff8a948e, 0xddfc4b4cef07f5b1},
+      {0x95f83d0a1fb69cd9, 0x4abdaf101564f98f},
+      {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f2},
+      {0xea53df5fd18d5513, 0x84c86189216dc5ee},
+      {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb5},
+      {0xb7118682dbb66a77, 0x3fbc8c33221dc2a2},
+      {0xe4d5e82392a40515, 0x0fabaf3feaa5334b},
+      {0x8f05b1163ba6832d, 0x29cb4d87f2a7400f},
+      {0xb2c71d5bca9023f8, 0x743e20e9ef511013},
+      {0xdf78e4b2bd342cf6, 0x914da9246b255417},
+      {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548f},
+      {0xae9672aba3d0c320, 0xa184ac2473b529b2},
+      {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741f},
+      {0x8865899617fb1871, 0x7e2fa67c7a658893},
+      {0xaa7eebfb9df9de8d, 0xddbb901b98feeab8},
+      {0xd51ea6fa85785631, 0x552a74227f3ea566},
+      {0x8533285c936b35de, 0xd53a88958f872760},
+      {0xa67ff273b8460356, 0x8a892abaf368f138},
+      {0xd01fef10a657842c, 0x2d2b7569b0432d86},
+      {0x8213f56a67f6b29b, 0x9c3b29620e29fc74},
+      {0xa298f2c501f45f42, 0x8349f3ba91b47b90},
+      {0xcb3f2f7642717713, 0x241c70a936219a74},
+      {0xfe0efb53d30dd4d7, 0xed238cd383aa0111},
+      {0x9ec95d1463e8a506, 0xf4363804324a40ab},
+      {0xc67bb4597ce2ce48, 0xb143c6053edcd0d6},
+      {0xf81aa16fdc1b81da, 0xdd94b7868e94050b},
+      {0x9b10a4e5e9913128, 0xca7cf2b4191c8327},
+      {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f1},
+      {0xf24a01a73cf2dccf, 0xbc633b39673c8ced},
+      {0x976e41088617ca01, 0xd5be0503e085d814},
+      {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e19},
+      {0xec9c459d51852ba2, 0xddf8e7d60ed1219f},
+      {0x93e1ab8252f33b45, 0xcabb90e5c942b504},
+      {0xb8da1662e7b00a17, 0x3d6a751f3b936244},
+      {0xe7109bfba19c0c9d, 0x0cc512670a783ad5},
+      {0x906a617d450187e2, 0x27fb2b80668b24c6},
+      {0xb484f9dc9641e9da, 0xb1f9f660802dedf7},
+      {0xe1a63853bbd26451, 0x5e7873f8a0396974},
+      {0x8d07e33455637eb2, 0xdb0b487b6423e1e9},
+      {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda63},
+      {0xdc5c5301c56b75f7, 0x7641a140cc7810fc},
+      {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9e},
+      {0xac2820d9623bf429, 0x546345fa9fbdcd45},
+      {0xd732290fbacaf133, 0xa97c177947ad4096},
+      {0x867f59a9d4bed6c0, 0x49ed8eabcccc485e},
+      {0xa81f301449ee8c70, 0x5c68f256bfff5a75},
+      {0xd226fc195c6a2f8c, 0x73832eec6fff3112},
+      {0x83585d8fd9c25db7, 0xc831fd53c5ff7eac},
+      {0xa42e74f3d032f525, 0xba3e7ca8b77f5e56},
+      {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35ec},
+      {0x80444b5e7aa7cf85, 0x7980d163cf5b81b4},
+      {0xa0555e361951c366, 0xd7e105bcc3326220},
+      {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa8},
+      {0xfa856334878fc150, 0xb14f98f6f0feb952},
+      {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d4},
+      {0xc3b8358109e84f07, 0x0a862f80ec4700c9},
+      {0xf4a642e14c6262c8, 0xcd27bb612758c0fb},
+      {0x98e7e9cccfbd7dbd, 0x8038d51cb897789d},
+      {0xbf21e44003acdd2c, 0xe0470a63e6bd56c4},
+      {0xeeea5d5004981478, 0x1858ccfce06cac75},
+      {0x95527a5202df0ccb, 0x0f37801e0c43ebc9},
+      {0xbaa718e68396cffd, 0xd30560258f54e6bb},
+      {0xe950df20247c83fd, 0x47c6b82ef32a206a},
+      {0x91d28b7416cdd27e, 0x4cdc331d57fa5442},
+      {0xb6472e511c81471d, 0xe0133fe4adf8e953},
+      {0xe3d8f9e563a198e5, 0x58180fddd97723a7},
+      {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7649},
+      {0xb201833b35d63f73, 0x2cd2cc6551e513db},
+      {0xde81e40a034bcf4f, 0xf8077f7ea65e58d2},
+      {0x8b112e86420f6191, 0xfb04afaf27faf783},
+      {0xadd57a27d29339f6, 0x79c5db9af1f9b564},
+      {0xd94ad8b1c7380874, 0x18375281ae7822bd},
+      {0x87cec76f1c830548, 0x8f2293910d0b15b6},
+      {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb23},
+      {0xd433179d9c8cb841, 0x5fa60692a46151ec},
+      {0x849feec281d7f328, 0xdbc7c41ba6bcd334},
+      {0xa5c7ea73224deff3, 0x12b9b522906c0801},
+      {0xcf39e50feae16bef, 0xd768226b34870a01},
+      {0x81842f29f2cce375, 0xe6a1158300d46641},
+      {0xa1e53af46f801c53, 0x60495ae3c1097fd1},
+      {0xca5e89b18b602368, 0x385bb19cb14bdfc5},
+      {0xfcf62c1dee382c42, 0x46729e03dd9ed7b6},
+      {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d2},
+      {0xc5a05277621be293, 0xc7098b7305241886},
+      { 0xf70867153aa2db38,
+        0xb8cbee4fc66d1ea8 }
+#else
+      {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b},
+      {0xce5d73ff402d98e3, 0xfb0a3d212dc81290},
+      {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f},
+      {0x86a8d39ef77164bc, 0xae5dff9c02033198},
+      {0xd98ddaee19068c76, 0x3badd624dd9b0958},
+      {0xafbd2350644eeacf, 0xe5d1929ef90898fb},
+      {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2},
+      {0xe55990879ddcaabd, 0xcc420a6a101d0516},
+      {0xb94470938fa89bce, 0xf808e40e8d5b3e6a},
+      {0x95a8637627989aad, 0xdde7001379a44aa9},
+      {0xf1c90080baf72cb1, 0x5324c68b12dd6339},
+      {0xc350000000000000, 0x0000000000000000},
+      {0x9dc5ada82b70b59d, 0xf020000000000000},
+      {0xfee50b7025c36a08, 0x02f236d04753d5b5},
+      {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87},
+      {0xa6539930bf6bff45, 0x84db8346b786151d},
+      {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3},
+      {0xd910f7ff28069da4, 0x1b2ba1518094da05},
+      {0xaf58416654a6babb, 0x387ac8d1970027b3},
+      {0x8da471a9de737e24, 0x5ceaecfed289e5d3},
+      {0xe4d5e82392a40515, 0x0fabaf3feaa5334b},
+      {0xb8da1662e7b00a17, 0x3d6a751f3b936244},
+      { 0x95527a5202df0ccb,
+        0x0f37801e0c43ebc9 }
+#endif
+    };
+
+#if FMT_USE_FULL_CACHE_DRAGONBOX
+    return pow10_significands[k - float_info<double>::min_k];
+#else
+    static constexpr const uint64_t powers_of_5_64[] = {
+        0x0000000000000001, 0x0000000000000005, 0x0000000000000019,
+        0x000000000000007d, 0x0000000000000271, 0x0000000000000c35,
+        0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1,
+        0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd,
+        0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9,
+        0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5,
+        0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631,
+        0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed,
+        0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9};
+
+    static const int compression_ratio = 27;
+
+    // Compute base index.
+    int cache_index = (k - float_info<double>::min_k) / compression_ratio;
+    int kb = cache_index * compression_ratio + float_info<double>::min_k;
+    int offset = k - kb;
+
+    // Get base cache.
+    uint128_fallback base_cache = pow10_significands[cache_index];
+    if (offset == 0) return base_cache;
+
+    // Compute the required amount of bit-shift.
+    int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset;
+    FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected");
+
+    // Try to recover the real cache.
+    uint64_t pow5 = powers_of_5_64[offset];
+    uint128_fallback recovered_cache = umul128(base_cache.high(), pow5);
+    uint128_fallback middle_low = umul128(base_cache.low(), pow5);
+
+    recovered_cache += middle_low.high();
+
+    uint64_t high_to_middle = recovered_cache.high() << (64 - alpha);
+    uint64_t middle_to_low = recovered_cache.low() << (64 - alpha);
+
+    recovered_cache =
+        uint128_fallback{(recovered_cache.low() >> alpha) | high_to_middle,
+                         ((middle_low.low() >> alpha) | middle_to_low)};
+    FMT_ASSERT(recovered_cache.low() + 1 != 0, "");
+    return {recovered_cache.high(), recovered_cache.low() + 1};
+#endif
+  }
+
+  struct compute_mul_result {
+    carrier_uint result;
+    bool is_integer;
+  };
+  struct compute_mul_parity_result {
+    bool parity;
+    bool is_integer;
+  };
+
+  static compute_mul_result compute_mul(
+      carrier_uint u, const cache_entry_type& cache) noexcept {
+    auto r = umul192_upper128(u, cache);
+    return {r.high(), r.low() == 0};
+  }
+
+  static uint32_t compute_delta(cache_entry_type const& cache,
+                                int beta) noexcept {
+    return static_cast<uint32_t>(cache.high() >> (64 - 1 - beta));
+  }
+
+  static compute_mul_parity_result compute_mul_parity(
+      carrier_uint two_f, const cache_entry_type& cache, int beta) noexcept {
+    FMT_ASSERT(beta >= 1, "");
+    FMT_ASSERT(beta < 64, "");
+
+    auto r = umul192_lower128(two_f, cache);
+    return {((r.high() >> (64 - beta)) & 1) != 0,
+            ((r.high() << beta) | (r.low() >> (64 - beta))) == 0};
+  }
+
+  static carrier_uint compute_left_endpoint_for_shorter_interval_case(
+      const cache_entry_type& cache, int beta) noexcept {
+    return (cache.high() -
+            (cache.high() >> (num_significand_bits<double>() + 2))) >>
+           (64 - num_significand_bits<double>() - 1 - beta);
+  }
+
+  static carrier_uint compute_right_endpoint_for_shorter_interval_case(
+      const cache_entry_type& cache, int beta) noexcept {
+    return (cache.high() +
+            (cache.high() >> (num_significand_bits<double>() + 1))) >>
+           (64 - num_significand_bits<double>() - 1 - beta);
+  }
+
+  static carrier_uint compute_round_up_for_shorter_interval_case(
+      const cache_entry_type& cache, int beta) noexcept {
+    return ((cache.high() >> (64 - num_significand_bits<double>() - 2 - beta)) +
+            1) /
+           2;
+  }
+};
+
+// Various integer checks
+template <class T>
+bool is_left_endpoint_integer_shorter_interval(int exponent) noexcept {
+  const int case_shorter_interval_left_endpoint_lower_threshold = 2;
+  const int case_shorter_interval_left_endpoint_upper_threshold = 3;
+  return exponent >= case_shorter_interval_left_endpoint_lower_threshold &&
+         exponent <= case_shorter_interval_left_endpoint_upper_threshold;
+}
+
+// Remove trailing zeros from n and return the number of zeros removed (float)
+FMT_INLINE int remove_trailing_zeros(uint32_t& n) noexcept {
+  FMT_ASSERT(n != 0, "");
+  const uint32_t mod_inv_5 = 0xcccccccd;
+  const uint32_t mod_inv_25 = mod_inv_5 * mod_inv_5;
+
+  int s = 0;
+  while (true) {
+    auto q = rotr(n * mod_inv_25, 2);
+    if (q > max_value<uint32_t>() / 100) break;
+    n = q;
+    s += 2;
+  }
+  auto q = rotr(n * mod_inv_5, 1);
+  if (q <= max_value<uint32_t>() / 10) {
+    n = q;
+    s |= 1;
+  }
+
+  return s;
+}
+
+// Removes trailing zeros and returns the number of zeros removed (double)
+FMT_INLINE int remove_trailing_zeros(uint64_t& n) noexcept {
+  FMT_ASSERT(n != 0, "");
+
+  // This magic number is ceil(2^90 / 10^8).
+  constexpr uint64_t magic_number = 12379400392853802749ull;
+  auto nm = umul128(n, magic_number);
+
+  // Is n is divisible by 10^8?
+  if ((nm.high() & ((1ull << (90 - 64)) - 1)) == 0 && nm.low() < magic_number) {
+    // If yes, work with the quotient.
+    auto n32 = static_cast<uint32_t>(nm.high() >> (90 - 64));
+
+    const uint32_t mod_inv_5 = 0xcccccccd;
+    const uint32_t mod_inv_25 = mod_inv_5 * mod_inv_5;
+
+    int s = 8;
+    while (true) {
+      auto q = rotr(n32 * mod_inv_25, 2);
+      if (q > max_value<uint32_t>() / 100) break;
+      n32 = q;
+      s += 2;
+    }
+    auto q = rotr(n32 * mod_inv_5, 1);
+    if (q <= max_value<uint32_t>() / 10) {
+      n32 = q;
+      s |= 1;
+    }
+
+    n = n32;
+    return s;
+  }
+
+  // If n is not divisible by 10^8, work with n itself.
+  const uint64_t mod_inv_5 = 0xcccccccccccccccd;
+  const uint64_t mod_inv_25 = mod_inv_5 * mod_inv_5;
+
+  int s = 0;
+  while (true) {
+    auto q = rotr(n * mod_inv_25, 2);
+    if (q > max_value<uint64_t>() / 100) break;
+    n = q;
+    s += 2;
+  }
+  auto q = rotr(n * mod_inv_5, 1);
+  if (q <= max_value<uint64_t>() / 10) {
+    n = q;
+    s |= 1;
+  }
+
+  return s;
+}
+
+// The main algorithm for shorter interval case
+template <class T>
+FMT_INLINE decimal_fp<T> shorter_interval_case(int exponent) noexcept {
+  decimal_fp<T> ret_value;
+  // Compute k and beta
+  const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent);
+  const int beta = exponent + floor_log2_pow10(-minus_k);
+
+  // Compute xi and zi
+  using cache_entry_type = typename cache_accessor<T>::cache_entry_type;
+  const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k);
+
+  auto xi = cache_accessor<T>::compute_left_endpoint_for_shorter_interval_case(
+      cache, beta);
+  auto zi = cache_accessor<T>::compute_right_endpoint_for_shorter_interval_case(
+      cache, beta);
+
+  // If the left endpoint is not an integer, increase it
+  if (!is_left_endpoint_integer_shorter_interval<T>(exponent)) ++xi;
+
+  // Try bigger divisor
+  ret_value.significand = zi / 10;
+
+  // If succeed, remove trailing zeros if necessary and return
+  if (ret_value.significand * 10 >= xi) {
+    ret_value.exponent = minus_k + 1;
+    ret_value.exponent += remove_trailing_zeros(ret_value.significand);
+    return ret_value;
+  }
+
+  // Otherwise, compute the round-up of y
+  ret_value.significand =
+      cache_accessor<T>::compute_round_up_for_shorter_interval_case(cache,
+                                                                    beta);
+  ret_value.exponent = minus_k;
+
+  // When tie occurs, choose one of them according to the rule
+  if (exponent >= float_info<T>::shorter_interval_tie_lower_threshold &&
+      exponent <= float_info<T>::shorter_interval_tie_upper_threshold) {
+    ret_value.significand = ret_value.significand % 2 == 0
+                                ? ret_value.significand
+                                : ret_value.significand - 1;
+  } else if (ret_value.significand < xi) {
+    ++ret_value.significand;
+  }
+  return ret_value;
+}
+
+template <typename T> decimal_fp<T> to_decimal(T x) noexcept {
+  // Step 1: integer promotion & Schubfach multiplier calculation.
+
+  using carrier_uint = typename float_info<T>::carrier_uint;
+  using cache_entry_type = typename cache_accessor<T>::cache_entry_type;
+  auto br = bit_cast<carrier_uint>(x);
+
+  // Extract significand bits and exponent bits.
+  const carrier_uint significand_mask =
+      (static_cast<carrier_uint>(1) << num_significand_bits<T>()) - 1;
+  carrier_uint significand = (br & significand_mask);
+  int exponent =
+      static_cast<int>((br & exponent_mask<T>()) >> num_significand_bits<T>());
+
+  if (exponent != 0) {  // Check if normal.
+    exponent -= exponent_bias<T>() + num_significand_bits<T>();
+
+    // Shorter interval case; proceed like Schubfach.
+    // In fact, when exponent == 1 and significand == 0, the interval is
+    // regular. However, it can be shown that the end-results are anyway same.
+    if (significand == 0) return shorter_interval_case<T>(exponent);
+
+    significand |= (static_cast<carrier_uint>(1) << num_significand_bits<T>());
+  } else {
+    // Subnormal case; the interval is always regular.
+    if (significand == 0) return {0, 0};
+    exponent =
+        std::numeric_limits<T>::min_exponent - num_significand_bits<T>() - 1;
+  }
+
+  const bool include_left_endpoint = (significand % 2 == 0);
+  const bool include_right_endpoint = include_left_endpoint;
+
+  // Compute k and beta.
+  const int minus_k = floor_log10_pow2(exponent) - float_info<T>::kappa;
+  const cache_entry_type cache = cache_accessor<T>::get_cached_power(-minus_k);
+  const int beta = exponent + floor_log2_pow10(-minus_k);
+
+  // Compute zi and deltai.
+  // 10^kappa <= deltai < 10^(kappa + 1)
+  const uint32_t deltai = cache_accessor<T>::compute_delta(cache, beta);
+  const carrier_uint two_fc = significand << 1;
+
+  // For the case of binary32, the result of integer check is not correct for
+  // 29711844 * 2^-82
+  // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18
+  // and 29711844 * 2^-81
+  // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17,
+  // and they are the unique counterexamples. However, since 29711844 is even,
+  // this does not cause any problem for the endpoints calculations; it can only
+  // cause a problem when we need to perform integer check for the center.
+  // Fortunately, with these inputs, that branch is never executed, so we are
+  // fine.
+  const typename cache_accessor<T>::compute_mul_result z_mul =
+      cache_accessor<T>::compute_mul((two_fc | 1) << beta, cache);
+
+  // Step 2: Try larger divisor; remove trailing zeros if necessary.
+
+  // Using an upper bound on zi, we might be able to optimize the division
+  // better than the compiler; we are computing zi / big_divisor here.
+  decimal_fp<T> ret_value;
+  ret_value.significand = divide_by_10_to_kappa_plus_1(z_mul.result);
+  uint32_t r = static_cast<uint32_t>(z_mul.result - float_info<T>::big_divisor *
+                                                        ret_value.significand);
+
+  if (r < deltai) {
+    // Exclude the right endpoint if necessary.
+    if (r == 0 && (z_mul.is_integer & !include_right_endpoint)) {
+      --ret_value.significand;
+      r = float_info<T>::big_divisor;
+      goto small_divisor_case_label;
+    }
+  } else if (r > deltai) {
+    goto small_divisor_case_label;
+  } else {
+    // r == deltai; compare fractional parts.
+    const typename cache_accessor<T>::compute_mul_parity_result x_mul =
+        cache_accessor<T>::compute_mul_parity(two_fc - 1, cache, beta);
+
+    if (!(x_mul.parity | (x_mul.is_integer & include_left_endpoint)))
+      goto small_divisor_case_label;
+  }
+  ret_value.exponent = minus_k + float_info<T>::kappa + 1;
+
+  // We may need to remove trailing zeros.
+  ret_value.exponent += remove_trailing_zeros(ret_value.significand);
+  return ret_value;
+
+  // Step 3: Find the significand with the smaller divisor.
+
+small_divisor_case_label:
+  ret_value.significand *= 10;
+  ret_value.exponent = minus_k + float_info<T>::kappa;
+
+  uint32_t dist = r - (deltai / 2) + (float_info<T>::small_divisor / 2);
+  const bool approx_y_parity =
+      ((dist ^ (float_info<T>::small_divisor / 2)) & 1) != 0;
+
+  // Is dist divisible by 10^kappa?
+  const bool divisible_by_small_divisor =
+      check_divisibility_and_divide_by_pow10<float_info<T>::kappa>(dist);
+
+  // Add dist / 10^kappa to the significand.
+  ret_value.significand += dist;
+
+  if (!divisible_by_small_divisor) return ret_value;
+
+  // Check z^(f) >= epsilon^(f).
+  // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1,
+  // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f).
+  // Since there are only 2 possibilities, we only need to care about the
+  // parity. Also, zi and r should have the same parity since the divisor
+  // is an even number.
+  const auto y_mul = cache_accessor<T>::compute_mul_parity(two_fc, cache, beta);
+
+  // If z^(f) >= epsilon^(f), we might have a tie when z^(f) == epsilon^(f),
+  // or equivalently, when y is an integer.
+  if (y_mul.parity != approx_y_parity)
+    --ret_value.significand;
+  else if (y_mul.is_integer & (ret_value.significand % 2 != 0))
+    --ret_value.significand;
+  return ret_value;
+}
+}  // namespace dragonbox
+
+#ifdef _MSC_VER
+FMT_FUNC auto fmt_snprintf(char* buf, size_t size, const char* fmt, ...)
+    -> int {
+  auto args = va_list();
+  va_start(args, fmt);
+  int result = vsnprintf_s(buf, size, _TRUNCATE, fmt, args);
+  va_end(args);
+  return result;
+}
+#endif
+}  // namespace detail
+
+template <> struct formatter<detail::bigint> {
+  FMT_CONSTEXPR auto parse(format_parse_context& ctx)
+      -> format_parse_context::iterator {
+    return ctx.begin();
+  }
+
+  template <typename FormatContext>
+  auto format(const detail::bigint& n, FormatContext& ctx) const ->
+      typename FormatContext::iterator {
+    auto out = ctx.out();
+    bool first = true;
+    for (auto i = n.bigits_.size(); i > 0; --i) {
+      auto value = n.bigits_[i - 1u];
+      if (first) {
+        out = format_to(out, FMT_STRING("{:x}"), value);
+        first = false;
+        continue;
+      }
+      out = format_to(out, FMT_STRING("{:08x}"), value);
+    }
+    if (n.exp_ > 0)
+      out = format_to(out, FMT_STRING("p{}"),
+                      n.exp_ * detail::bigint::bigit_bits);
+    return out;
+  }
+};
+
+FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) {
+  for_each_codepoint(s, [this](uint32_t cp, string_view) {
+    if (cp == invalid_code_point) FMT_THROW(std::runtime_error("invalid utf8"));
+    if (cp <= 0xFFFF) {
+      buffer_.push_back(static_cast<wchar_t>(cp));
+    } else {
+      cp -= 0x10000;
+      buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10)));
+      buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF)));
+    }
+    return true;
+  });
+  buffer_.push_back(0);
+}
+
+FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code,
+                                  const char* message) noexcept {
+  FMT_TRY {
+    auto ec = std::error_code(error_code, std::generic_category());
+    write(std::back_inserter(out), std::system_error(ec, message).what());
+    return;
+  }
+  FMT_CATCH(...) {}
+  format_error_code(out, error_code, message);
+}
+
+FMT_FUNC void report_system_error(int error_code,
+                                  const char* message) noexcept {
+  report_error(format_system_error, error_code, message);
+}
+
+FMT_FUNC std::string vformat(string_view fmt, format_args args) {
+  // Don't optimize the "{}" case to keep the binary size small and because it
+  // can be better optimized in fmt::format anyway.
+  auto buffer = memory_buffer();
+  detail::vformat_to(buffer, fmt, args);
+  return to_string(buffer);
+}
+
+namespace detail {
+#ifdef _WIN32
+using dword = conditional_t<sizeof(long) == 4, unsigned long, unsigned>;
+extern "C" __declspec(dllimport) int __stdcall WriteConsoleW(  //
+    void*, const void*, dword, dword*, void*);
+
+FMT_FUNC bool write_console(std::FILE* f, string_view text) {
+  auto fd = _fileno(f);
+  if (_isatty(fd)) {
+    detail::utf8_to_utf16 u16(string_view(text.data(), text.size()));
+    auto written = detail::dword();
+    if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)),
+                              u16.c_str(), static_cast<uint32_t>(u16.size()),
+                              &written, nullptr)) {
+      return true;
+    }
+  }
+  // We return false if the file descriptor was not TTY, or it was but
+  // SetConsoleW failed which can happen if the output has been redirected to
+  // NUL. In both cases when we return false, we should attempt to do regular
+  // write via fwrite or std::ostream::write.
+  return false;
+}
+#endif
+
+FMT_FUNC void print(std::FILE* f, string_view text) {
+#ifdef _WIN32
+  if (write_console(f, text)) return;
+#endif
+  detail::fwrite_fully(text.data(), 1, text.size(), f);
+}
+}  // namespace detail
+
+FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) {
+  memory_buffer buffer;
+  detail::vformat_to(buffer, format_str, args);
+  detail::print(f, {buffer.data(), buffer.size()});
+}
+
+#ifdef _WIN32
+// Print assuming legacy (non-Unicode) encoding.
+FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str,
+                                      format_args args) {
+  memory_buffer buffer;
+  detail::vformat_to(buffer, format_str,
+                     basic_format_args<buffer_context<char>>(args));
+  fwrite_fully(buffer.data(), 1, buffer.size(), f);
+}
+#endif
+
+FMT_FUNC void vprint(string_view format_str, format_args args) {
+  vprint(stdout, format_str, args);
+}
+
+namespace detail {
+
+struct singleton {
+  unsigned char upper;
+  unsigned char lower_count;
+};
+
+inline auto is_printable(uint16_t x, const singleton* singletons,
+                         size_t singletons_size,
+                         const unsigned char* singleton_lowers,
+                         const unsigned char* normal, size_t normal_size)
+    -> bool {
+  auto upper = x >> 8;
+  auto lower_start = 0;
+  for (size_t i = 0; i < singletons_size; ++i) {
+    auto s = singletons[i];
+    auto lower_end = lower_start + s.lower_count;
+    if (upper < s.upper) break;
+    if (upper == s.upper) {
+      for (auto j = lower_start; j < lower_end; ++j) {
+        if (singleton_lowers[j] == (x & 0xff)) return false;
+      }
+    }
+    lower_start = lower_end;
+  }
+
+  auto xsigned = static_cast<int>(x);
+  auto current = true;
+  for (size_t i = 0; i < normal_size; ++i) {
+    auto v = static_cast<int>(normal[i]);
+    auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v;
+    xsigned -= len;
+    if (xsigned < 0) break;
+    current = !current;
+  }
+  return current;
+}
+
+// This code is generated by support/printable.py.
+FMT_FUNC auto is_printable(uint32_t cp) -> bool {
+  static constexpr singleton singletons0[] = {
+      {0x00, 1},  {0x03, 5},  {0x05, 6},  {0x06, 3},  {0x07, 6},  {0x08, 8},
+      {0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13},
+      {0x0f, 4},  {0x10, 3},  {0x12, 18}, {0x13, 9},  {0x16, 1},  {0x17, 5},
+      {0x18, 2},  {0x19, 3},  {0x1a, 7},  {0x1c, 2},  {0x1d, 1},  {0x1f, 22},
+      {0x20, 3},  {0x2b, 3},  {0x2c, 2},  {0x2d, 11}, {0x2e, 1},  {0x30, 3},
+      {0x31, 2},  {0x32, 1},  {0xa7, 2},  {0xa9, 2},  {0xaa, 4},  {0xab, 8},
+      {0xfa, 2},  {0xfb, 5},  {0xfd, 4},  {0xfe, 3},  {0xff, 9},
+  };
+  static constexpr unsigned char singletons0_lower[] = {
+      0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90,
+      0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f,
+      0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1,
+      0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04,
+      0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d,
+      0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf,
+      0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
+      0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d,
+      0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d,
+      0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d,
+      0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5,
+      0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7,
+      0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49,
+      0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7,
+      0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7,
+      0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e,
+      0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16,
+      0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e,
+      0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f,
+      0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,
+      0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0,
+      0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,
+      0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91,
+      0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7,
+      0xfe, 0xff,
+  };
+  static constexpr singleton singletons1[] = {
+      {0x00, 6},  {0x01, 1}, {0x03, 1},  {0x04, 2}, {0x08, 8},  {0x09, 2},
+      {0x0a, 5},  {0x0b, 2}, {0x0e, 4},  {0x10, 1}, {0x11, 2},  {0x12, 5},
+      {0x13, 17}, {0x14, 1}, {0x15, 2},  {0x17, 2}, {0x19, 13}, {0x1c, 5},
+      {0x1d, 8},  {0x24, 1}, {0x6a, 3},  {0x6b, 2}, {0xbc, 2},  {0xd1, 2},
+      {0xd4, 12}, {0xd5, 9}, {0xd6, 2},  {0xd7, 2}, {0xda, 1},  {0xe0, 5},
+      {0xe1, 2},  {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2},  {0xf9, 2},
+      {0xfa, 2},  {0xfb, 1},
+  };
+  static constexpr unsigned char singletons1_lower[] = {
+      0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07,
+      0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36,
+      0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87,
+      0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
+      0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b,
+      0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9,
+      0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66,
+      0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27,
+      0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc,
+      0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7,
+      0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6,
+      0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c,
+      0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66,
+      0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0,
+      0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93,
+  };
+  static constexpr unsigned char normal0[] = {
+      0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04,
+      0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0,
+      0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01,
+      0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03,
+      0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03,
+      0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a,
+      0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15,
+      0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f,
+      0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80,
+      0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07,
+      0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06,
+      0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04,
+      0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac,
+      0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c,
+      0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11,
+      0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c,
+      0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b,
+      0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6,
+      0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03,
+      0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80,
+      0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06,
+      0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c,
+      0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17,
+      0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80,
+      0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80,
+      0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d,
+  };
+  static constexpr unsigned char normal1[] = {
+      0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f,
+      0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e,
+      0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04,
+      0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09,
+      0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16,
+      0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f,
+      0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36,
+      0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33,
+      0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08,
+      0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e,
+      0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41,
+      0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03,
+      0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22,
+      0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04,
+      0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45,
+      0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03,
+      0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81,
+      0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75,
+      0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1,
+      0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a,
+      0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11,
+      0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09,
+      0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89,
+      0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6,
+      0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09,
+      0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50,
+      0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05,
+      0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83,
+      0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05,
+      0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80,
+      0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80,
+      0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07,
+      0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e,
+      0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07,
+      0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06,
+  };
+  auto lower = static_cast<uint16_t>(cp);
+  if (cp < 0x10000) {
+    return is_printable(lower, singletons0,
+                        sizeof(singletons0) / sizeof(*singletons0),
+                        singletons0_lower, normal0, sizeof(normal0));
+  }
+  if (cp < 0x20000) {
+    return is_printable(lower, singletons1,
+                        sizeof(singletons1) / sizeof(*singletons1),
+                        singletons1_lower, normal1, sizeof(normal1));
+  }
+  if (0x2a6de <= cp && cp < 0x2a700) return false;
+  if (0x2b735 <= cp && cp < 0x2b740) return false;
+  if (0x2b81e <= cp && cp < 0x2b820) return false;
+  if (0x2cea2 <= cp && cp < 0x2ceb0) return false;
+  if (0x2ebe1 <= cp && cp < 0x2f800) return false;
+  if (0x2fa1e <= cp && cp < 0x30000) return false;
+  if (0x3134b <= cp && cp < 0xe0100) return false;
+  if (0xe01f0 <= cp && cp < 0x110000) return false;
+  return cp < 0x110000;
+}
+
+}  // namespace detail
+
+FMT_END_NAMESPACE
+
+#endif  // FMT_FORMAT_INL_H_
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/format.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format.h
similarity index 62%
rename from wpiutil/src/main/native/fmtlib/include/fmt/format.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format.h
index ee69651..7c607db 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/format.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/format.h
@@ -1,33 +1,33 @@
 /*
- Formatting library for C++
+  Formatting library for C++
 
- Copyright (c) 2012 - present, Victor Zverovich
+  Copyright (c) 2012 - present, Victor Zverovich
 
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
+  Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
 
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
 
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
- --- Optional exception to the license ---
+  --- Optional exception to the license ---
 
- As an exception, if, as a result of your compiling your source code, portions
- of this Software are embedded into a machine-executable object form of such
- source code, you may redistribute such embedded portions in such object form
- without including the above copyright and permission notices.
+  As an exception, if, as a result of your compiling your source code, portions
+  of this Software are embedded into a machine-executable object form of such
+  source code, you may redistribute such embedded portions in such object form
+  without including the above copyright and permission notices.
  */
 
 #ifndef FMT_FORMAT_H_
@@ -35,11 +35,11 @@
 
 #include <cmath>         // std::signbit
 #include <cstdint>       // uint32_t
+#include <cstring>       // std::memcpy
 #include <limits>        // std::numeric_limits
 #include <memory>        // std::uninitialized_copy
 #include <stdexcept>     // std::runtime_error
 #include <system_error>  // std::system_error
-#include <utility>       // std::swap
 
 #ifdef __cpp_lib_bit_cast
 #  include <bit>  // std::bitcast
@@ -71,7 +71,7 @@
 #  define FMT_NOINLINE
 #endif
 
-#if FMT_MSC_VER
+#if FMT_MSC_VERSION
 #  define FMT_MSC_DEFAULT = default
 #else
 #  define FMT_MSC_DEFAULT
@@ -79,7 +79,7 @@
 
 #ifndef FMT_THROW
 #  if FMT_EXCEPTIONS
-#    if FMT_MSC_VER || FMT_NVCC
+#    if FMT_MSC_VERSION || defined(__NVCC__)
 FMT_BEGIN_NAMESPACE
 namespace detail {
 template <typename Exception> inline void do_throw(const Exception& x) {
@@ -118,17 +118,10 @@
 #  endif
 #endif
 
-// Workaround broken [[deprecated]] in the Intel, PGI and NVCC compilers.
-#if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC
-#  define FMT_DEPRECATED_ALIAS
-#else
-#  define FMT_DEPRECATED_ALIAS FMT_DEPRECATED
-#endif
-
 #ifndef FMT_USE_USER_DEFINED_LITERALS
 // EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
 #  if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
-       FMT_MSC_VER >= 1900) &&                                         \
+       FMT_MSC_VERSION >= 1900) &&                                     \
       (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
 #    define FMT_USE_USER_DEFINED_LITERALS 1
 #  else
@@ -146,7 +139,7 @@
 
 // __builtin_clz is broken in clang with Microsoft CodeGen:
 // https://github.com/fmtlib/fmt/issues/519.
-#if !FMT_MSC_VER
+#if !FMT_MSC_VERSION
 #  if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
 #    define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
 #  endif
@@ -158,22 +151,25 @@
 // __builtin_ctz is broken in Intel Compiler Classic on Windows:
 // https://github.com/fmtlib/fmt/issues/2510.
 #ifndef __ICL
-#  if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION
+#  if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
+      defined(__NVCOMPILER)
 #    define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
 #  endif
-#  if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
+#  if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
+      FMT_ICC_VERSION || defined(__NVCOMPILER)
 #    define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
 #  endif
 #endif
 
-#if FMT_MSC_VER
+#if FMT_MSC_VERSION
 #  include <intrin.h>  // _BitScanReverse[64], _BitScanForward[64], _umul128
 #endif
 
 // Some compilers masquerade as both MSVC and GCC-likes or otherwise support
 // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
 // MSVC intrinsics if the clz and clzll builtins are not available.
-#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(FMT_BUILTIN_CTZLL)
+#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
+    !defined(FMT_BUILTIN_CTZLL)
 FMT_BEGIN_NAMESPACE
 namespace detail {
 // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
@@ -243,15 +239,28 @@
 FMT_END_NAMESPACE
 #endif
 
-#ifdef FMT_HEADER_ONLY
-#  define FMT_HEADER_ONLY_CONSTEXPR20 FMT_CONSTEXPR20
-#else
-#  define FMT_HEADER_ONLY_CONSTEXPR20
-#endif
-
 FMT_BEGIN_NAMESPACE
 namespace detail {
 
+FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) {
+  ignore_unused(condition);
+#ifdef FMT_FUZZ
+  if (condition) throw std::runtime_error("fuzzing limit reached");
+#endif
+}
+
+template <typename CharT, CharT... C> struct string_literal {
+  static constexpr CharT value[sizeof...(C)] = {C...};
+  constexpr operator basic_string_view<CharT>() const {
+    return {value, sizeof...(C)};
+  }
+};
+
+#if FMT_CPLUSPLUS < 201703L
+template <typename CharT, CharT... C>
+constexpr CharT string_literal<CharT, C...>::value[sizeof...(C)];
+#endif
+
 template <typename Streambuf> class formatbuf : public Streambuf {
  private:
   using char_type = typename Streambuf::char_type;
@@ -284,14 +293,14 @@
 };
 
 // Implementation of std::bit_cast for pre-C++20.
-template <typename To, typename From>
+template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) == sizeof(From))>
 FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To {
-  static_assert(sizeof(To) == sizeof(From), "size mismatch");
 #ifdef __cpp_lib_bit_cast
   if (is_constant_evaluated()) return std::bit_cast<To>(from);
 #endif
   auto to = To();
-  std::memcpy(&to, &from, sizeof(to));
+  // The cast suppresses a bogus -Wclass-memaccess on GCC.
+  std::memcpy(static_cast<void*>(&to), &from, sizeof(to));
   return to;
 }
 
@@ -310,29 +319,117 @@
 #endif
 }
 
-// A fallback implementation of uintptr_t for systems that lack it.
-struct fallback_uintptr {
-  unsigned char value[sizeof(void*)];
+class uint128_fallback {
+ private:
+  uint64_t lo_, hi_;
 
-  fallback_uintptr() = default;
-  explicit fallback_uintptr(const void* p) {
-    *this = bit_cast<fallback_uintptr>(p);
-    if (const_check(is_big_endian())) {
-      for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
-        std::swap(value[i], value[j]);
+  friend uint128_fallback umul128(uint64_t x, uint64_t y) noexcept;
+
+ public:
+  constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
+  constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {}
+
+  constexpr uint64_t high() const noexcept { return hi_; }
+  constexpr uint64_t low() const noexcept { return lo_; }
+
+  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
+  constexpr explicit operator T() const {
+    return static_cast<T>(lo_);
+  }
+
+  friend constexpr auto operator==(const uint128_fallback& lhs,
+                                   const uint128_fallback& rhs) -> bool {
+    return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
+  }
+  friend constexpr auto operator!=(const uint128_fallback& lhs,
+                                   const uint128_fallback& rhs) -> bool {
+    return !(lhs == rhs);
+  }
+  friend constexpr auto operator>(const uint128_fallback& lhs,
+                                  const uint128_fallback& rhs) -> bool {
+    return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
+  }
+  friend constexpr auto operator|(const uint128_fallback& lhs,
+                                  const uint128_fallback& rhs)
+      -> uint128_fallback {
+    return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
+  }
+  friend constexpr auto operator&(const uint128_fallback& lhs,
+                                  const uint128_fallback& rhs)
+      -> uint128_fallback {
+    return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
+  }
+  friend auto operator+(const uint128_fallback& lhs,
+                        const uint128_fallback& rhs) -> uint128_fallback {
+    auto result = uint128_fallback(lhs);
+    result += rhs;
+    return result;
+  }
+  friend auto operator*(const uint128_fallback& lhs, uint32_t rhs)
+      -> uint128_fallback {
+    FMT_ASSERT(lhs.hi_ == 0, "");
+    uint64_t hi = (lhs.lo_ >> 32) * rhs;
+    uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
+    uint64_t new_lo = (hi << 32) + lo;
+    return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
+  }
+  friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
+      -> uint128_fallback {
+    return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
+  }
+  FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback {
+    if (shift == 64) return {0, hi_};
+    if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64);
+    return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
+  }
+  FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback {
+    if (shift == 64) return {lo_, 0};
+    if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64);
+    return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};
+  }
+  FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& {
+    return *this = *this >> shift;
+  }
+  FMT_CONSTEXPR void operator+=(uint128_fallback n) {
+    uint64_t new_lo = lo_ + n.lo_;
+    uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0);
+    FMT_ASSERT(new_hi >= hi_, "");
+    lo_ = new_lo;
+    hi_ = new_hi;
+  }
+
+  FMT_CONSTEXPR20 uint128_fallback& operator+=(uint64_t n) noexcept {
+    if (is_constant_evaluated()) {
+      lo_ += n;
+      hi_ += (lo_ < n ? 1 : 0);
+      return *this;
     }
+#if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
+    unsigned long long carry;
+    lo_ = __builtin_addcll(lo_, n, 0, &carry);
+    hi_ += carry;
+#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
+    unsigned long long result;
+    auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result);
+    lo_ = result;
+    hi_ += carry;
+#elif defined(_MSC_VER) && defined(_M_X64)
+    auto carry = _addcarry_u64(0, lo_, n, &lo_);
+    _addcarry_u64(carry, hi_, 0, &hi_);
+#else
+    lo_ += n;
+    hi_ += (lo_ < n ? 1 : 0);
+#endif
+    return *this;
   }
 };
+
+using uint128_t = conditional_t<FMT_USE_INT128, uint128_opt, uint128_fallback>;
+
 #ifdef UINTPTR_MAX
 using uintptr_t = ::uintptr_t;
-inline auto to_uintptr(const void* p) -> uintptr_t {
-  return bit_cast<uintptr_t>(p);
-}
 #else
-using uintptr_t = fallback_uintptr;
-inline auto to_uintptr(const void* p) -> fallback_uintptr {
-  return fallback_uintptr(p);
-}
+using uintptr_t = uint128_t;
 #endif
 
 // Returns the largest possible value for type T. Same as
@@ -344,16 +441,31 @@
   return std::numeric_limits<T>::digits;
 }
 // std::numeric_limits<T>::digits may return 0 for 128-bit ints.
-template <> constexpr auto num_bits<int128_t>() -> int { return 128; }
+template <> constexpr auto num_bits<int128_opt>() -> int { return 128; }
 template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
-template <> constexpr auto num_bits<fallback_uintptr>() -> int {
-  return static_cast<int>(sizeof(void*) *
-                          std::numeric_limits<unsigned char>::digits);
+
+// A heterogeneous bit_cast used for converting 96-bit long double to uint128_t
+// and 128-bit pointers to uint128_fallback.
+template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) > sizeof(From))>
+inline auto bit_cast(const From& from) -> To {
+  constexpr auto size = static_cast<int>(sizeof(From) / sizeof(unsigned));
+  struct data_t {
+    unsigned value[static_cast<unsigned>(size)];
+  } data = bit_cast<data_t>(from);
+  auto result = To();
+  if (const_check(is_big_endian())) {
+    for (int i = 0; i < size; ++i)
+      result = (result << num_bits<unsigned>()) | data.value[i];
+  } else {
+    for (int i = size - 1; i >= 0; --i)
+      result = (result << num_bits<unsigned>()) | data.value[i];
+  }
+  return result;
 }
 
 FMT_INLINE void assume(bool condition) {
   (void)condition;
-#if FMT_HAS_BUILTIN(__builtin_assume)
+#if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
   __builtin_assume(condition);
 #endif
 }
@@ -495,19 +607,23 @@
   constexpr const int shiftc[] = {0, 18, 12, 6, 0};
   constexpr const int shifte[] = {0, 6, 4, 2, 0};
 
-  int len = code_point_length(s);
-  const char* next = s + len;
+  int len = code_point_length_impl(*s);
+  // Compute the pointer to the next character early so that the next
+  // iteration can start working on the next character. Neither Clang
+  // nor GCC figure out this reordering on their own.
+  const char* next = s + len + !len;
+
+  using uchar = unsigned char;
 
   // Assume a four-byte character and load four bytes. Unused bits are
   // shifted out.
-  *c = uint32_t(s[0] & masks[len]) << 18;
-  *c |= uint32_t(s[1] & 0x3f) << 12;
-  *c |= uint32_t(s[2] & 0x3f) << 6;
-  *c |= uint32_t(s[3] & 0x3f) << 0;
+  *c = uint32_t(uchar(s[0]) & masks[len]) << 18;
+  *c |= uint32_t(uchar(s[1]) & 0x3f) << 12;
+  *c |= uint32_t(uchar(s[2]) & 0x3f) << 6;
+  *c |= uint32_t(uchar(s[3]) & 0x3f) << 0;
   *c >>= shiftc[len];
 
   // Accumulate the various error conditions.
-  using uchar = unsigned char;
   *e = (*c < mins[len]) << 6;       // non-canonical encoding
   *e |= ((*c >> 11) == 0x1b) << 7;  // surrogate half?
   *e |= (*c > 0x10FFFF) << 8;       // out of range?
@@ -531,8 +647,8 @@
     auto error = 0;
     auto end = utf8_decode(buf_ptr, &cp, &error);
     bool result = f(error ? invalid_code_point : cp,
-                    string_view(ptr, to_unsigned(end - buf_ptr)));
-    return result ? end : nullptr;
+                    string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr)));
+    return result ? (error ? buf_ptr + 1 : end) : nullptr;
   };
   auto p = s.data();
   const size_t block_size = 4;  // utf8_decode always reads blocks of 4 chars.
@@ -595,8 +711,8 @@
 }
 
 inline auto compute_width(basic_string_view<char8_type> s) -> size_t {
-  return compute_width(basic_string_view<char>(
-      reinterpret_cast<const char*>(s.data()), s.size()));
+  return compute_width(
+      string_view(reinterpret_cast<const char*>(s.data()), s.size()));
 }
 
 template <typename Char>
@@ -606,9 +722,8 @@
 }
 
 // Calculates the index of the nth code point in a UTF-8 string.
-inline auto code_point_index(basic_string_view<char8_type> s, size_t n)
-    -> size_t {
-  const char8_type* data = s.data();
+inline auto code_point_index(string_view s, size_t n) -> size_t {
+  const char* data = s.data();
   size_t num_code_points = 0;
   for (size_t i = 0, size = s.size(); i != size; ++i) {
     if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i;
@@ -616,11 +731,38 @@
   return s.size();
 }
 
+inline auto code_point_index(basic_string_view<char8_type> s, size_t n)
+    -> size_t {
+  return code_point_index(
+      string_view(reinterpret_cast<const char*>(s.data()), s.size()), n);
+}
+
+#ifndef FMT_USE_FLOAT128
+#  ifdef __SIZEOF_FLOAT128__
+#    define FMT_USE_FLOAT128 1
+#  else
+#    define FMT_USE_FLOAT128 0
+#  endif
+#endif
+#if FMT_USE_FLOAT128
+using float128 = __float128;
+#else
+using float128 = void;
+#endif
+template <typename T> using is_float128 = std::is_same<T, float128>;
+
+template <typename T>
+using is_floating_point =
+    bool_constant<std::is_floating_point<T>::value || is_float128<T>::value>;
+
 template <typename T, bool = std::is_floating_point<T>::value>
 struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&
                                      sizeof(T) <= sizeof(double)> {};
 template <typename T> struct is_fast_float<T, false> : std::false_type {};
 
+template <typename T>
+using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
+
 #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
 #  define FMT_USE_FULL_CACHE_DRAGONBOX 0
 #endif
@@ -698,9 +840,7 @@
       const Allocator& alloc = Allocator())
       : alloc_(alloc) {
     this->set(store_, SIZE);
-    if (detail::is_constant_evaluated()) {
-      detail::fill_n(store_, SIZE, T{});
-    }
+    if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T());
   }
   FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); }
 
@@ -712,18 +852,14 @@
     size_t size = other.size(), capacity = other.capacity();
     if (data == other.store_) {
       this->set(store_, capacity);
-      if (detail::is_constant_evaluated()) {
-        detail::copy_str<T>(other.store_, other.store_ + size,
-                            detail::make_checked(store_, capacity));
-      } else {
-        std::uninitialized_copy(other.store_, other.store_ + size,
-                                detail::make_checked(store_, capacity));
-      }
+      detail::copy_str<T>(other.store_, other.store_ + size,
+                          detail::make_checked(store_, capacity));
     } else {
       this->set(data, capacity);
       // Set pointer to the inline array so that delete is not called
       // when deallocating.
       other.set(other.store_, 0);
+      other.clear();
     }
     this->resize(size);
   }
@@ -735,8 +871,7 @@
     of the other object to it.
     \endrst
    */
-  FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other)
-      FMT_NOEXCEPT {
+  FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) noexcept {
     move(other);
   }
 
@@ -745,8 +880,7 @@
     Moves the content of the other ``basic_memory_buffer`` object to this one.
     \endrst
    */
-  auto operator=(basic_memory_buffer&& other) FMT_NOEXCEPT
-      -> basic_memory_buffer& {
+  auto operator=(basic_memory_buffer&& other) noexcept -> basic_memory_buffer& {
     FMT_ASSERT(this != &other, "");
     deallocate();
     move(other);
@@ -776,9 +910,7 @@
 template <typename T, size_t SIZE, typename Allocator>
 FMT_CONSTEXPR20 void basic_memory_buffer<T, SIZE, Allocator>::grow(
     size_t size) {
-#ifdef FMT_FUZZ
-  if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much");
-#endif
+  detail::abort_fuzzing_if(size > 5000);
   const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
   size_t old_capacity = this->capacity();
   size_t new_capacity = old_capacity + old_capacity / 2;
@@ -806,8 +938,11 @@
 };
 
 namespace detail {
+#ifdef _WIN32
+FMT_API bool write_console(std::FILE* f, string_view text);
+#endif
 FMT_API void print(std::FILE*, string_view);
-}
+}  // namespace detail
 
 /** A formatting error such as invalid format string. */
 FMT_CLASS_API
@@ -820,39 +955,17 @@
   format_error& operator=(const format_error&) = default;
   format_error(format_error&&) = default;
   format_error& operator=(format_error&&) = default;
-  ~format_error() FMT_NOEXCEPT override FMT_MSC_DEFAULT;
+  ~format_error() noexcept override FMT_MSC_DEFAULT;
 };
 
-/**
-  \rst
-  Constructs a `~fmt::format_arg_store` object that contains references
-  to arguments and can be implicitly converted to `~fmt::format_args`.
-  If ``fmt`` is a compile-time string then `make_args_checked` checks
-  its validity at compile time.
-  \endrst
- */
-template <typename... Args, typename S, typename Char = char_t<S>>
-FMT_INLINE auto make_args_checked(const S& fmt,
-                                  const remove_reference_t<Args>&... args)
-    -> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> {
-  static_assert(
-      detail::count<(
-              std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
-              std::is_reference<Args>::value)...>() == 0,
-      "passing views as lvalues is disallowed");
-  detail::check_format_string<Args...>(fmt);
-  return {args...};
-}
-
-// compile-time support
 namespace detail_exported {
-#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+#if FMT_USE_NONTYPE_TEMPLATE_ARGS
 template <typename Char, size_t N> struct fixed_string {
   constexpr fixed_string(const Char (&str)[N]) {
     detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str),
                                                str + N, data);
   }
-  Char data[N]{};
+  Char data[N] = {};
 };
 #endif
 
@@ -874,30 +987,31 @@
 FMT_BEGIN_DETAIL_NAMESPACE
 
 template <typename T> struct is_integral : std::is_integral<T> {};
-template <> struct is_integral<int128_t> : std::true_type {};
+template <> struct is_integral<int128_opt> : std::true_type {};
 template <> struct is_integral<uint128_t> : std::true_type {};
 
 template <typename T>
 using is_signed =
     std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
-                                     std::is_same<T, int128_t>::value>;
+                                     std::is_same<T, int128_opt>::value>;
 
 // Returns true if value is negative, false otherwise.
 // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
 template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
-FMT_CONSTEXPR auto is_negative(T value) -> bool {
+constexpr auto is_negative(T value) -> bool {
   return value < 0;
 }
 template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
-FMT_CONSTEXPR auto is_negative(T) -> bool {
+constexpr auto is_negative(T) -> bool {
   return false;
 }
 
-template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
-FMT_CONSTEXPR auto is_supported_floating_point(T) -> uint16_t {
-  return (std::is_same<T, float>::value && FMT_USE_FLOAT) ||
-         (std::is_same<T, double>::value && FMT_USE_DOUBLE) ||
-         (std::is_same<T, long double>::value && FMT_USE_LONG_DOUBLE);
+template <typename T>
+FMT_CONSTEXPR auto is_supported_floating_point(T) -> bool {
+  if (std::is_same<T, float>()) return FMT_USE_FLOAT;
+  if (std::is_same<T, double>()) return FMT_USE_DOUBLE;
+  if (std::is_same<T, long double>()) return FMT_USE_LONG_DOUBLE;
+  return true;
 }
 
 // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
@@ -948,7 +1062,7 @@
   }
 }
 #if FMT_USE_INT128
-FMT_CONSTEXPR inline auto count_digits(uint128_t n) -> int {
+FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int {
   return count_digits_fallback(n);
 }
 #endif
@@ -989,7 +1103,7 @@
 template <int BITS, typename UInt>
 FMT_CONSTEXPR auto count_digits(UInt n) -> int {
 #ifdef FMT_BUILTIN_CLZ
-  if (num_bits<UInt>() == 32)
+  if (!is_constant_evaluated() && num_bits<UInt>() == 32)
     return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1;
 #endif
   // Lambda avoids unreachable code warnings from NVHPC.
@@ -1002,8 +1116,6 @@
   }(n);
 }
 
-template <> auto count_digits<4>(detail::fallback_uintptr n) -> int;
-
 #ifdef FMT_BUILTIN_CLZ
 // It is a separate function rather than a part of count_digits to workaround
 // the lack of static constexpr in constexpr functions.
@@ -1039,15 +1151,11 @@
   return count_digits_fallback(n);
 }
 
-template <typename Int> constexpr auto digits10() FMT_NOEXCEPT -> int {
+template <typename Int> constexpr auto digits10() noexcept -> int {
   return std::numeric_limits<Int>::digits10;
 }
-template <> constexpr auto digits10<int128_t>() FMT_NOEXCEPT -> int {
-  return 38;
-}
-template <> constexpr auto digits10<uint128_t>() FMT_NOEXCEPT -> int {
-  return 38;
-}
+template <> constexpr auto digits10<int128_opt>() noexcept -> int { return 38; }
+template <> constexpr auto digits10<uint128_t>() noexcept -> int { return 38; }
 
 template <typename Char> struct thousands_sep_result {
   std::string grouping;
@@ -1127,7 +1235,7 @@
 
 template <typename Char, typename UInt, typename Iterator,
           FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
-inline auto format_decimal(Iterator out, UInt value, int size)
+FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size)
     -> format_decimal_result<Iterator> {
   // Buffer is large enough to hold all digits (digits10 + 1).
   Char buffer[digits10<UInt>() + 1];
@@ -1142,35 +1250,13 @@
   Char* end = buffer;
   do {
     const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
-    unsigned digit = (value & ((1 << BASE_BITS) - 1));
+    unsigned digit = static_cast<unsigned>(value & ((1 << BASE_BITS) - 1));
     *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
                                                 : digits[digit]);
   } while ((value >>= BASE_BITS) != 0);
   return end;
 }
 
-template <unsigned BASE_BITS, typename Char>
-auto format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits,
-                 bool = false) -> Char* {
-  auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
-  int start = (num_digits + char_digits - 1) / char_digits - 1;
-  if (int start_digits = num_digits % char_digits) {
-    unsigned value = n.value[start--];
-    buffer = format_uint<BASE_BITS>(buffer, value, start_digits);
-  }
-  for (; start >= 0; --start) {
-    unsigned value = n.value[start];
-    buffer += char_digits;
-    auto p = buffer;
-    for (int i = 0; i < char_digits; ++i) {
-      unsigned digit = (value & ((1 << BASE_BITS) - 1));
-      *--p = static_cast<Char>("0123456789abcdef"[digit]);
-      value >>= BASE_BITS;
-    }
-  }
-  return buffer;
-}
-
 template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
 inline auto format_uint(It out, UInt value, int num_digits, bool upper = false)
     -> It {
@@ -1200,58 +1286,45 @@
 namespace dragonbox {
 
 // Type-specific information that Dragonbox uses.
-template <class T> struct float_info;
+template <typename T, typename Enable = void> struct float_info;
 
 template <> struct float_info<float> {
   using carrier_uint = uint32_t;
-  static const int significand_bits = 23;
   static const int exponent_bits = 8;
-  static const int min_exponent = -126;
-  static const int max_exponent = 127;
-  static const int exponent_bias = -127;
-  static const int decimal_digits = 9;
   static const int kappa = 1;
   static const int big_divisor = 100;
   static const int small_divisor = 10;
   static const int min_k = -31;
   static const int max_k = 46;
-  static const int cache_bits = 64;
-  static const int divisibility_check_by_5_threshold = 39;
-  static const int case_fc_pm_half_lower_threshold = -1;
-  static const int case_fc_pm_half_upper_threshold = 6;
-  static const int case_fc_lower_threshold = -2;
-  static const int case_fc_upper_threshold = 6;
-  static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
-  static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
   static const int shorter_interval_tie_lower_threshold = -35;
   static const int shorter_interval_tie_upper_threshold = -35;
-  static const int max_trailing_zeros = 7;
 };
 
 template <> struct float_info<double> {
   using carrier_uint = uint64_t;
-  static const int significand_bits = 52;
   static const int exponent_bits = 11;
-  static const int min_exponent = -1022;
-  static const int max_exponent = 1023;
-  static const int exponent_bias = -1023;
-  static const int decimal_digits = 17;
   static const int kappa = 2;
   static const int big_divisor = 1000;
   static const int small_divisor = 100;
   static const int min_k = -292;
   static const int max_k = 326;
-  static const int cache_bits = 128;
-  static const int divisibility_check_by_5_threshold = 86;
-  static const int case_fc_pm_half_lower_threshold = -2;
-  static const int case_fc_pm_half_upper_threshold = 9;
-  static const int case_fc_lower_threshold = -4;
-  static const int case_fc_upper_threshold = 9;
-  static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
-  static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
   static const int shorter_interval_tie_lower_threshold = -77;
   static const int shorter_interval_tie_upper_threshold = -77;
-  static const int max_trailing_zeros = 16;
+};
+
+// An 80- or 128-bit floating point number.
+template <typename T>
+struct float_info<T, enable_if_t<std::numeric_limits<T>::digits == 64 ||
+                                 std::numeric_limits<T>::digits == 113 ||
+                                 is_float128<T>::value>> {
+  using carrier_uint = detail::uint128_t;
+  static const int exponent_bits = 15;
+};
+
+// A double-double floating point number.
+template <typename T>
+struct float_info<T, enable_if_t<is_double_double<T>::value>> {
+  using carrier_uint = detail::uint128_t;
 };
 
 template <typename T> struct decimal_fp {
@@ -1260,16 +1333,35 @@
   int exponent;
 };
 
-template <typename T>
-FMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp<T>;
+template <typename T> FMT_API auto to_decimal(T x) noexcept -> decimal_fp<T>;
 }  // namespace dragonbox
 
-template <typename T>
+// Returns true iff Float has the implicit bit which is not stored.
+template <typename Float> constexpr bool has_implicit_bit() {
+  // An 80-bit FP number has a 64-bit significand an no implicit bit.
+  return std::numeric_limits<Float>::digits != 64;
+}
+
+// Returns the number of significand bits stored in Float. The implicit bit is
+// not counted since it is not stored.
+template <typename Float> constexpr int num_significand_bits() {
+  // std::numeric_limits may not support __float128.
+  return is_float128<Float>() ? 112
+                              : (std::numeric_limits<Float>::digits -
+                                 (has_implicit_bit<Float>() ? 1 : 0));
+}
+
+template <typename Float>
 constexpr auto exponent_mask() ->
-    typename dragonbox::float_info<T>::carrier_uint {
-  using uint = typename dragonbox::float_info<T>::carrier_uint;
-  return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1)
-         << dragonbox::float_info<T>::significand_bits;
+    typename dragonbox::float_info<Float>::carrier_uint {
+  using uint = typename dragonbox::float_info<Float>::carrier_uint;
+  return ((uint(1) << dragonbox::float_info<Float>::exponent_bits) - 1)
+         << num_significand_bits<Float>();
+}
+template <typename Float> constexpr auto exponent_bias() -> int {
+  // std::numeric_limits may not support __float128.
+  return is_float128<Float>() ? 16383
+                              : std::numeric_limits<Float>::max_exponent - 1;
 }
 
 // Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
@@ -1294,21 +1386,251 @@
   return it;
 }
 
-template <typename T>
-FMT_HEADER_ONLY_CONSTEXPR20 auto format_float(T value, int precision,
-                                              float_specs specs,
-                                              buffer<char>& buf) -> int;
+// A floating-point number f * pow(2, e) where F is an unsigned type.
+template <typename F> struct basic_fp {
+  F f;
+  int e;
 
-// Formats a floating-point number with snprintf.
-template <typename T>
-auto snprintf_float(T value, int precision, float_specs specs,
-                    buffer<char>& buf) -> int;
+  static constexpr const int num_significand_bits =
+      static_cast<int>(sizeof(F) * num_bits<unsigned char>());
 
-template <typename T> constexpr auto promote_float(T value) -> T {
+  constexpr basic_fp() : f(0), e(0) {}
+  constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
+
+  // Constructs fp from an IEEE754 floating-point number.
+  template <typename Float> FMT_CONSTEXPR basic_fp(Float n) { assign(n); }
+
+  // Assigns n to this and return true iff predecessor is closer than successor.
+  template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)>
+  FMT_CONSTEXPR auto assign(Float n) -> bool {
+    static_assert(std::numeric_limits<Float>::digits <= 113, "unsupported FP");
+    // Assume Float is in the format [sign][exponent][significand].
+    using carrier_uint = typename dragonbox::float_info<Float>::carrier_uint;
+    const auto num_float_significand_bits =
+        detail::num_significand_bits<Float>();
+    const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
+    const auto significand_mask = implicit_bit - 1;
+    auto u = bit_cast<carrier_uint>(n);
+    f = static_cast<F>(u & significand_mask);
+    auto biased_e = static_cast<int>((u & exponent_mask<Float>()) >>
+                                     num_float_significand_bits);
+    // The predecessor is closer if n is a normalized power of 2 (f == 0)
+    // other than the smallest normalized number (biased_e > 1).
+    auto is_predecessor_closer = f == 0 && biased_e > 1;
+    if (biased_e == 0)
+      biased_e = 1;  // Subnormals use biased exponent 1 (min exponent).
+    else if (has_implicit_bit<Float>())
+      f += static_cast<F>(implicit_bit);
+    e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
+    if (!has_implicit_bit<Float>()) ++e;
+    return is_predecessor_closer;
+  }
+
+  template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)>
+  FMT_CONSTEXPR auto assign(Float n) -> bool {
+    static_assert(std::numeric_limits<double>::is_iec559, "unsupported FP");
+    return assign(static_cast<double>(n));
+  }
+};
+
+using fp = basic_fp<unsigned long long>;
+
+// Normalizes the value converted from double and multiplied by (1 << SHIFT).
+template <int SHIFT = 0, typename F>
+FMT_CONSTEXPR basic_fp<F> normalize(basic_fp<F> value) {
+  // Handle subnormals.
+  const auto implicit_bit = F(1) << num_significand_bits<double>();
+  const auto shifted_implicit_bit = implicit_bit << SHIFT;
+  while ((value.f & shifted_implicit_bit) == 0) {
+    value.f <<= 1;
+    --value.e;
+  }
+  // Subtract 1 to account for hidden bit.
+  const auto offset = basic_fp<F>::num_significand_bits -
+                      num_significand_bits<double>() - SHIFT - 1;
+  value.f <<= offset;
+  value.e -= offset;
   return value;
 }
-constexpr auto promote_float(float value) -> double {
-  return static_cast<double>(value);
+
+// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
+FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
+#if FMT_USE_INT128
+  auto product = static_cast<__uint128_t>(lhs) * rhs;
+  auto f = static_cast<uint64_t>(product >> 64);
+  return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
+#else
+  // Multiply 32-bit parts of significands.
+  uint64_t mask = (1ULL << 32) - 1;
+  uint64_t a = lhs >> 32, b = lhs & mask;
+  uint64_t c = rhs >> 32, d = rhs & mask;
+  uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
+  // Compute mid 64-bit of result and round.
+  uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
+  return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
+#endif
+}
+
+FMT_CONSTEXPR inline fp operator*(fp x, fp y) {
+  return {multiply(x.f, y.f), x.e + y.e + 64};
+}
+
+template <typename T = void> struct basic_data {
+  // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340.
+  // These are generated by support/compute-powers.py.
+  static constexpr uint64_t pow10_significands[87] = {
+      0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76,
+      0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df,
+      0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c,
+      0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5,
+      0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57,
+      0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7,
+      0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e,
+      0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996,
+      0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126,
+      0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053,
+      0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f,
+      0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b,
+      0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06,
+      0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb,
+      0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000,
+      0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984,
+      0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068,
+      0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8,
+      0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758,
+      0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85,
+      0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d,
+      0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25,
+      0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2,
+      0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a,
+      0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410,
+      0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129,
+      0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85,
+      0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841,
+      0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b,
+  };
+
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
+#  pragma GCC diagnostic push
+#  pragma GCC diagnostic ignored "-Wnarrowing"
+#endif
+  // Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding
+  // to significands above.
+  static constexpr int16_t pow10_exponents[87] = {
+      -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954,
+      -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,  -688, -661,
+      -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,  -422,  -396, -369,
+      -343,  -316,  -289,  -263,  -236,  -210,  -183,  -157,  -130,  -103, -77,
+      -50,   -24,   3,     30,    56,    83,    109,   136,   162,   189,  216,
+      242,   269,   295,   322,   348,   375,   402,   428,   455,   481,  508,
+      534,   561,   588,   614,   641,   667,   694,   720,   747,   774,  800,
+      827,   853,   880,   907,   933,   960,   986,   1013,  1039,  1066};
+#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
+#  pragma GCC diagnostic pop
+#endif
+
+  static constexpr uint64_t power_of_10_64[20] = {
+      1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL),
+      10000000000000000000ULL};
+};
+
+#if FMT_CPLUSPLUS < 201703L
+template <typename T> constexpr uint64_t basic_data<T>::pow10_significands[];
+template <typename T> constexpr int16_t basic_data<T>::pow10_exponents[];
+template <typename T> constexpr uint64_t basic_data<T>::power_of_10_64[];
+#endif
+
+// This is a struct rather than an alias to avoid shadowing warnings in gcc.
+struct data : basic_data<> {};
+
+// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its
+// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`.
+FMT_CONSTEXPR inline fp get_cached_power(int min_exponent,
+                                         int& pow10_exponent) {
+  const int shift = 32;
+  // log10(2) = 0x0.4d104d427de7fbcc...
+  const int64_t significand = 0x4d104d427de7fbcc;
+  int index = static_cast<int>(
+      ((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) +
+       ((int64_t(1) << shift) - 1))  // ceil
+      >> 32                          // arithmetic shift
+  );
+  // Decimal exponent of the first (smallest) cached power of 10.
+  const int first_dec_exp = -348;
+  // Difference between 2 consecutive decimal exponents in cached powers of 10.
+  const int dec_exp_step = 8;
+  index = (index - first_dec_exp - 1) / dec_exp_step + 1;
+  pow10_exponent = first_dec_exp + index * dec_exp_step;
+  // Using *(x + index) instead of x[index] avoids an issue with some compilers
+  // using the EDG frontend (e.g. nvhpc/22.3 in C++17 mode).
+  return {*(data::pow10_significands + index),
+          *(data::pow10_exponents + index)};
+}
+
+#ifndef _MSC_VER
+#  define FMT_SNPRINTF snprintf
+#else
+FMT_API auto fmt_snprintf(char* buf, size_t size, const char* fmt, ...) -> int;
+#  define FMT_SNPRINTF fmt_snprintf
+#endif  // _MSC_VER
+
+// Formats a floating-point number with snprintf using the hexfloat format.
+template <typename T>
+auto snprintf_float(T value, int precision, float_specs specs,
+                    buffer<char>& buf) -> int {
+  // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail.
+  FMT_ASSERT(buf.capacity() > buf.size(), "empty buffer");
+  FMT_ASSERT(specs.format == float_format::hex, "");
+  static_assert(!std::is_same<T, float>::value, "");
+
+  // Build the format string.
+  char format[7];  // The longest format is "%#.*Le".
+  char* format_ptr = format;
+  *format_ptr++ = '%';
+  if (specs.showpoint) *format_ptr++ = '#';
+  if (precision >= 0) {
+    *format_ptr++ = '.';
+    *format_ptr++ = '*';
+  }
+  if (std::is_same<T, long double>()) *format_ptr++ = 'L';
+  *format_ptr++ = specs.upper ? 'A' : 'a';
+  *format_ptr = '\0';
+
+  // Format using snprintf.
+  auto offset = buf.size();
+  for (;;) {
+    auto begin = buf.data() + offset;
+    auto capacity = buf.capacity() - offset;
+    abort_fuzzing_if(precision > 100000);
+    // Suppress the warning about a nonliteral format string.
+    // Cannot use auto because of a bug in MinGW (#1532).
+    int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF;
+    int result = precision >= 0
+                     ? snprintf_ptr(begin, capacity, format, precision, value)
+                     : snprintf_ptr(begin, capacity, format, value);
+    if (result < 0) {
+      // The buffer will grow exponentially.
+      buf.try_reserve(buf.capacity() + 1);
+      continue;
+    }
+    auto size = to_unsigned(result);
+    // Size equal to capacity means that the last character was truncated.
+    if (size < capacity) {
+      buf.try_resize(size + offset);
+      return 0;
+    }
+    buf.try_reserve(size + offset + 1);  // Add 1 for the terminating '\0'.
+  }
+}
+
+template <typename T>
+using convert_float_result =
+    conditional_t<std::is_same<T, float>::value || sizeof(T) == sizeof(double),
+                  double, T>;
+
+template <typename T>
+constexpr auto convert_float(T value) -> convert_float_result<T> {
+  return static_cast<convert_float_result<T>>(value);
 }
 
 template <typename OutputIt, typename Char>
@@ -1377,11 +1699,172 @@
                : base_iterator(out, write(reserve(out, size)));
 }
 
+// Returns true iff the code point cp is printable.
+FMT_API auto is_printable(uint32_t cp) -> bool;
+
+inline auto needs_escape(uint32_t cp) -> bool {
+  return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' ||
+         !is_printable(cp);
+}
+
+template <typename Char> struct find_escape_result {
+  const Char* begin;
+  const Char* end;
+  uint32_t cp;
+};
+
+template <typename Char>
+using make_unsigned_char =
+    typename conditional_t<std::is_integral<Char>::value,
+                           std::make_unsigned<Char>,
+                           type_identity<uint32_t>>::type;
+
+template <typename Char>
+auto find_escape(const Char* begin, const Char* end)
+    -> find_escape_result<Char> {
+  for (; begin != end; ++begin) {
+    uint32_t cp = static_cast<make_unsigned_char<Char>>(*begin);
+    if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue;
+    if (needs_escape(cp)) return {begin, begin + 1, cp};
+  }
+  return {begin, nullptr, 0};
+}
+
+inline auto find_escape(const char* begin, const char* end)
+    -> find_escape_result<char> {
+  if (!is_utf8()) return find_escape<char>(begin, end);
+  auto result = find_escape_result<char>{end, nullptr, 0};
+  for_each_codepoint(string_view(begin, to_unsigned(end - begin)),
+                     [&](uint32_t cp, string_view sv) {
+                       if (needs_escape(cp)) {
+                         result = {sv.begin(), sv.end(), cp};
+                         return false;
+                       }
+                       return true;
+                     });
+  return result;
+}
+
+#define FMT_STRING_IMPL(s, base, explicit)                                    \
+  [] {                                                                        \
+    /* Use the hidden visibility as a workaround for a GCC bug (#1973). */    \
+    /* Use a macro-like name to avoid shadowing warnings. */                  \
+    struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base {              \
+      using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \
+      FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit                                 \
+      operator fmt::basic_string_view<char_type>() const {                    \
+        return fmt::detail_exported::compile_string_to_view<char_type>(s);    \
+      }                                                                       \
+    };                                                                        \
+    return FMT_COMPILE_STRING();                                              \
+  }()
+
+/**
+  \rst
+  Constructs a compile-time format string from a string literal *s*.
+
+  **Example**::
+
+    // A compile-time error because 'd' is an invalid specifier for strings.
+    std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
+  \endrst
+ */
+#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, )
+
+template <size_t width, typename Char, typename OutputIt>
+auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt {
+  *out++ = static_cast<Char>('\\');
+  *out++ = static_cast<Char>(prefix);
+  Char buf[width];
+  fill_n(buf, width, static_cast<Char>('0'));
+  format_uint<4>(buf, cp, width);
+  return copy_str<Char>(buf, buf + width, out);
+}
+
+template <typename OutputIt, typename Char>
+auto write_escaped_cp(OutputIt out, const find_escape_result<Char>& escape)
+    -> OutputIt {
+  auto c = static_cast<Char>(escape.cp);
+  switch (escape.cp) {
+  case '\n':
+    *out++ = static_cast<Char>('\\');
+    c = static_cast<Char>('n');
+    break;
+  case '\r':
+    *out++ = static_cast<Char>('\\');
+    c = static_cast<Char>('r');
+    break;
+  case '\t':
+    *out++ = static_cast<Char>('\\');
+    c = static_cast<Char>('t');
+    break;
+  case '"':
+    FMT_FALLTHROUGH;
+  case '\'':
+    FMT_FALLTHROUGH;
+  case '\\':
+    *out++ = static_cast<Char>('\\');
+    break;
+  default:
+    if (is_utf8()) {
+      if (escape.cp < 0x100) {
+        return write_codepoint<2, Char>(out, 'x', escape.cp);
+      }
+      if (escape.cp < 0x10000) {
+        return write_codepoint<4, Char>(out, 'u', escape.cp);
+      }
+      if (escape.cp < 0x110000) {
+        return write_codepoint<8, Char>(out, 'U', escape.cp);
+      }
+    }
+    for (Char escape_char : basic_string_view<Char>(
+             escape.begin, to_unsigned(escape.end - escape.begin))) {
+      out = write_codepoint<2, Char>(out, 'x',
+                                     static_cast<uint32_t>(escape_char) & 0xFF);
+    }
+    return out;
+  }
+  *out++ = c;
+  return out;
+}
+
+template <typename Char, typename OutputIt>
+auto write_escaped_string(OutputIt out, basic_string_view<Char> str)
+    -> OutputIt {
+  *out++ = static_cast<Char>('"');
+  auto begin = str.begin(), end = str.end();
+  do {
+    auto escape = find_escape(begin, end);
+    out = copy_str<Char>(begin, escape.begin, out);
+    begin = escape.end;
+    if (!begin) break;
+    out = write_escaped_cp<OutputIt, Char>(out, escape);
+  } while (begin != end);
+  *out++ = static_cast<Char>('"');
+  return out;
+}
+
+template <typename Char, typename OutputIt>
+auto write_escaped_char(OutputIt out, Char v) -> OutputIt {
+  *out++ = static_cast<Char>('\'');
+  if ((needs_escape(static_cast<uint32_t>(v)) && v != static_cast<Char>('"')) ||
+      v == static_cast<Char>('\'')) {
+    out = write_escaped_cp(
+        out, find_escape_result<Char>{&v, &v + 1, static_cast<uint32_t>(v)});
+  } else {
+    *out++ = v;
+  }
+  *out++ = static_cast<Char>('\'');
+  return out;
+}
+
 template <typename Char, typename OutputIt>
 FMT_CONSTEXPR auto write_char(OutputIt out, Char value,
                               const basic_format_specs<Char>& specs)
     -> OutputIt {
+  bool is_debug = specs.type == presentation_type::debug;
   return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
+    if (is_debug) return write_escaped_char(it, value);
     *it++ = value;
     return it;
   });
@@ -1519,7 +2002,10 @@
                               grouping.count_separators(num_digits));
   return write_padded<align::right>(
       out, specs, size, size, [&](reserve_iterator<OutputIt> it) {
-        if (prefix != 0) *it++ = static_cast<Char>(prefix);
+        if (prefix != 0) {
+          char sign = static_cast<char>(prefix);
+          *it++ = static_cast<Char>(sign);
+        }
         return grouping.apply(it, string_view(digits, to_unsigned(num_digits)));
       });
 }
@@ -1647,6 +2133,46 @@
   return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);
 }
 
+// An output iterator that counts the number of objects written to it and
+// discards them.
+class counting_iterator {
+ private:
+  size_t count_;
+
+ public:
+  using iterator_category = std::output_iterator_tag;
+  using difference_type = std::ptrdiff_t;
+  using pointer = void;
+  using reference = void;
+  FMT_UNCHECKED_ITERATOR(counting_iterator);
+
+  struct value_type {
+    template <typename T> FMT_CONSTEXPR void operator=(const T&) {}
+  };
+
+  FMT_CONSTEXPR counting_iterator() : count_(0) {}
+
+  FMT_CONSTEXPR size_t count() const { return count_; }
+
+  FMT_CONSTEXPR counting_iterator& operator++() {
+    ++count_;
+    return *this;
+  }
+  FMT_CONSTEXPR counting_iterator operator++(int) {
+    auto it = *this;
+    ++*this;
+    return it;
+  }
+
+  FMT_CONSTEXPR friend counting_iterator operator+(counting_iterator it,
+                                                   difference_type n) {
+    it.count_ += static_cast<size_t>(n);
+    return it;
+  }
+
+  FMT_CONSTEXPR value_type operator*() const { return {}; }
+};
+
 template <typename Char, typename OutputIt>
 FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s,
                          const basic_format_specs<Char>& specs) -> OutputIt {
@@ -1654,10 +2180,17 @@
   auto size = s.size();
   if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
     size = code_point_index(s, to_unsigned(specs.precision));
-  auto width =
-      specs.width != 0 ? compute_width(basic_string_view<Char>(data, size)) : 0;
+  bool is_debug = specs.type == presentation_type::debug;
+  size_t width = 0;
+  if (specs.width != 0) {
+    if (is_debug)
+      width = write_escaped_string(counting_iterator{}, s).count();
+    else
+      width = compute_width(basic_string_view<Char>(data, size));
+  }
   return write_padded(out, specs, size, width,
                       [=](reserve_iterator<OutputIt> it) {
+                        if (is_debug) return write_escaped_string(it, s);
                         return copy_str<Char>(data, data + size, it);
                       });
 }
@@ -1675,15 +2208,37 @@
     -> OutputIt {
   return check_cstring_type_spec(specs.type)
              ? write(out, basic_string_view<Char>(s), specs, {})
-             : write_ptr<Char>(out, to_uintptr(s), &specs);
+             : write_ptr<Char>(out, bit_cast<uintptr_t>(s), &specs);
+}
+
+template <typename Char, typename OutputIt, typename T,
+          FMT_ENABLE_IF(is_integral<T>::value &&
+                        !std::is_same<T, bool>::value &&
+                        !std::is_same<T, Char>::value)>
+FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
+  auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
+  bool negative = is_negative(value);
+  // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
+  if (negative) abs_value = ~abs_value + 1;
+  int num_digits = count_digits(abs_value);
+  auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
+  auto it = reserve(out, size);
+  if (auto ptr = to_pointer<Char>(it, size)) {
+    if (negative) *ptr++ = static_cast<Char>('-');
+    format_decimal<Char>(ptr, abs_value, num_digits);
+    return out;
+  }
+  if (negative) *it++ = static_cast<Char>('-');
+  it = format_decimal<Char>(it, abs_value, num_digits).end;
+  return base_iterator(out, it);
 }
 
 template <typename Char, typename OutputIt>
-FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isinf,
+FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan,
                                      basic_format_specs<Char> specs,
                                      const float_specs& fspecs) -> OutputIt {
   auto str =
-      isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan");
+      isnan ? (fspecs.upper ? "NAN" : "nan") : (fspecs.upper ? "INF" : "inf");
   constexpr size_t str_size = 3;
   auto sign = fspecs.sign;
   auto size = str_size + (sign ? 1 : 0);
@@ -1704,12 +2259,12 @@
   int exponent;
 };
 
-constexpr auto get_significand_size(const big_decimal_fp& fp) -> int {
-  return fp.significand_size;
+constexpr auto get_significand_size(const big_decimal_fp& f) -> int {
+  return f.significand_size;
 }
 template <typename T>
-inline auto get_significand_size(const dragonbox::decimal_fp<T>& fp) -> int {
-  return count_digits(fp.significand);
+inline auto get_significand_size(const dragonbox::decimal_fp<T>& f) -> int {
+  return count_digits(f.significand);
 }
 
 template <typename Char, typename OutputIt>
@@ -1747,7 +2302,7 @@
   int floating_size = significand_size - integral_size;
   for (int i = floating_size / 2; i > 0; --i) {
     out -= 2;
-    copy2(out, digits2(significand % 100));
+    copy2(out, digits2(static_cast<std::size_t>(significand % 100)));
     significand /= 100;
   }
   if (floating_size % 2 != 0) {
@@ -1803,13 +2358,13 @@
 
 template <typename OutputIt, typename DecimalFP, typename Char,
           typename Grouping = digit_grouping<Char>>
-FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& fp,
+FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f,
                                     const basic_format_specs<Char>& specs,
                                     float_specs fspecs, locale_ref loc)
     -> OutputIt {
-  auto significand = fp.significand;
-  int significand_size = get_significand_size(fp);
-  constexpr Char zero = static_cast<Char>('0');
+  auto significand = f.significand;
+  int significand_size = get_significand_size(f);
+  const Char zero = static_cast<Char>('0');
   auto sign = fspecs.sign;
   size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
   using iterator = reserve_iterator<OutputIt>;
@@ -1817,7 +2372,7 @@
   Char decimal_point =
       fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.');
 
-  int output_exp = fp.exponent + significand_size - 1;
+  int output_exp = f.exponent + significand_size - 1;
   auto use_exp_format = [=]() {
     if (fspecs.format == float_format::exp) return true;
     if (fspecs.format != float_format::general) return false;
@@ -1855,25 +2410,23 @@
                            : base_iterator(out, write(reserve(out, size)));
   }
 
-  int exp = fp.exponent + significand_size;
-  if (fp.exponent >= 0) {
+  int exp = f.exponent + significand_size;
+  if (f.exponent >= 0) {
     // 1234e5 -> 123400000[.0+]
-    size += to_unsigned(fp.exponent);
+    size += to_unsigned(f.exponent);
     int num_zeros = fspecs.precision - exp;
-#ifdef FMT_FUZZ
-    if (num_zeros > 5000)
-      throw std::runtime_error("fuzz mode - avoiding excessive cpu use");
-#endif
+    abort_fuzzing_if(num_zeros > 5000);
     if (fspecs.showpoint) {
+      ++size;
       if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1;
-      if (num_zeros > 0) size += to_unsigned(num_zeros) + 1;
+      if (num_zeros > 0) size += to_unsigned(num_zeros);
     }
     auto grouping = Grouping(loc, fspecs.locale);
-    size += to_unsigned(grouping.count_separators(significand_size));
+    size += to_unsigned(grouping.count_separators(exp));
     return write_padded<align::right>(out, specs, size, [&](iterator it) {
       if (sign) *it++ = detail::sign<Char>(sign);
       it = write_significand<Char>(it, significand, significand_size,
-                                   fp.exponent, grouping);
+                                   f.exponent, grouping);
       if (!fspecs.showpoint) return it;
       *it++ = decimal_point;
       return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
@@ -1924,63 +2477,713 @@
 };
 
 template <typename OutputIt, typename DecimalFP, typename Char>
-FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& fp,
+FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f,
                                  const basic_format_specs<Char>& specs,
                                  float_specs fspecs, locale_ref loc)
     -> OutputIt {
   if (is_constant_evaluated()) {
     return do_write_float<OutputIt, DecimalFP, Char,
-                          fallback_digit_grouping<Char>>(out, fp, specs, fspecs,
+                          fallback_digit_grouping<Char>>(out, f, specs, fspecs,
                                                          loc);
   } else {
-    return do_write_float(out, fp, specs, fspecs, loc);
+    return do_write_float(out, f, specs, fspecs, loc);
   }
 }
 
-template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
-FMT_CONSTEXPR20 bool isinf(T value) {
-  if (is_constant_evaluated()) {
-#if defined(__cpp_if_constexpr)
-    if constexpr (std::numeric_limits<double>::is_iec559) {
-      auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
-      constexpr auto significand_bits =
-          dragonbox::float_info<double>::significand_bits;
-      return (bits & exponent_mask<double>()) &&
-             !(bits & ((uint64_t(1) << significand_bits) - 1));
-    }
-#endif
-  }
-  return std::isinf(value);
+template <typename T> constexpr bool isnan(T value) {
+  return !(value >= value);  // std::isnan doesn't support __float128.
 }
 
-template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
+template <typename T, typename Enable = void>
+struct has_isfinite : std::false_type {};
+
+template <typename T>
+struct has_isfinite<T, enable_if_t<sizeof(std::isfinite(T())) != 0>>
+    : std::true_type {};
+
+template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value&&
+                                        has_isfinite<T>::value)>
 FMT_CONSTEXPR20 bool isfinite(T value) {
-  if (is_constant_evaluated()) {
-#if defined(__cpp_if_constexpr)
-    if constexpr (std::numeric_limits<double>::is_iec559) {
-      auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
-      return (bits & exponent_mask<double>()) != exponent_mask<double>();
-    }
-#endif
-  }
+  constexpr T inf = T(std::numeric_limits<double>::infinity());
+  if (is_constant_evaluated())
+    return !detail::isnan(value) && value != inf && value != -inf;
   return std::isfinite(value);
 }
+template <typename T, FMT_ENABLE_IF(!has_isfinite<T>::value)>
+FMT_CONSTEXPR bool isfinite(T value) {
+  T inf = T(std::numeric_limits<double>::infinity());
+  // std::isfinite doesn't support __float128.
+  return !detail::isnan(value) && value != inf && value != -inf;
+}
 
-template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
+template <typename T, FMT_ENABLE_IF(is_floating_point<T>::value)>
 FMT_INLINE FMT_CONSTEXPR bool signbit(T value) {
   if (is_constant_evaluated()) {
 #ifdef __cpp_if_constexpr
     if constexpr (std::numeric_limits<double>::is_iec559) {
       auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
-      return (bits & (uint64_t(1) << (num_bits<uint64_t>() - 1))) != 0;
+      return (bits >> (num_bits<uint64_t>() - 1)) != 0;
     }
 #endif
   }
-  return std::signbit(value);
+  return std::signbit(static_cast<double>(value));
+}
+
+enum class round_direction { unknown, up, down };
+
+// Given the divisor (normally a power of 10), the remainder = v % divisor for
+// some number v and the error, returns whether v should be rounded up, down, or
+// whether the rounding direction can't be determined due to error.
+// error should be less than divisor / 2.
+FMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor,
+                                                         uint64_t remainder,
+                                                         uint64_t error) {
+  FMT_ASSERT(remainder < divisor, "");  // divisor - remainder won't overflow.
+  FMT_ASSERT(error < divisor, "");      // divisor - error won't overflow.
+  FMT_ASSERT(error < divisor - error, "");  // error * 2 won't overflow.
+  // Round down if (remainder + error) * 2 <= divisor.
+  if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2)
+    return round_direction::down;
+  // Round up if (remainder - error) * 2 >= divisor.
+  if (remainder >= error &&
+      remainder - error >= divisor - (remainder - error)) {
+    return round_direction::up;
+  }
+  return round_direction::unknown;
+}
+
+namespace digits {
+enum result {
+  more,  // Generate more digits.
+  done,  // Done generating digits.
+  error  // Digit generation cancelled due to an error.
+};
+}
+
+struct gen_digits_handler {
+  char* buf;
+  int size;
+  int precision;
+  int exp10;
+  bool fixed;
+
+  FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor,
+                                        uint64_t remainder, uint64_t error,
+                                        bool integral) {
+    FMT_ASSERT(remainder < divisor, "");
+    buf[size++] = digit;
+    if (!integral && error >= remainder) return digits::error;
+    if (size < precision) return digits::more;
+    if (!integral) {
+      // Check if error * 2 < divisor with overflow prevention.
+      // The check is not needed for the integral part because error = 1
+      // and divisor > (1 << 32) there.
+      if (error >= divisor || error >= divisor - error) return digits::error;
+    } else {
+      FMT_ASSERT(error == 1 && divisor > 2, "");
+    }
+    auto dir = get_round_direction(divisor, remainder, error);
+    if (dir != round_direction::up)
+      return dir == round_direction::down ? digits::done : digits::error;
+    ++buf[size - 1];
+    for (int i = size - 1; i > 0 && buf[i] > '9'; --i) {
+      buf[i] = '0';
+      ++buf[i - 1];
+    }
+    if (buf[0] > '9') {
+      buf[0] = '1';
+      if (fixed)
+        buf[size++] = '0';
+      else
+        ++exp10;
+    }
+    return digits::done;
+  }
+};
+
+inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) {
+  // Adjust fixed precision by exponent because it is relative to decimal
+  // point.
+  if (exp10 > 0 && precision > max_value<int>() - exp10)
+    FMT_THROW(format_error("number is too big"));
+  precision += exp10;
+}
+
+// Generates output using the Grisu digit-gen algorithm.
+// error: the size of the region (lower, upper) outside of which numbers
+// definitely do not round to value (Delta in Grisu3).
+FMT_INLINE FMT_CONSTEXPR20 auto grisu_gen_digits(fp value, uint64_t error,
+                                                 int& exp,
+                                                 gen_digits_handler& handler)
+    -> digits::result {
+  const fp one(1ULL << -value.e, value.e);
+  // The integral part of scaled value (p1 in Grisu) = value / one. It cannot be
+  // zero because it contains a product of two 64-bit numbers with MSB set (due
+  // to normalization) - 1, shifted right by at most 60 bits.
+  auto integral = static_cast<uint32_t>(value.f >> -one.e);
+  FMT_ASSERT(integral != 0, "");
+  FMT_ASSERT(integral == value.f >> -one.e, "");
+  // The fractional part of scaled value (p2 in Grisu) c = value % one.
+  uint64_t fractional = value.f & (one.f - 1);
+  exp = count_digits(integral);  // kappa in Grisu.
+  // Non-fixed formats require at least one digit and no precision adjustment.
+  if (handler.fixed) {
+    adjust_precision(handler.precision, exp + handler.exp10);
+    // Check if precision is satisfied just by leading zeros, e.g.
+    // format("{:.2f}", 0.001) gives "0.00" without generating any digits.
+    if (handler.precision <= 0) {
+      if (handler.precision < 0) return digits::done;
+      // Divide by 10 to prevent overflow.
+      uint64_t divisor = data::power_of_10_64[exp - 1] << -one.e;
+      auto dir = get_round_direction(divisor, value.f / 10, error * 10);
+      if (dir == round_direction::unknown) return digits::error;
+      handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0';
+      return digits::done;
+    }
+  }
+  // Generate digits for the integral part. This can produce up to 10 digits.
+  do {
+    uint32_t digit = 0;
+    auto divmod_integral = [&](uint32_t divisor) {
+      digit = integral / divisor;
+      integral %= divisor;
+    };
+    // This optimization by Milo Yip reduces the number of integer divisions by
+    // one per iteration.
+    switch (exp) {
+    case 10:
+      divmod_integral(1000000000);
+      break;
+    case 9:
+      divmod_integral(100000000);
+      break;
+    case 8:
+      divmod_integral(10000000);
+      break;
+    case 7:
+      divmod_integral(1000000);
+      break;
+    case 6:
+      divmod_integral(100000);
+      break;
+    case 5:
+      divmod_integral(10000);
+      break;
+    case 4:
+      divmod_integral(1000);
+      break;
+    case 3:
+      divmod_integral(100);
+      break;
+    case 2:
+      divmod_integral(10);
+      break;
+    case 1:
+      digit = integral;
+      integral = 0;
+      break;
+    default:
+      FMT_ASSERT(false, "invalid number of digits");
+    }
+    --exp;
+    auto remainder = (static_cast<uint64_t>(integral) << -one.e) + fractional;
+    auto result = handler.on_digit(static_cast<char>('0' + digit),
+                                   data::power_of_10_64[exp] << -one.e,
+                                   remainder, error, true);
+    if (result != digits::more) return result;
+  } while (exp > 0);
+  // Generate digits for the fractional part.
+  for (;;) {
+    fractional *= 10;
+    error *= 10;
+    char digit = static_cast<char>('0' + (fractional >> -one.e));
+    fractional &= one.f - 1;
+    --exp;
+    auto result = handler.on_digit(digit, one.f, fractional, error, false);
+    if (result != digits::more) return result;
+  }
+}
+
+class bigint {
+ private:
+  // A bigint is stored as an array of bigits (big digits), with bigit at index
+  // 0 being the least significant one.
+  using bigit = uint32_t;
+  using double_bigit = uint64_t;
+  enum { bigits_capacity = 32 };
+  basic_memory_buffer<bigit, bigits_capacity> bigits_;
+  int exp_;
+
+  FMT_CONSTEXPR20 bigit operator[](int index) const {
+    return bigits_[to_unsigned(index)];
+  }
+  FMT_CONSTEXPR20 bigit& operator[](int index) {
+    return bigits_[to_unsigned(index)];
+  }
+
+  static constexpr const int bigit_bits = num_bits<bigit>();
+
+  friend struct formatter<bigint>;
+
+  FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) {
+    auto result = static_cast<double_bigit>((*this)[index]) - other - borrow;
+    (*this)[index] = static_cast<bigit>(result);
+    borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));
+  }
+
+  FMT_CONSTEXPR20 void remove_leading_zeros() {
+    int num_bigits = static_cast<int>(bigits_.size()) - 1;
+    while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits;
+    bigits_.resize(to_unsigned(num_bigits + 1));
+  }
+
+  // Computes *this -= other assuming aligned bigints and *this >= other.
+  FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) {
+    FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints");
+    FMT_ASSERT(compare(*this, other) >= 0, "");
+    bigit borrow = 0;
+    int i = other.exp_ - exp_;
+    for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)
+      subtract_bigits(i, other.bigits_[j], borrow);
+    while (borrow > 0) subtract_bigits(i, 0, borrow);
+    remove_leading_zeros();
+  }
+
+  FMT_CONSTEXPR20 void multiply(uint32_t value) {
+    const double_bigit wide_value = value;
+    bigit carry = 0;
+    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
+      double_bigit result = bigits_[i] * wide_value + carry;
+      bigits_[i] = static_cast<bigit>(result);
+      carry = static_cast<bigit>(result >> bigit_bits);
+    }
+    if (carry != 0) bigits_.push_back(carry);
+  }
+
+  template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
+                                         std::is_same<UInt, uint128_t>::value)>
+  FMT_CONSTEXPR20 void multiply(UInt value) {
+    using half_uint =
+        conditional_t<std::is_same<UInt, uint128_t>::value, uint64_t, uint32_t>;
+    const int shift = num_bits<half_uint>() - bigit_bits;
+    const UInt lower = static_cast<half_uint>(value);
+    const UInt upper = value >> num_bits<half_uint>();
+    UInt carry = 0;
+    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
+      UInt result = lower * bigits_[i] + static_cast<bigit>(carry);
+      carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) +
+              (carry >> bigit_bits);
+      bigits_[i] = static_cast<bigit>(result);
+    }
+    while (carry != 0) {
+      bigits_.push_back(static_cast<bigit>(carry));
+      carry >>= bigit_bits;
+    }
+  }
+
+  template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
+                                         std::is_same<UInt, uint128_t>::value)>
+  FMT_CONSTEXPR20 void assign(UInt n) {
+    size_t num_bigits = 0;
+    do {
+      bigits_[num_bigits++] = static_cast<bigit>(n);
+      n >>= bigit_bits;
+    } while (n != 0);
+    bigits_.resize(num_bigits);
+    exp_ = 0;
+  }
+
+ public:
+  FMT_CONSTEXPR20 bigint() : exp_(0) {}
+  explicit bigint(uint64_t n) { assign(n); }
+
+  bigint(const bigint&) = delete;
+  void operator=(const bigint&) = delete;
+
+  FMT_CONSTEXPR20 void assign(const bigint& other) {
+    auto size = other.bigits_.size();
+    bigits_.resize(size);
+    auto data = other.bigits_.data();
+    std::copy(data, data + size, make_checked(bigits_.data(), size));
+    exp_ = other.exp_;
+  }
+
+  template <typename Int> FMT_CONSTEXPR20 void operator=(Int n) {
+    FMT_ASSERT(n > 0, "");
+    assign(uint64_or_128_t<Int>(n));
+  }
+
+  FMT_CONSTEXPR20 int num_bigits() const {
+    return static_cast<int>(bigits_.size()) + exp_;
+  }
+
+  FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) {
+    FMT_ASSERT(shift >= 0, "");
+    exp_ += shift / bigit_bits;
+    shift %= bigit_bits;
+    if (shift == 0) return *this;
+    bigit carry = 0;
+    for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
+      bigit c = bigits_[i] >> (bigit_bits - shift);
+      bigits_[i] = (bigits_[i] << shift) + carry;
+      carry = c;
+    }
+    if (carry != 0) bigits_.push_back(carry);
+    return *this;
+  }
+
+  template <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) {
+    FMT_ASSERT(value > 0, "");
+    multiply(uint32_or_64_or_128_t<Int>(value));
+    return *this;
+  }
+
+  friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) {
+    int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
+    if (num_lhs_bigits != num_rhs_bigits)
+      return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
+    int i = static_cast<int>(lhs.bigits_.size()) - 1;
+    int j = static_cast<int>(rhs.bigits_.size()) - 1;
+    int end = i - j;
+    if (end < 0) end = 0;
+    for (; i >= end; --i, --j) {
+      bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];
+      if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1;
+    }
+    if (i != j) return i > j ? 1 : -1;
+    return 0;
+  }
+
+  // Returns compare(lhs1 + lhs2, rhs).
+  friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2,
+                                         const bigint& rhs) {
+    auto minimum = [](int a, int b) { return a < b ? a : b; };
+    auto maximum = [](int a, int b) { return a > b ? a : b; };
+    int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits());
+    int num_rhs_bigits = rhs.num_bigits();
+    if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;
+    if (max_lhs_bigits > num_rhs_bigits) return 1;
+    auto get_bigit = [](const bigint& n, int i) -> bigit {
+      return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0;
+    };
+    double_bigit borrow = 0;
+    int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_);
+    for (int i = num_rhs_bigits - 1; i >= min_exp; --i) {
+      double_bigit sum =
+          static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);
+      bigit rhs_bigit = get_bigit(rhs, i);
+      if (sum > rhs_bigit + borrow) return 1;
+      borrow = rhs_bigit + borrow - sum;
+      if (borrow > 1) return -1;
+      borrow <<= bigit_bits;
+    }
+    return borrow != 0 ? -1 : 0;
+  }
+
+  // Assigns pow(10, exp) to this bigint.
+  FMT_CONSTEXPR20 void assign_pow10(int exp) {
+    FMT_ASSERT(exp >= 0, "");
+    if (exp == 0) return *this = 1;
+    // Find the top bit.
+    int bitmask = 1;
+    while (exp >= bitmask) bitmask <<= 1;
+    bitmask >>= 1;
+    // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
+    // repeated squaring and multiplication.
+    *this = 5;
+    bitmask >>= 1;
+    while (bitmask != 0) {
+      square();
+      if ((exp & bitmask) != 0) *this *= 5;
+      bitmask >>= 1;
+    }
+    *this <<= exp;  // Multiply by pow(2, exp) by shifting.
+  }
+
+  FMT_CONSTEXPR20 void square() {
+    int num_bigits = static_cast<int>(bigits_.size());
+    int num_result_bigits = 2 * num_bigits;
+    basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));
+    bigits_.resize(to_unsigned(num_result_bigits));
+    auto sum = uint128_t();
+    for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {
+      // Compute bigit at position bigit_index of the result by adding
+      // cross-product terms n[i] * n[j] such that i + j == bigit_index.
+      for (int i = 0, j = bigit_index; j >= 0; ++i, --j) {
+        // Most terms are multiplied twice which can be optimized in the future.
+        sum += static_cast<double_bigit>(n[i]) * n[j];
+      }
+      (*this)[bigit_index] = static_cast<bigit>(sum);
+      sum >>= num_bits<bigit>();  // Compute the carry.
+    }
+    // Do the same for the top half.
+    for (int bigit_index = num_bigits; bigit_index < num_result_bigits;
+         ++bigit_index) {
+      for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)
+        sum += static_cast<double_bigit>(n[i++]) * n[j--];
+      (*this)[bigit_index] = static_cast<bigit>(sum);
+      sum >>= num_bits<bigit>();
+    }
+    remove_leading_zeros();
+    exp_ *= 2;
+  }
+
+  // If this bigint has a bigger exponent than other, adds trailing zero to make
+  // exponents equal. This simplifies some operations such as subtraction.
+  FMT_CONSTEXPR20 void align(const bigint& other) {
+    int exp_difference = exp_ - other.exp_;
+    if (exp_difference <= 0) return;
+    int num_bigits = static_cast<int>(bigits_.size());
+    bigits_.resize(to_unsigned(num_bigits + exp_difference));
+    for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
+      bigits_[j] = bigits_[i];
+    std::uninitialized_fill_n(bigits_.data(), exp_difference, 0);
+    exp_ -= exp_difference;
+  }
+
+  // Divides this bignum by divisor, assigning the remainder to this and
+  // returning the quotient.
+  FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) {
+    FMT_ASSERT(this != &divisor, "");
+    if (compare(*this, divisor) < 0) return 0;
+    FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, "");
+    align(divisor);
+    int quotient = 0;
+    do {
+      subtract_aligned(divisor);
+      ++quotient;
+    } while (compare(*this, divisor) >= 0);
+    return quotient;
+  }
+};
+
+// format_dragon flags.
+enum dragon {
+  predecessor_closer = 1,
+  fixup = 2,  // Run fixup to correct exp10 which can be off by one.
+  fixed = 4,
+};
+
+// Formats a floating-point number using a variation of the Fixed-Precision
+// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
+// https://fmt.dev/papers/p372-steele.pdf.
+FMT_CONSTEXPR20 inline void format_dragon(basic_fp<uint128_t> value,
+                                          unsigned flags, int num_digits,
+                                          buffer<char>& buf, int& exp10) {
+  bigint numerator;    // 2 * R in (FPP)^2.
+  bigint denominator;  // 2 * S in (FPP)^2.
+  // lower and upper are differences between value and corresponding boundaries.
+  bigint lower;             // (M^- in (FPP)^2).
+  bigint upper_store;       // upper's value if different from lower.
+  bigint* upper = nullptr;  // (M^+ in (FPP)^2).
+  // Shift numerator and denominator by an extra bit or two (if lower boundary
+  // is closer) to make lower and upper integers. This eliminates multiplication
+  // by 2 during later computations.
+  bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0;
+  int shift = is_predecessor_closer ? 2 : 1;
+  if (value.e >= 0) {
+    numerator = value.f;
+    numerator <<= value.e + shift;
+    lower = 1;
+    lower <<= value.e;
+    if (is_predecessor_closer) {
+      upper_store = 1;
+      upper_store <<= value.e + 1;
+      upper = &upper_store;
+    }
+    denominator.assign_pow10(exp10);
+    denominator <<= shift;
+  } else if (exp10 < 0) {
+    numerator.assign_pow10(-exp10);
+    lower.assign(numerator);
+    if (is_predecessor_closer) {
+      upper_store.assign(numerator);
+      upper_store <<= 1;
+      upper = &upper_store;
+    }
+    numerator *= value.f;
+    numerator <<= shift;
+    denominator = 1;
+    denominator <<= shift - value.e;
+  } else {
+    numerator = value.f;
+    numerator <<= shift;
+    denominator.assign_pow10(exp10);
+    denominator <<= shift - value.e;
+    lower = 1;
+    if (is_predecessor_closer) {
+      upper_store = 1ULL << 1;
+      upper = &upper_store;
+    }
+  }
+  int even = static_cast<int>((value.f & 1) == 0);
+  if (!upper) upper = &lower;
+  if ((flags & dragon::fixup) != 0) {
+    if (add_compare(numerator, *upper, denominator) + even <= 0) {
+      --exp10;
+      numerator *= 10;
+      if (num_digits < 0) {
+        lower *= 10;
+        if (upper != &lower) *upper *= 10;
+      }
+    }
+    if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1);
+  }
+  // Invariant: value == (numerator / denominator) * pow(10, exp10).
+  if (num_digits < 0) {
+    // Generate the shortest representation.
+    num_digits = 0;
+    char* data = buf.data();
+    for (;;) {
+      int digit = numerator.divmod_assign(denominator);
+      bool low = compare(numerator, lower) - even < 0;  // numerator <[=] lower.
+      // numerator + upper >[=] pow10:
+      bool high = add_compare(numerator, *upper, denominator) + even > 0;
+      data[num_digits++] = static_cast<char>('0' + digit);
+      if (low || high) {
+        if (!low) {
+          ++data[num_digits - 1];
+        } else if (high) {
+          int result = add_compare(numerator, numerator, denominator);
+          // Round half to even.
+          if (result > 0 || (result == 0 && (digit % 2) != 0))
+            ++data[num_digits - 1];
+        }
+        buf.try_resize(to_unsigned(num_digits));
+        exp10 -= num_digits - 1;
+        return;
+      }
+      numerator *= 10;
+      lower *= 10;
+      if (upper != &lower) *upper *= 10;
+    }
+  }
+  // Generate the given number of digits.
+  exp10 -= num_digits - 1;
+  if (num_digits == 0) {
+    denominator *= 10;
+    auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
+    buf.push_back(digit);
+    return;
+  }
+  buf.try_resize(to_unsigned(num_digits));
+  for (int i = 0; i < num_digits - 1; ++i) {
+    int digit = numerator.divmod_assign(denominator);
+    buf[i] = static_cast<char>('0' + digit);
+    numerator *= 10;
+  }
+  int digit = numerator.divmod_assign(denominator);
+  auto result = add_compare(numerator, numerator, denominator);
+  if (result > 0 || (result == 0 && (digit % 2) != 0)) {
+    if (digit == 9) {
+      const auto overflow = '0' + 10;
+      buf[num_digits - 1] = overflow;
+      // Propagate the carry.
+      for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
+        buf[i] = '0';
+        ++buf[i - 1];
+      }
+      if (buf[0] == overflow) {
+        buf[0] = '1';
+        ++exp10;
+      }
+      return;
+    }
+    ++digit;
+  }
+  buf[num_digits - 1] = static_cast<char>('0' + digit);
+}
+
+template <typename Float>
+FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs,
+                                  buffer<char>& buf) -> int {
+  // float is passed as double to reduce the number of instantiations.
+  static_assert(!std::is_same<Float, float>::value, "");
+  FMT_ASSERT(value >= 0, "value is negative");
+  auto converted_value = convert_float(value);
+
+  const bool fixed = specs.format == float_format::fixed;
+  if (value <= 0) {  // <= instead of == to silence a warning.
+    if (precision <= 0 || !fixed) {
+      buf.push_back('0');
+      return 0;
+    }
+    buf.try_resize(to_unsigned(precision));
+    fill_n(buf.data(), precision, '0');
+    return -precision;
+  }
+
+  int exp = 0;
+  bool use_dragon = true;
+  unsigned dragon_flags = 0;
+  if (!is_fast_float<Float>()) {
+    const auto inv_log2_10 = 0.3010299956639812;  // 1 / log2(10)
+    using info = dragonbox::float_info<decltype(converted_value)>;
+    const auto f = basic_fp<typename info::carrier_uint>(converted_value);
+    // Compute exp, an approximate power of 10, such that
+    //   10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
+    // This is based on log10(value) == log2(value) / log2(10) and approximation
+    // of log2(value) by e + num_fraction_bits idea from double-conversion.
+    exp = static_cast<int>(
+        std::ceil((f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10));
+    dragon_flags = dragon::fixup;
+  } else if (!is_constant_evaluated() && precision < 0) {
+    // Use Dragonbox for the shortest format.
+    if (specs.binary32) {
+      auto dec = dragonbox::to_decimal(static_cast<float>(value));
+      write<char>(buffer_appender<char>(buf), dec.significand);
+      return dec.exponent;
+    }
+    auto dec = dragonbox::to_decimal(static_cast<double>(value));
+    write<char>(buffer_appender<char>(buf), dec.significand);
+    return dec.exponent;
+  } else {
+    // Use Grisu + Dragon4 for the given precision:
+    // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf.
+    const int min_exp = -60;  // alpha in Grisu.
+    int cached_exp10 = 0;     // K in Grisu.
+    fp normalized = normalize(fp(converted_value));
+    const auto cached_pow = get_cached_power(
+        min_exp - (normalized.e + fp::num_significand_bits), cached_exp10);
+    normalized = normalized * cached_pow;
+    gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed};
+    if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error &&
+        !is_constant_evaluated()) {
+      exp += handler.exp10;
+      buf.try_resize(to_unsigned(handler.size));
+      use_dragon = false;
+    } else {
+      exp += handler.size - cached_exp10 - 1;
+      precision = handler.precision;
+    }
+  }
+  if (use_dragon) {
+    auto f = basic_fp<uint128_t>();
+    bool is_predecessor_closer = specs.binary32
+                                     ? f.assign(static_cast<float>(value))
+                                     : f.assign(converted_value);
+    if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer;
+    if (fixed) dragon_flags |= dragon::fixed;
+    // Limit precision to the maximum possible number of significant digits in
+    // an IEEE754 double because we don't need to generate zeros.
+    const int max_double_digits = 767;
+    if (precision > max_double_digits) precision = max_double_digits;
+    format_dragon(f, dragon_flags, precision, buf, exp);
+  }
+  if (!fixed && !specs.showpoint) {
+    // Remove trailing zeros.
+    auto num_digits = buf.size();
+    while (num_digits > 0 && buf[num_digits - 1] == '0') {
+      --num_digits;
+      ++exp;
+    }
+    buf.try_resize(num_digits);
+  }
+  return exp;
 }
 
 template <typename Char, typename OutputIt, typename T,
-          FMT_ENABLE_IF(std::is_floating_point<T>::value)>
+          FMT_ENABLE_IF(is_floating_point<T>::value)>
 FMT_CONSTEXPR20 auto write(OutputIt out, T value,
                            basic_format_specs<Char> specs, locale_ref loc = {})
     -> OutputIt {
@@ -1995,7 +3198,7 @@
   }
 
   if (!detail::isfinite(value))
-    return write_nonfinite(out, detail::isinf(value), specs, fspecs);
+    return write_nonfinite(out, detail::isnan(value), specs, fspecs);
 
   if (specs.align == align::numeric && fspecs.sign) {
     auto it = reserve(out, 1);
@@ -2008,7 +3211,7 @@
   memory_buffer buffer;
   if (fspecs.format == float_format::hex) {
     if (fspecs.sign) buffer.push_back(detail::sign<char>(fspecs.sign));
-    snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
+    snprintf_float(convert_float(value), specs.precision, fspecs, buffer);
     return write_bytes<align::right>(out, {buffer.data(), buffer.size()},
                                      specs);
   }
@@ -2020,28 +3223,23 @@
       throw_format_error("number is too big");
     else
       ++precision;
+  } else if (fspecs.format != float_format::fixed && precision == 0) {
+    precision = 1;
   }
   if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
-  if (!is_fast_float<T>()) fspecs.fallback = true;
-  int exp = format_float(promote_float(value), precision, fspecs, buffer);
+  int exp = format_float(convert_float(value), precision, fspecs, buffer);
   fspecs.precision = precision;
-  auto fp = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
-  return write_float(out, fp, specs, fspecs, loc);
+  auto f = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
+  return write_float(out, f, specs, fspecs, loc);
 }
 
 template <typename Char, typename OutputIt, typename T,
           FMT_ENABLE_IF(is_fast_float<T>::value)>
 FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
-  if (is_constant_evaluated()) {
+  if (is_constant_evaluated())
     return write(out, value, basic_format_specs<Char>());
-  }
-
   if (const_check(!is_supported_floating_point(value))) return out;
 
-  using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;
-  using uint = typename dragonbox::float_info<floaty>::carrier_uint;
-  auto bits = bit_cast<uint>(value);
-
   auto fspecs = float_specs();
   if (detail::signbit(value)) {
     fspecs.sign = sign::minus;
@@ -2049,16 +3247,18 @@
   }
 
   constexpr auto specs = basic_format_specs<Char>();
+  using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;
+  using uint = typename dragonbox::float_info<floaty>::carrier_uint;
   uint mask = exponent_mask<floaty>();
-  if ((bits & mask) == mask)
-    return write_nonfinite(out, std::isinf(value), specs, fspecs);
+  if ((bit_cast<uint>(value) & mask) == mask)
+    return write_nonfinite(out, std::isnan(value), specs, fspecs);
 
   auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
   return write_float(out, dec, specs, fspecs, {});
 }
 
 template <typename Char, typename OutputIt, typename T,
-          FMT_ENABLE_IF(std::is_floating_point<T>::value &&
+          FMT_ENABLE_IF(is_floating_point<T>::value &&
                         !is_fast_float<T>::value)>
 inline auto write(OutputIt out, T value) -> OutputIt {
   return write(out, value, basic_format_specs<Char>());
@@ -2085,28 +3285,6 @@
   return write<Char>(out, to_string_view(value));
 }
 
-template <typename Char, typename OutputIt, typename T,
-          FMT_ENABLE_IF(is_integral<T>::value &&
-                        !std::is_same<T, bool>::value &&
-                        !std::is_same<T, Char>::value)>
-FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
-  auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
-  bool negative = is_negative(value);
-  // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
-  if (negative) abs_value = ~abs_value + 1;
-  int num_digits = count_digits(abs_value);
-  auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
-  auto it = reserve(out, size);
-  if (auto ptr = to_pointer<Char>(it, size)) {
-    if (negative) *ptr++ = static_cast<Char>('-');
-    format_decimal<Char>(ptr, abs_value, num_digits);
-    return out;
-  }
-  if (negative) *it++ = static_cast<Char>('-');
-  it = format_decimal<Char>(it, abs_value, num_digits).end;
-  return base_iterator(out, it);
-}
-
 // FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
 template <
     typename Char, typename OutputIt, typename T,
@@ -2116,8 +3294,7 @@
             type::custom_type,
     FMT_ENABLE_IF(check)>
 FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
-  return write<Char>(
-      out, static_cast<typename std::underlying_type<T>::type>(value));
+  return write<Char>(out, static_cast<underlying_t<T>>(value));
 }
 
 template <typename Char, typename OutputIt, typename T,
@@ -2155,7 +3332,7 @@
            const basic_format_specs<Char>& specs = {}, locale_ref = {})
     -> OutputIt {
   check_pointer_type_spec(specs.type, error_handler());
-  return write_ptr<Char>(out, to_uintptr(value), &specs);
+  return write_ptr<Char>(out, bit_cast<uintptr_t>(value), &specs);
 }
 
 // A write overload that handles implicit conversions.
@@ -2163,7 +3340,7 @@
           typename Context = basic_format_context<OutputIt, Char>>
 FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t<
     std::is_class<T>::value && !is_string<T>::value &&
-        !std::is_same<T, Char>::value &&
+        !is_floating_point<T>::value && !std::is_same<T, Char>::value &&
         !std::is_same<const T&,
                       decltype(arg_mapper<Context>().map(value))>::value,
     OutputIt> {
@@ -2356,43 +3533,17 @@
   }
 }
 
-#define FMT_STRING_IMPL(s, base, explicit)                                 \
-  [] {                                                                     \
-    /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
-    /* Use a macro-like name to avoid shadowing warnings. */               \
-    struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base {           \
-      using char_type = fmt::remove_cvref_t<decltype(s[0])>;               \
-      FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit                              \
-      operator fmt::basic_string_view<char_type>() const {                 \
-        return fmt::detail_exported::compile_string_to_view<char_type>(s); \
-      }                                                                    \
-    };                                                                     \
-    return FMT_COMPILE_STRING();                                           \
-  }()
-
-/**
-  \rst
-  Constructs a compile-time format string from a string literal *s*.
-
-  **Example**::
-
-    // A compile-time error because 'd' is an invalid specifier for strings.
-    std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
-  \endrst
- */
-#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string, )
-
 #if FMT_USE_USER_DEFINED_LITERALS
 template <typename Char> struct udl_formatter {
   basic_string_view<Char> str;
 
   template <typename... T>
   auto operator()(T&&... args) const -> std::basic_string<Char> {
-    return vformat(str, fmt::make_args_checked<T...>(str, args...));
+    return vformat(str, fmt::make_format_args<buffer_context<Char>>(args...));
   }
 };
 
-#  if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+#  if FMT_USE_NONTYPE_TEMPLATE_ARGS
 template <typename T, typename Char, size_t N,
           fmt::detail_exported::fixed_string<Char, N> Str>
 struct statically_named_arg : view {
@@ -2441,10 +3592,10 @@
 using format_func = void (*)(detail::buffer<char>&, int, const char*);
 
 FMT_API void format_error_code(buffer<char>& out, int error_code,
-                               string_view message) FMT_NOEXCEPT;
+                               string_view message) noexcept;
 
 FMT_API void report_error(format_func func, int error_code,
-                          const char* message) FMT_NOEXCEPT;
+                          const char* message) noexcept;
 FMT_END_DETAIL_NAMESPACE
 
 FMT_API auto vsystem_error(int error_code, string_view format_str,
@@ -2490,12 +3641,11 @@
   \endrst
  */
 FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
-                                 const char* message) FMT_NOEXCEPT;
+                                 const char* message) noexcept;
 
 // Reports a system error without throwing an exception.
 // Can be used to report errors from destructors.
-FMT_API void report_system_error(int error_code,
-                                 const char* message) FMT_NOEXCEPT;
+FMT_API void report_system_error(int error_code, const char* message) noexcept;
 
 /** Fast integer formatter. */
 class format_int {
@@ -2577,28 +3727,6 @@
   return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
 }
 
-#define FMT_FORMAT_AS(Type, Base)                                        \
-  template <typename Char>                                               \
-  struct formatter<Type, Char> : formatter<Base, Char> {                 \
-    template <typename FormatContext>                                    \
-    auto format(Type const& val, FormatContext& ctx) const               \
-        -> decltype(ctx.out()) {                                         \
-      return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \
-    }                                                                    \
-  }
-
-FMT_FORMAT_AS(signed char, int);
-FMT_FORMAT_AS(unsigned char, unsigned);
-FMT_FORMAT_AS(short, int);
-FMT_FORMAT_AS(unsigned short, unsigned);
-FMT_FORMAT_AS(long, long long);
-FMT_FORMAT_AS(unsigned long, unsigned long long);
-FMT_FORMAT_AS(Char*, const Char*);
-FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
-FMT_FORMAT_AS(std::nullptr_t, const void*);
-FMT_FORMAT_AS(detail::byte, unsigned char);
-FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
-
 template <typename Char>
 struct formatter<void*, Char> : formatter<const void*, Char> {
   template <typename FormatContext>
@@ -2688,6 +3816,28 @@
   return p.get();
 }
 
+/**
+  \rst
+  Converts ``e`` to the underlying type.
+
+  **Example**::
+
+    enum class color { red, green, blue };
+    auto s = fmt::format("{}", fmt::underlying(color::red));
+  \endrst
+ */
+template <typename Enum>
+constexpr auto underlying(Enum e) noexcept -> underlying_t<Enum> {
+  return static_cast<underlying_t<Enum>>(e);
+}
+
+namespace enums {
+template <typename Enum, FMT_ENABLE_IF(std::is_enum<Enum>::value)>
+constexpr auto format_as(Enum e) noexcept -> underlying_t<Enum> {
+  return static_cast<underlying_t<Enum>>(e);
+}
+}  // namespace enums
+
 class bytes {
  private:
   string_view data_;
@@ -2779,9 +3929,6 @@
 };
 
 template <typename It, typename Sentinel, typename Char>
-using arg_join FMT_DEPRECATED_ALIAS = join_view<It, Sentinel, Char>;
-
-template <typename It, typename Sentinel, typename Char>
 struct formatter<join_view<It, Sentinel, Char>, Char> {
  private:
   using value_type =
@@ -2818,8 +3965,8 @@
   }
 
   template <typename FormatContext>
-  auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx)
-      -> decltype(ctx.out()) {
+  auto format(const join_view<It, Sentinel, Char>& value,
+              FormatContext& ctx) const -> decltype(ctx.out()) {
     auto it = value.begin;
     auto out = ctx.out();
     if (it != value.end) {
@@ -2936,9 +4083,10 @@
     basic_format_parse_context<Char> parse_context;
     buffer_context<Char> context;
 
-    format_handler(buffer_appender<Char> out, basic_string_view<Char> str,
-                   basic_format_args<buffer_context<Char>> args, locale_ref loc)
-        : parse_context(str), context(out, args, loc) {}
+    format_handler(buffer_appender<Char> p_out, basic_string_view<Char> str,
+                   basic_format_args<buffer_context<Char>> p_args,
+                   locale_ref p_loc)
+        : parse_context(str), context(p_out, p_args, p_loc) {}
 
     void on_text(const Char* begin, const Char* end) {
       auto text = basic_string_view<Char>(begin, to_unsigned(end - begin));
@@ -2995,20 +4143,6 @@
     -> thousands_sep_result<wchar_t>;
 extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
 extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
-extern template auto format_float<double>(double value, int precision,
-                                          float_specs specs, buffer<char>& buf)
-    -> int;
-extern template auto format_float<long double>(long double value, int precision,
-                                               float_specs specs,
-                                               buffer<char>& buf) -> int;
-void snprintf_float(float, int, float_specs, buffer<char>&) = delete;
-extern template auto snprintf_float<double>(double value, int precision,
-                                            float_specs specs,
-                                            buffer<char>& buf) -> int;
-extern template auto snprintf_float<long double>(long double value,
-                                                 int precision,
-                                                 float_specs specs,
-                                                 buffer<char>& buf) -> int;
 #endif  // FMT_HEADER_ONLY
 
 FMT_END_DETAIL_NAMESPACE
@@ -3025,25 +4159,16 @@
     fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
   \endrst
  */
-#  if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
-template <detail_exported::fixed_string Str>
-constexpr auto operator""_a()
-    -> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>,
-                       sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> {
-  return {};
+#  if FMT_USE_NONTYPE_TEMPLATE_ARGS
+template <detail_exported::fixed_string Str> constexpr auto operator""_a() {
+  using char_t = remove_cvref_t<decltype(Str.data[0])>;
+  return detail::udl_arg<char_t, sizeof(Str.data) / sizeof(char_t), Str>();
 }
 #  else
 constexpr auto operator"" _a(const char* s, size_t) -> detail::udl_arg<char> {
   return {s};
 }
 #  endif
-
-// DEPRECATED!
-// User-defined literal equivalent of fmt::format.
-FMT_DEPRECATED constexpr auto operator"" _format(const char* s, size_t n)
-    -> detail::udl_formatter<char> {
-  return {{s, n}};
-}
 }  // namespace literals
 #endif  // FMT_USE_USER_DEFINED_LITERALS
 
@@ -3060,14 +4185,6 @@
   return vformat(loc, string_view(fmt), fmt::make_format_args(args...));
 }
 
-template <typename... T, size_t SIZE, typename Allocator>
-FMT_DEPRECATED auto format_to(basic_memory_buffer<char, SIZE, Allocator>& buf,
-                              format_string<T...> fmt, T&&... args)
-    -> appender {
-  detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...));
-  return appender(buf);
-}
-
 template <typename OutputIt, typename Locale,
           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
                             detail::is_locale<Locale>::value)>
@@ -3090,10 +4207,6 @@
 FMT_MODULE_EXPORT_END
 FMT_END_NAMESPACE
 
-#ifdef FMT_DEPRECATED_INCLUDE_XCHAR
-#  include "xchar.h"
-#endif
-
 #ifdef FMT_HEADER_ONLY
 #  define FMT_FUNC inline
 #  include "format-inl.h"
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/os.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/os.h
similarity index 82%
rename from wpiutil/src/main/native/fmtlib/include/fmt/os.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/os.h
index b64f8bb..d82be11 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/os.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/os.h
@@ -9,10 +9,8 @@
 #define FMT_OS_H_
 
 #include <cerrno>
-#include <clocale>  // locale_t
 #include <cstddef>
 #include <cstdio>
-#include <cstdlib>       // strtod_l
 #include <system_error>  // std::system_error
 
 #if defined __APPLE__ || defined(__FreeBSD__)
@@ -141,7 +139,7 @@
 };
 
 #ifdef _WIN32
-FMT_API const std::error_category& system_category() FMT_NOEXCEPT;
+FMT_API const std::error_category& system_category() noexcept;
 
 FMT_BEGIN_DETAIL_NAMESPACE
 // A converter from UTF-16 to UTF-8.
@@ -165,7 +163,7 @@
 };
 
 FMT_API void format_windows_error(buffer<char>& out, int error_code,
-                                  const char* message) FMT_NOEXCEPT;
+                                  const char* message) noexcept;
 FMT_END_DETAIL_NAMESPACE
 
 FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
@@ -207,10 +205,9 @@
 
 // Reports a Windows error without throwing an exception.
 // Can be used to report errors from destructors.
-FMT_API void report_windows_error(int error_code,
-                                  const char* message) FMT_NOEXCEPT;
+FMT_API void report_windows_error(int error_code, const char* message) noexcept;
 #else
-inline const std::error_category& system_category() FMT_NOEXCEPT {
+inline const std::error_category& system_category() noexcept {
   return std::system_category();
 }
 #endif  // _WIN32
@@ -237,13 +234,13 @@
   void operator=(const buffered_file&) = delete;
 
   // Constructs a buffered_file object which doesn't represent any file.
-  buffered_file() FMT_NOEXCEPT : file_(nullptr) {}
+  buffered_file() noexcept : file_(nullptr) {}
 
   // Destroys the object closing the file it represents if any.
-  FMT_API ~buffered_file() FMT_NOEXCEPT;
+  FMT_API ~buffered_file() noexcept;
 
  public:
-  buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) {
+  buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
     other.file_ = nullptr;
   }
 
@@ -261,11 +258,9 @@
   FMT_API void close();
 
   // Returns the pointer to a FILE object representing this file.
-  FILE* get() const FMT_NOEXCEPT { return file_; }
+  FILE* get() const noexcept { return file_; }
 
-  // We place parentheses around fileno to workaround a bug in some versions
-  // of MinGW that define fileno as a macro.
-  FMT_API int(fileno)() const;
+  FMT_API int descriptor() const;
 
   void vprint(string_view format_str, format_args args) {
     fmt::vprint(file_, format_str, args);
@@ -279,12 +274,12 @@
 
 #if FMT_USE_FCNTL
 // A file. Closed file is represented by a file object with descriptor -1.
-// Methods that are not declared with FMT_NOEXCEPT may throw
+// Methods that are not declared with noexcept may throw
 // fmt::system_error in case of failure. Note that some errors such as
 // closing the file multiple times will cause a crash on Windows rather
 // than an exception. You can get standard behavior by overriding the
 // invalid parameter handler with _set_invalid_parameter_handler.
-class file {
+class FMT_API file {
  private:
   int fd_;  // File descriptor.
 
@@ -303,16 +298,16 @@
   };
 
   // Constructs a file object which doesn't represent any file.
-  file() FMT_NOEXCEPT : fd_(-1) {}
+  file() noexcept : fd_(-1) {}
 
   // Opens a file and constructs a file object representing this file.
-  FMT_API file(cstring_view path, int oflag);
+  file(cstring_view path, int oflag);
 
  public:
   file(const file&) = delete;
   void operator=(const file&) = delete;
 
-  file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }
+  file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
 
   // Move assignment is not noexcept because close may throw.
   file& operator=(file&& other) {
@@ -323,43 +318,43 @@
   }
 
   // Destroys the object closing the file it represents if any.
-  FMT_API ~file() FMT_NOEXCEPT;
+  ~file() noexcept;
 
   // Returns the file descriptor.
-  int descriptor() const FMT_NOEXCEPT { return fd_; }
+  int descriptor() const noexcept { return fd_; }
 
   // Closes the file.
-  FMT_API void close();
+  void close();
 
   // Returns the file size. The size has signed type for consistency with
   // stat::st_size.
-  FMT_API long long size() const;
+  long long size() const;
 
   // Attempts to read count bytes from the file into the specified buffer.
-  FMT_API size_t read(void* buffer, size_t count);
+  size_t read(void* buffer, size_t count);
 
   // Attempts to write count bytes from the specified buffer to the file.
-  FMT_API size_t write(const void* buffer, size_t count);
+  size_t write(const void* buffer, size_t count);
 
   // Duplicates a file descriptor with the dup function and returns
   // the duplicate as a file object.
-  FMT_API static file dup(int fd);
+  static file dup(int fd);
 
   // Makes fd be the copy of this file descriptor, closing fd first if
   // necessary.
-  FMT_API void dup2(int fd);
+  void dup2(int fd);
 
   // Makes fd be the copy of this file descriptor, closing fd first if
   // necessary.
-  FMT_API void dup2(int fd, std::error_code& ec) FMT_NOEXCEPT;
+  void dup2(int fd, std::error_code& ec) noexcept;
 
   // Creates a pipe setting up read_end and write_end file objects for reading
   // and writing respectively.
-  FMT_API static void pipe(file& read_end, file& write_end);
+  static void pipe(file& read_end, file& write_end);
 
   // Creates a buffered_file object associated with this file and detaches
   // this file object from the file.
-  FMT_API buffered_file fdopen(const char* mode);
+  buffered_file fdopen(const char* mode);
 };
 
 // Returns the memory page size.
@@ -462,7 +457,7 @@
 
   * ``<integer>``: Flags passed to `open
     <https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html>`_
-    (``file::WRONLY | file::CREATE`` by default)
+    (``file::WRONLY | file::CREATE | file::TRUNC`` by default)
   * ``buffer_size=<integer>``: Output buffer size
 
   **Example**::
@@ -477,50 +472,6 @@
 }
 #endif  // FMT_USE_FCNTL
 
-#ifdef FMT_LOCALE
-// A "C" numeric locale.
-class locale {
- private:
-#  ifdef _WIN32
-  using locale_t = _locale_t;
-
-  static void freelocale(locale_t loc) { _free_locale(loc); }
-
-  static double strtod_l(const char* nptr, char** endptr, _locale_t loc) {
-    return _strtod_l(nptr, endptr, loc);
-  }
-#  endif
-
-  locale_t locale_;
-
- public:
-  using type = locale_t;
-  locale(const locale&) = delete;
-  void operator=(const locale&) = delete;
-
-  locale() {
-#  ifndef _WIN32
-    locale_ = FMT_SYSTEM(newlocale(LC_NUMERIC_MASK, "C", nullptr));
-#  else
-    locale_ = _create_locale(LC_NUMERIC, "C");
-#  endif
-    if (!locale_) FMT_THROW(system_error(errno, "cannot create locale"));
-  }
-  ~locale() { freelocale(locale_); }
-
-  type get() const { return locale_; }
-
-  // Converts string to floating-point number and advances str past the end
-  // of the parsed input.
-  FMT_DEPRECATED double strtod(const char*& str) const {
-    char* end = nullptr;
-    double result = strtod_l(str, &end, locale_);
-    str = end;
-    return result;
-  }
-};
-using Locale FMT_DEPRECATED_ALIAS = locale;
-#endif  // FMT_LOCALE
 FMT_MODULE_EXPORT_END
 FMT_END_NAMESPACE
 
diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ostream.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ostream.h
new file mode 100644
index 0000000..c3cdd4a
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ostream.h
@@ -0,0 +1,237 @@
+// Formatting library for C++ - std::ostream support
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#ifndef FMT_OSTREAM_H_
+#define FMT_OSTREAM_H_
+
+#include <fstream>
+#include <ostream>
+#if defined(_WIN32) && defined(__GLIBCXX__)
+#  include <ext/stdio_filebuf.h>
+#  include <ext/stdio_sync_filebuf.h>
+#elif defined(_WIN32) && defined(_LIBCPP_VERSION)
+#  include <__std_stream>
+#endif
+
+#include "format.h"
+
+FMT_BEGIN_NAMESPACE
+
+template <typename OutputIt, typename Char> class basic_printf_context;
+
+namespace detail {
+
+// Checks if T has a user-defined operator<<.
+template <typename T, typename Char, typename Enable = void>
+class is_streamable {
+ private:
+  template <typename U>
+  static auto test(int)
+      -> bool_constant<sizeof(std::declval<std::basic_ostream<Char>&>()
+                              << std::declval<U>()) != 0>;
+
+  template <typename> static auto test(...) -> std::false_type;
+
+  using result = decltype(test<T>(0));
+
+ public:
+  is_streamable() = default;
+
+  static const bool value = result::value;
+};
+
+// Formatting of built-in types and arrays is intentionally disabled because
+// it's handled by standard (non-ostream) formatters.
+template <typename T, typename Char>
+struct is_streamable<
+    T, Char,
+    enable_if_t<
+        std::is_arithmetic<T>::value || std::is_array<T>::value ||
+        std::is_pointer<T>::value || std::is_same<T, char8_type>::value ||
+        std::is_convertible<T, fmt::basic_string_view<Char>>::value ||
+        std::is_same<T, std_string_view<Char>>::value ||
+        (std::is_convertible<T, int>::value && !std::is_enum<T>::value)>>
+    : std::false_type {};
+
+// Generate a unique explicit instantion in every translation unit using a tag
+// type in an anonymous namespace.
+namespace {
+struct file_access_tag {};
+}  // namespace
+template <class Tag, class BufType, FILE* BufType::*FileMemberPtr>
+class file_access {
+  friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; }
+};
+
+#if FMT_MSC_VERSION
+template class file_access<file_access_tag, std::filebuf,
+                           &std::filebuf::_Myfile>;
+auto get_file(std::filebuf&) -> FILE*;
+#elif defined(_WIN32) && defined(_LIBCPP_VERSION)
+template class file_access<file_access_tag, std::__stdoutbuf<char>,
+                           &std::__stdoutbuf<char>::__file_>;
+auto get_file(std::__stdoutbuf<char>&) -> FILE*;
+#endif
+
+inline bool write_ostream_unicode(std::ostream& os, fmt::string_view data) {
+#if FMT_MSC_VERSION
+  if (auto* buf = dynamic_cast<std::filebuf*>(os.rdbuf()))
+    if (FILE* f = get_file(*buf)) return write_console(f, data);
+#elif defined(_WIN32) && defined(__GLIBCXX__)
+  auto* rdbuf = os.rdbuf();
+  FILE* c_file;
+  if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(rdbuf))
+    c_file = fbuf->file();
+  else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(rdbuf))
+    c_file = fbuf->file();
+  else
+    return false;
+  if (c_file) return write_console(c_file, data);
+#elif defined(_WIN32) && defined(_LIBCPP_VERSION)
+  if (auto* buf = dynamic_cast<std::__stdoutbuf<char>*>(os.rdbuf()))
+    if (FILE* f = get_file(*buf)) return write_console(f, data);
+#else
+  ignore_unused(os, data);
+#endif
+  return false;
+}
+inline bool write_ostream_unicode(std::wostream&,
+                                  fmt::basic_string_view<wchar_t>) {
+  return false;
+}
+
+// Write the content of buf to os.
+// It is a separate function rather than a part of vprint to simplify testing.
+template <typename Char>
+void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
+  const Char* buf_data = buf.data();
+  using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
+  unsigned_streamsize size = buf.size();
+  unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
+  do {
+    unsigned_streamsize n = size <= max_size ? size : max_size;
+    os.write(buf_data, static_cast<std::streamsize>(n));
+    buf_data += n;
+    size -= n;
+  } while (size != 0);
+}
+
+template <typename Char, typename T>
+void format_value(buffer<Char>& buf, const T& value,
+                  locale_ref loc = locale_ref()) {
+  auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
+  auto&& output = std::basic_ostream<Char>(&format_buf);
+#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
+  if (loc) output.imbue(loc.get<std::locale>());
+#endif
+  output << value;
+  output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
+}
+
+template <typename T> struct streamed_view { const T& value; };
+
+}  // namespace detail
+
+// Formats an object of type T that has an overloaded ostream operator<<.
+template <typename Char>
+struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
+  void set_debug_format() = delete;
+
+  template <typename T, typename OutputIt>
+  auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) const
+      -> OutputIt {
+    auto buffer = basic_memory_buffer<Char>();
+    format_value(buffer, value, ctx.locale());
+    return formatter<basic_string_view<Char>, Char>::format(
+        {buffer.data(), buffer.size()}, ctx);
+  }
+};
+
+using ostream_formatter = basic_ostream_formatter<char>;
+
+template <typename T, typename Char>
+struct formatter<detail::streamed_view<T>, Char>
+    : basic_ostream_formatter<Char> {
+  template <typename OutputIt>
+  auto format(detail::streamed_view<T> view,
+              basic_format_context<OutputIt, Char>& ctx) const -> OutputIt {
+    return basic_ostream_formatter<Char>::format(view.value, ctx);
+  }
+};
+
+/**
+  \rst
+  Returns a view that formats `value` via an ostream ``operator<<``.
+
+  **Example**::
+
+    fmt::print("Current thread id: {}\n",
+               fmt::streamed(std::this_thread::get_id()));
+  \endrst
+ */
+template <typename T>
+auto streamed(const T& value) -> detail::streamed_view<T> {
+  return {value};
+}
+
+namespace detail {
+
+// Formats an object of type T that has an overloaded ostream operator<<.
+template <typename T, typename Char>
+struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
+    : basic_ostream_formatter<Char> {
+  using basic_ostream_formatter<Char>::format;
+};
+
+inline void vprint_directly(std::ostream& os, string_view format_str,
+                            format_args args) {
+  auto buffer = memory_buffer();
+  detail::vformat_to(buffer, format_str, args);
+  detail::write_buffer(os, buffer);
+}
+
+}  // namespace detail
+
+FMT_MODULE_EXPORT template <typename Char>
+void vprint(std::basic_ostream<Char>& os,
+            basic_string_view<type_identity_t<Char>> format_str,
+            basic_format_args<buffer_context<type_identity_t<Char>>> args) {
+  auto buffer = basic_memory_buffer<Char>();
+  detail::vformat_to(buffer, format_str, args);
+  if (detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) return;
+  detail::write_buffer(os, buffer);
+}
+
+/**
+  \rst
+  Prints formatted data to the stream *os*.
+
+  **Example**::
+
+    fmt::print(cerr, "Don't {}!", "panic");
+  \endrst
+ */
+FMT_MODULE_EXPORT template <typename... T>
+void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
+  const auto& vargs = fmt::make_format_args(args...);
+  if (detail::is_utf8())
+    vprint(os, fmt, vargs);
+  else
+    detail::vprint_directly(os, fmt, vargs);
+}
+
+FMT_MODULE_EXPORT
+template <typename... Args>
+void print(std::wostream& os,
+           basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
+           Args&&... args) {
+  vprint(os, fmt, fmt::make_format_args<buffer_context<wchar_t>>(args...));
+}
+
+FMT_END_NAMESPACE
+
+#endif  // FMT_OSTREAM_H_
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/printf.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/printf.h
similarity index 94%
rename from wpiutil/src/main/native/fmtlib/include/fmt/printf.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/printf.h
index 19d550f..70a592d 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/printf.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/printf.h
@@ -10,7 +10,6 @@
 
 #include <algorithm>  // std::max
 #include <limits>     // std::numeric_limits
-#include <ostream>
 
 #include "format.h"
 
@@ -561,7 +560,7 @@
     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
     -> std::basic_string<Char> {
   basic_memory_buffer<Char> buffer;
-  vprintf(buffer, to_string_view(fmt), args);
+  vprintf(buffer, detail::to_string_view(fmt), args);
   return to_string(buffer);
 }
 
@@ -578,7 +577,8 @@
           typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
 inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {
   using context = basic_printf_context_t<Char>;
-  return vsprintf(to_string_view(fmt), fmt::make_format_args<context>(args...));
+  return vsprintf(detail::to_string_view(fmt),
+                  fmt::make_format_args<context>(args...));
 }
 
 template <typename S, typename Char = char_t<S>>
@@ -587,7 +587,7 @@
     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
     -> int {
   basic_memory_buffer<Char> buffer;
-  vprintf(buffer, to_string_view(fmt), args);
+  vprintf(buffer, detail::to_string_view(fmt), args);
   size_t size = buffer.size();
   return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
              ? -1
@@ -606,7 +606,7 @@
 template <typename S, typename... T, typename Char = char_t<S>>
 inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {
   using context = basic_printf_context_t<Char>;
-  return vfprintf(f, to_string_view(fmt),
+  return vfprintf(f, detail::to_string_view(fmt),
                   fmt::make_format_args<context>(args...));
 }
 
@@ -615,7 +615,7 @@
     const S& fmt,
     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
     -> int {
-  return vfprintf(stdout, to_string_view(fmt), args);
+  return vfprintf(stdout, detail::to_string_view(fmt), args);
 }
 
 /**
@@ -630,27 +630,10 @@
 template <typename S, typename... T, FMT_ENABLE_IF(detail::is_string<S>::value)>
 inline auto printf(const S& fmt, const T&... args) -> int {
   return vprintf(
-      to_string_view(fmt),
+      detail::to_string_view(fmt),
       fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...));
 }
 
-template <typename S, typename Char = char_t<S>>
-FMT_DEPRECATED auto vfprintf(
-    std::basic_ostream<Char>& os, const S& fmt,
-    basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args)
-    -> int {
-  basic_memory_buffer<Char> buffer;
-  vprintf(buffer, to_string_view(fmt), args);
-  os.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
-  return static_cast<int>(buffer.size());
-}
-template <typename S, typename... T, typename Char = char_t<S>>
-FMT_DEPRECATED auto fprintf(std::basic_ostream<Char>& os, const S& fmt,
-                            const T&... args) -> int {
-  return vfprintf(os, to_string_view(fmt),
-                  fmt::make_format_args<basic_printf_context_t<Char>>(args...));
-}
-
 FMT_MODULE_EXPORT_END
 FMT_END_NAMESPACE
 
diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ranges.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ranges.h
new file mode 100644
index 0000000..dea7d60
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/ranges.h
@@ -0,0 +1,722 @@
+// Formatting library for C++ - experimental range support
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+//
+// Copyright (c) 2018 - present, Remotion (Igor Schulz)
+// All Rights Reserved
+// {fmt} support for ranges, containers and types tuple interface.
+
+#ifndef FMT_RANGES_H_
+#define FMT_RANGES_H_
+
+#include <initializer_list>
+#include <tuple>
+#include <type_traits>
+
+#include "format.h"
+
+FMT_BEGIN_NAMESPACE
+
+namespace detail {
+
+template <typename RangeT, typename OutputIterator>
+OutputIterator copy(const RangeT& range, OutputIterator out) {
+  for (auto it = range.begin(), end = range.end(); it != end; ++it)
+    *out++ = *it;
+  return out;
+}
+
+template <typename OutputIterator>
+OutputIterator copy(const char* str, OutputIterator out) {
+  while (*str) *out++ = *str++;
+  return out;
+}
+
+template <typename OutputIterator>
+OutputIterator copy(char ch, OutputIterator out) {
+  *out++ = ch;
+  return out;
+}
+
+template <typename OutputIterator>
+OutputIterator copy(wchar_t ch, OutputIterator out) {
+  *out++ = ch;
+  return out;
+}
+
+// Returns true if T has a std::string-like interface, like std::string_view.
+template <typename T> class is_std_string_like {
+  template <typename U>
+  static auto check(U* p)
+      -> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
+  template <typename> static void check(...);
+
+ public:
+  static constexpr const bool value =
+      is_string<T>::value ||
+      std::is_convertible<T, std_string_view<char>>::value ||
+      !std::is_void<decltype(check<T>(nullptr))>::value;
+};
+
+template <typename Char>
+struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};
+
+template <typename T> class is_map {
+  template <typename U> static auto check(U*) -> typename U::mapped_type;
+  template <typename> static void check(...);
+
+ public:
+#ifdef FMT_FORMAT_MAP_AS_LIST
+  static constexpr const bool value = false;
+#else
+  static constexpr const bool value =
+      !std::is_void<decltype(check<T>(nullptr))>::value;
+#endif
+};
+
+template <typename T> class is_set {
+  template <typename U> static auto check(U*) -> typename U::key_type;
+  template <typename> static void check(...);
+
+ public:
+#ifdef FMT_FORMAT_SET_AS_LIST
+  static constexpr const bool value = false;
+#else
+  static constexpr const bool value =
+      !std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
+#endif
+};
+
+template <typename... Ts> struct conditional_helper {};
+
+template <typename T, typename _ = void> struct is_range_ : std::false_type {};
+
+#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1800
+
+#  define FMT_DECLTYPE_RETURN(val)  \
+    ->decltype(val) { return val; } \
+    static_assert(                  \
+        true, "")  // This makes it so that a semicolon is required after the
+                   // macro, which helps clang-format handle the formatting.
+
+// C array overload
+template <typename T, std::size_t N>
+auto range_begin(const T (&arr)[N]) -> const T* {
+  return arr;
+}
+template <typename T, std::size_t N>
+auto range_end(const T (&arr)[N]) -> const T* {
+  return arr + N;
+}
+
+template <typename T, typename Enable = void>
+struct has_member_fn_begin_end_t : std::false_type {};
+
+template <typename T>
+struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()),
+                                           decltype(std::declval<T>().end())>>
+    : std::true_type {};
+
+// Member function overload
+template <typename T>
+auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin());
+template <typename T>
+auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end());
+
+// ADL overload. Only participates in overload resolution if member functions
+// are not found.
+template <typename T>
+auto range_begin(T&& rng)
+    -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
+                   decltype(begin(static_cast<T&&>(rng)))> {
+  return begin(static_cast<T&&>(rng));
+}
+template <typename T>
+auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value,
+                                       decltype(end(static_cast<T&&>(rng)))> {
+  return end(static_cast<T&&>(rng));
+}
+
+template <typename T, typename Enable = void>
+struct has_const_begin_end : std::false_type {};
+template <typename T, typename Enable = void>
+struct has_mutable_begin_end : std::false_type {};
+
+template <typename T>
+struct has_const_begin_end<
+    T,
+    void_t<
+        decltype(detail::range_begin(std::declval<const remove_cvref_t<T>&>())),
+        decltype(detail::range_end(std::declval<const remove_cvref_t<T>&>()))>>
+    : std::true_type {};
+
+template <typename T>
+struct has_mutable_begin_end<
+    T, void_t<decltype(detail::range_begin(std::declval<T>())),
+              decltype(detail::range_end(std::declval<T>())),
+              enable_if_t<std::is_copy_constructible<T>::value>>>
+    : std::true_type {};
+
+template <typename T>
+struct is_range_<T, void>
+    : std::integral_constant<bool, (has_const_begin_end<T>::value ||
+                                    has_mutable_begin_end<T>::value)> {};
+#  undef FMT_DECLTYPE_RETURN
+#endif
+
+// tuple_size and tuple_element check.
+template <typename T> class is_tuple_like_ {
+  template <typename U>
+  static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
+  template <typename> static void check(...);
+
+ public:
+  static constexpr const bool value =
+      !std::is_void<decltype(check<T>(nullptr))>::value;
+};
+
+// Check for integer_sequence
+#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
+template <typename T, T... N>
+using integer_sequence = std::integer_sequence<T, N...>;
+template <size_t... N> using index_sequence = std::index_sequence<N...>;
+template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
+#else
+template <typename T, T... N> struct integer_sequence {
+  using value_type = T;
+
+  static FMT_CONSTEXPR size_t size() { return sizeof...(N); }
+};
+
+template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
+
+template <typename T, size_t N, T... Ns>
+struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
+template <typename T, T... Ns>
+struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
+
+template <size_t N>
+using make_index_sequence = make_integer_sequence<size_t, N>;
+#endif
+
+template <typename T>
+using tuple_index_sequence = make_index_sequence<std::tuple_size<T>::value>;
+
+template <typename T, typename C, bool = is_tuple_like_<T>::value>
+class is_tuple_formattable_ {
+ public:
+  static constexpr const bool value = false;
+};
+template <typename T, typename C> class is_tuple_formattable_<T, C, true> {
+  template <std::size_t... I>
+  static std::true_type check2(index_sequence<I...>,
+                               integer_sequence<bool, (I == I)...>);
+  static std::false_type check2(...);
+  template <std::size_t... I>
+  static decltype(check2(
+      index_sequence<I...>{},
+      integer_sequence<
+          bool, (is_formattable<typename std::tuple_element<I, T>::type,
+                                C>::value)...>{})) check(index_sequence<I...>);
+
+ public:
+  static constexpr const bool value =
+      decltype(check(tuple_index_sequence<T>{}))::value;
+};
+
+template <class Tuple, class F, size_t... Is>
+void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) noexcept {
+  using std::get;
+  // using free function get<I>(T) now.
+  const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
+  (void)_;  // blocks warnings
+}
+
+template <class T>
+FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(
+    T const&) {
+  return {};
+}
+
+template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
+  const auto indexes = get_indexes(tup);
+  for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
+}
+
+#if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920
+// Older MSVC doesn't get the reference type correctly for arrays.
+template <typename R> struct range_reference_type_impl {
+  using type = decltype(*detail::range_begin(std::declval<R&>()));
+};
+
+template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
+  using type = T&;
+};
+
+template <typename T>
+using range_reference_type = typename range_reference_type_impl<T>::type;
+#else
+template <typename Range>
+using range_reference_type =
+    decltype(*detail::range_begin(std::declval<Range&>()));
+#endif
+
+// We don't use the Range's value_type for anything, but we do need the Range's
+// reference type, with cv-ref stripped.
+template <typename Range>
+using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
+
+template <typename Range>
+using uncvref_first_type =
+    remove_cvref_t<decltype(std::declval<range_reference_type<Range>>().first)>;
+
+template <typename Range>
+using uncvref_second_type = remove_cvref_t<
+    decltype(std::declval<range_reference_type<Range>>().second)>;
+
+template <typename OutputIt> OutputIt write_delimiter(OutputIt out) {
+  *out++ = ',';
+  *out++ = ' ';
+  return out;
+}
+
+template <typename Char, typename OutputIt>
+auto write_range_entry(OutputIt out, basic_string_view<Char> str) -> OutputIt {
+  return write_escaped_string(out, str);
+}
+
+template <typename Char, typename OutputIt, typename T,
+          FMT_ENABLE_IF(std::is_convertible<T, std_string_view<char>>::value)>
+inline auto write_range_entry(OutputIt out, const T& str) -> OutputIt {
+  auto sv = std_string_view<Char>(str);
+  return write_range_entry<Char>(out, basic_string_view<Char>(sv));
+}
+
+template <typename Char, typename OutputIt, typename Arg,
+          FMT_ENABLE_IF(std::is_same<Arg, Char>::value)>
+OutputIt write_range_entry(OutputIt out, const Arg v) {
+  return write_escaped_char(out, v);
+}
+
+template <
+    typename Char, typename OutputIt, typename Arg,
+    FMT_ENABLE_IF(!is_std_string_like<typename std::decay<Arg>::type>::value &&
+                  !std::is_same<Arg, Char>::value)>
+OutputIt write_range_entry(OutputIt out, const Arg& v) {
+  return write<Char>(out, v);
+}
+
+}  // namespace detail
+
+template <typename T> struct is_tuple_like {
+  static constexpr const bool value =
+      detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
+};
+
+template <typename T, typename C> struct is_tuple_formattable {
+  static constexpr const bool value =
+      detail::is_tuple_formattable_<T, C>::value;
+};
+
+template <typename TupleT, typename Char>
+struct formatter<TupleT, Char,
+                 enable_if_t<fmt::is_tuple_like<TupleT>::value &&
+                             fmt::is_tuple_formattable<TupleT, Char>::value>> {
+ private:
+  basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
+  basic_string_view<Char> opening_bracket_ =
+      detail::string_literal<Char, '('>{};
+  basic_string_view<Char> closing_bracket_ =
+      detail::string_literal<Char, ')'>{};
+
+  // C++11 generic lambda for format().
+  template <typename FormatContext> struct format_each {
+    template <typename T> void operator()(const T& v) {
+      if (i > 0) out = detail::copy_str<Char>(separator, out);
+      out = detail::write_range_entry<Char>(out, v);
+      ++i;
+    }
+    int i;
+    typename FormatContext::iterator& out;
+    basic_string_view<Char> separator;
+  };
+
+ public:
+  FMT_CONSTEXPR formatter() {}
+
+  FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
+    separator_ = sep;
+  }
+
+  FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
+                                  basic_string_view<Char> close) {
+    opening_bracket_ = open;
+    closing_bracket_ = close;
+  }
+
+  template <typename ParseContext>
+  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+    return ctx.begin();
+  }
+
+  template <typename FormatContext = format_context>
+  auto format(const TupleT& values, FormatContext& ctx) const
+      -> decltype(ctx.out()) {
+    auto out = ctx.out();
+    out = detail::copy_str<Char>(opening_bracket_, out);
+    detail::for_each(values, format_each<FormatContext>{0, out, separator_});
+    out = detail::copy_str<Char>(closing_bracket_, out);
+    return out;
+  }
+};
+
+template <typename T, typename Char> struct is_range {
+  static constexpr const bool value =
+      detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
+      !std::is_convertible<T, std::basic_string<Char>>::value &&
+      !std::is_convertible<T, detail::std_string_view<Char>>::value;
+};
+
+namespace detail {
+template <typename Context> struct range_mapper {
+  using mapper = arg_mapper<Context>;
+
+  template <typename T,
+            FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
+  static auto map(T&& value) -> T&& {
+    return static_cast<T&&>(value);
+  }
+  template <typename T,
+            FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
+  static auto map(T&& value)
+      -> decltype(mapper().map(static_cast<T&&>(value))) {
+    return mapper().map(static_cast<T&&>(value));
+  }
+};
+
+template <typename Char, typename Element>
+using range_formatter_type = conditional_t<
+    is_formattable<Element, Char>::value,
+    formatter<remove_cvref_t<decltype(range_mapper<buffer_context<Char>>{}.map(
+                  std::declval<Element>()))>,
+              Char>,
+    fallback_formatter<Element, Char>>;
+
+template <typename R>
+using maybe_const_range =
+    conditional_t<has_const_begin_end<R>::value, const R, R>;
+
+// Workaround a bug in MSVC 2015 and earlier.
+#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
+template <typename R, typename Char>
+struct is_formattable_delayed
+    : disjunction<
+          is_formattable<uncvref_type<maybe_const_range<R>>, Char>,
+          has_fallback_formatter<uncvref_type<maybe_const_range<R>>, Char>> {};
+#endif
+
+}  // namespace detail
+
+template <typename T, typename Char, typename Enable = void>
+struct range_formatter;
+
+template <typename T, typename Char>
+struct range_formatter<
+    T, Char,
+    enable_if_t<conjunction<
+        std::is_same<T, remove_cvref_t<T>>,
+        disjunction<is_formattable<T, Char>,
+                    detail::has_fallback_formatter<T, Char>>>::value>> {
+ private:
+  detail::range_formatter_type<Char, T> underlying_;
+  bool custom_specs_ = false;
+  basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
+  basic_string_view<Char> opening_bracket_ =
+      detail::string_literal<Char, '['>{};
+  basic_string_view<Char> closing_bracket_ =
+      detail::string_literal<Char, ']'>{};
+
+  template <class U>
+  FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, int)
+      -> decltype(u.set_debug_format()) {
+    u.set_debug_format();
+  }
+
+  template <class U>
+  FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {}
+
+  FMT_CONSTEXPR void maybe_set_debug_format() {
+    maybe_set_debug_format(underlying_, 0);
+  }
+
+ public:
+  FMT_CONSTEXPR range_formatter() {}
+
+  FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type<Char, T>& {
+    return underlying_;
+  }
+
+  FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
+    separator_ = sep;
+  }
+
+  FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
+                                  basic_string_view<Char> close) {
+    opening_bracket_ = open;
+    closing_bracket_ = close;
+  }
+
+  template <typename ParseContext>
+  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+    auto it = ctx.begin();
+    auto end = ctx.end();
+    if (it == end || *it == '}') {
+      maybe_set_debug_format();
+      return it;
+    }
+
+    if (*it == 'n') {
+      set_brackets({}, {});
+      ++it;
+    }
+
+    if (*it == '}') {
+      maybe_set_debug_format();
+      return it;
+    }
+
+    if (*it != ':')
+      FMT_THROW(format_error("no other top-level range formatters supported"));
+
+    custom_specs_ = true;
+    ++it;
+    ctx.advance_to(it);
+    return underlying_.parse(ctx);
+  }
+
+  template <typename R, class FormatContext>
+  auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
+    detail::range_mapper<buffer_context<Char>> mapper;
+    auto out = ctx.out();
+    out = detail::copy_str<Char>(opening_bracket_, out);
+    int i = 0;
+    auto it = detail::range_begin(range);
+    auto end = detail::range_end(range);
+    for (; it != end; ++it) {
+      if (i > 0) out = detail::copy_str<Char>(separator_, out);
+      ;
+      ctx.advance_to(out);
+      out = underlying_.format(mapper.map(*it), ctx);
+      ++i;
+    }
+    out = detail::copy_str<Char>(closing_bracket_, out);
+    return out;
+  }
+};
+
+enum class range_format { disabled, map, set, sequence, string, debug_string };
+
+namespace detail {
+template <typename T> struct range_format_kind_ {
+  static constexpr auto value = std::is_same<range_reference_type<T>, T>::value
+                                    ? range_format::disabled
+                                : is_map<T>::value ? range_format::map
+                                : is_set<T>::value ? range_format::set
+                                                   : range_format::sequence;
+};
+
+template <range_format K, typename R, typename Char, typename Enable = void>
+struct range_default_formatter;
+
+template <range_format K>
+using range_format_constant = std::integral_constant<range_format, K>;
+
+template <range_format K, typename R, typename Char>
+struct range_default_formatter<
+    K, R, Char,
+    enable_if_t<(K == range_format::sequence || K == range_format::map ||
+                 K == range_format::set)>> {
+  using range_type = detail::maybe_const_range<R>;
+  range_formatter<detail::uncvref_type<range_type>, Char> underlying_;
+
+  FMT_CONSTEXPR range_default_formatter() { init(range_format_constant<K>()); }
+
+  FMT_CONSTEXPR void init(range_format_constant<range_format::set>) {
+    underlying_.set_brackets(detail::string_literal<Char, '{'>{},
+                             detail::string_literal<Char, '}'>{});
+  }
+
+  FMT_CONSTEXPR void init(range_format_constant<range_format::map>) {
+    underlying_.set_brackets(detail::string_literal<Char, '{'>{},
+                             detail::string_literal<Char, '}'>{});
+    underlying_.underlying().set_brackets({}, {});
+    underlying_.underlying().set_separator(
+        detail::string_literal<Char, ':', ' '>{});
+  }
+
+  FMT_CONSTEXPR void init(range_format_constant<range_format::sequence>) {}
+
+  template <typename ParseContext>
+  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+    return underlying_.parse(ctx);
+  }
+
+  template <typename FormatContext>
+  auto format(range_type& range, FormatContext& ctx) const
+      -> decltype(ctx.out()) {
+    return underlying_.format(range, ctx);
+  }
+};
+}  // namespace detail
+
+template <typename T, typename Char, typename Enable = void>
+struct range_format_kind
+    : conditional_t<
+          is_range<T, Char>::value, detail::range_format_kind_<T>,
+          std::integral_constant<range_format, range_format::disabled>> {};
+
+template <typename R, typename Char>
+struct formatter<
+    R, Char,
+    enable_if_t<conjunction<bool_constant<range_format_kind<R, Char>::value !=
+                                          range_format::disabled>
+// Workaround a bug in MSVC 2015 and earlier.
+#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
+                            ,
+                            detail::is_formattable_delayed<R, Char>
+#endif
+                            >::value>>
+    : detail::range_default_formatter<range_format_kind<R, Char>::value, R,
+                                      Char> {
+};
+
+template <typename Char, typename... T> struct tuple_join_view : detail::view {
+  const std::tuple<T...>& tuple;
+  basic_string_view<Char> sep;
+
+  tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
+      : tuple(t), sep{s} {}
+};
+
+template <typename Char, typename... T>
+using tuple_arg_join = tuple_join_view<Char, T...>;
+
+// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
+// support in tuple_join. It is disabled by default because of issues with
+// the dynamic width and precision.
+#ifndef FMT_TUPLE_JOIN_SPECIFIERS
+#  define FMT_TUPLE_JOIN_SPECIFIERS 0
+#endif
+
+template <typename Char, typename... T>
+struct formatter<tuple_join_view<Char, T...>, Char> {
+  template <typename ParseContext>
+  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+    return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
+  }
+
+  template <typename FormatContext>
+  auto format(const tuple_join_view<Char, T...>& value,
+              FormatContext& ctx) const -> typename FormatContext::iterator {
+    return do_format(value, ctx,
+                     std::integral_constant<size_t, sizeof...(T)>());
+  }
+
+ private:
+  std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
+
+  template <typename ParseContext>
+  FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
+                              std::integral_constant<size_t, 0>)
+      -> decltype(ctx.begin()) {
+    return ctx.begin();
+  }
+
+  template <typename ParseContext, size_t N>
+  FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
+                              std::integral_constant<size_t, N>)
+      -> decltype(ctx.begin()) {
+    auto end = ctx.begin();
+#if FMT_TUPLE_JOIN_SPECIFIERS
+    end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
+    if (N > 1) {
+      auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
+      if (end != end1)
+        FMT_THROW(format_error("incompatible format specs for tuple elements"));
+    }
+#endif
+    return end;
+  }
+
+  template <typename FormatContext>
+  auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
+                 std::integral_constant<size_t, 0>) const ->
+      typename FormatContext::iterator {
+    return ctx.out();
+  }
+
+  template <typename FormatContext, size_t N>
+  auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
+                 std::integral_constant<size_t, N>) const ->
+      typename FormatContext::iterator {
+    auto out = std::get<sizeof...(T) - N>(formatters_)
+                   .format(std::get<sizeof...(T) - N>(value.tuple), ctx);
+    if (N > 1) {
+      out = std::copy(value.sep.begin(), value.sep.end(), out);
+      ctx.advance_to(out);
+      return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
+    }
+    return out;
+  }
+};
+
+FMT_MODULE_EXPORT_BEGIN
+
+/**
+  \rst
+  Returns an object that formats `tuple` with elements separated by `sep`.
+
+  **Example**::
+
+    std::tuple<int, char> t = {1, 'a'};
+    fmt::print("{}", fmt::join(t, ", "));
+    // Output: "1, a"
+  \endrst
+ */
+template <typename... T>
+FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
+    -> tuple_join_view<char, T...> {
+  return {tuple, sep};
+}
+
+template <typename... T>
+FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,
+                        basic_string_view<wchar_t> sep)
+    -> tuple_join_view<wchar_t, T...> {
+  return {tuple, sep};
+}
+
+/**
+  \rst
+  Returns an object that formats `initializer_list` with elements separated by
+  `sep`.
+
+  **Example**::
+
+    fmt::print("{}", fmt::join({1, 2, 3}, ", "));
+    // Output: "1, 2, 3"
+  \endrst
+ */
+template <typename T>
+auto join(std::initializer_list<T> list, string_view sep)
+    -> join_view<const T*, const T*> {
+  return join(std::begin(list), std::end(list), sep);
+}
+
+FMT_MODULE_EXPORT_END
+FMT_END_NAMESPACE
+
+#endif  // FMT_RANGES_H_
diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/std.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/std.h
new file mode 100644
index 0000000..41d2b28
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/std.h
@@ -0,0 +1,171 @@
+// Formatting library for C++ - formatters for standard library types
+//
+// Copyright (c) 2012 - present, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#ifndef FMT_STD_H_
+#define FMT_STD_H_
+
+#include <thread>
+#include <type_traits>
+#include <utility>
+
+#include "ostream.h"
+
+#if FMT_HAS_INCLUDE(<version>)
+#  include <version>
+#endif
+// Checking FMT_CPLUSPLUS for warning suppression in MSVC.
+#if FMT_CPLUSPLUS >= 201703L
+#  if FMT_HAS_INCLUDE(<filesystem>)
+#    include <filesystem>
+#  endif
+#  if FMT_HAS_INCLUDE(<variant>)
+#    include <variant>
+#  endif
+#endif
+
+#ifdef __cpp_lib_filesystem
+FMT_BEGIN_NAMESPACE
+
+namespace detail {
+
+template <typename Char>
+void write_escaped_path(basic_memory_buffer<Char>& quoted,
+                        const std::filesystem::path& p) {
+  write_escaped_string<Char>(std::back_inserter(quoted), p.string<Char>());
+}
+#  ifdef _WIN32
+template <>
+inline void write_escaped_path<char>(basic_memory_buffer<char>& quoted,
+                                     const std::filesystem::path& p) {
+  auto s = p.u8string();
+  write_escaped_string<char>(
+      std::back_inserter(quoted),
+      string_view(reinterpret_cast<const char*>(s.c_str()), s.size()));
+}
+#  endif
+template <>
+inline void write_escaped_path<std::filesystem::path::value_type>(
+    basic_memory_buffer<std::filesystem::path::value_type>& quoted,
+    const std::filesystem::path& p) {
+  write_escaped_string<std::filesystem::path::value_type>(
+      std::back_inserter(quoted), p.native());
+}
+
+}  // namespace detail
+
+template <typename Char>
+struct formatter<std::filesystem::path, Char>
+    : formatter<basic_string_view<Char>> {
+  template <typename FormatContext>
+  auto format(const std::filesystem::path& p, FormatContext& ctx) const ->
+      typename FormatContext::iterator {
+    basic_memory_buffer<Char> quoted;
+    detail::write_escaped_path(quoted, p);
+    return formatter<basic_string_view<Char>>::format(
+        basic_string_view<Char>(quoted.data(), quoted.size()), ctx);
+  }
+};
+FMT_END_NAMESPACE
+#endif
+
+FMT_BEGIN_NAMESPACE
+template <typename Char>
+struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {};
+FMT_END_NAMESPACE
+
+#ifdef __cpp_lib_variant
+FMT_BEGIN_NAMESPACE
+template <typename Char> struct formatter<std::monostate, Char> {
+  template <typename ParseContext>
+  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+    return ctx.begin();
+  }
+
+  template <typename FormatContext>
+  auto format(const std::monostate&, FormatContext& ctx) const
+      -> decltype(ctx.out()) {
+    auto out = ctx.out();
+    out = detail::write<Char>(out, "monostate");
+    return out;
+  }
+};
+
+namespace detail {
+
+template <typename T>
+using variant_index_sequence =
+    std::make_index_sequence<std::variant_size<T>::value>;
+
+// variant_size and variant_alternative check.
+template <typename T, typename U = void>
+struct is_variant_like_ : std::false_type {};
+template <typename T>
+struct is_variant_like_<T, std::void_t<decltype(std::variant_size<T>::value)>>
+    : std::true_type {};
+
+// formattable element check
+template <typename T, typename C> class is_variant_formattable_ {
+  template <std::size_t... I>
+  static std::conjunction<
+      is_formattable<std::variant_alternative_t<I, T>, C>...>
+      check(std::index_sequence<I...>);
+
+ public:
+  static constexpr const bool value =
+      decltype(check(variant_index_sequence<T>{}))::value;
+};
+
+template <typename Char, typename OutputIt, typename T>
+auto write_variant_alternative(OutputIt out, const T& v) -> OutputIt {
+  if constexpr (is_string<T>::value)
+    return write_escaped_string<Char>(out, detail::to_string_view(v));
+  else if constexpr (std::is_same_v<T, Char>)
+    return write_escaped_char(out, v);
+  else
+    return write<Char>(out, v);
+}
+
+}  // namespace detail
+
+template <typename T> struct is_variant_like {
+  static constexpr const bool value = detail::is_variant_like_<T>::value;
+};
+
+template <typename T, typename C> struct is_variant_formattable {
+  static constexpr const bool value =
+      detail::is_variant_formattable_<T, C>::value;
+};
+
+template <typename Variant, typename Char>
+struct formatter<
+    Variant, Char,
+    std::enable_if_t<std::conjunction_v<
+        is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> {
+  template <typename ParseContext>
+  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
+    return ctx.begin();
+  }
+
+  template <typename FormatContext>
+  auto format(const Variant& value, FormatContext& ctx) const
+      -> decltype(ctx.out()) {
+    auto out = ctx.out();
+
+    out = detail::write<Char>(out, "variant(");
+    std::visit(
+        [&](const auto& v) {
+          out = detail::write_variant_alternative<Char>(out, v);
+        },
+        value);
+    *out++ = ')';
+    return out;
+  }
+};
+FMT_END_NAMESPACE
+#endif
+
+#endif  // FMT_STD_H_
diff --git a/wpiutil/src/main/native/fmtlib/include/fmt/xchar.h b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/xchar.h
similarity index 80%
rename from wpiutil/src/main/native/fmtlib/include/fmt/xchar.h
rename to wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/xchar.h
index 9acb893..fc3c67f 100644
--- a/wpiutil/src/main/native/fmtlib/include/fmt/xchar.h
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/include/fmt/xchar.h
@@ -9,7 +9,6 @@
 #define FMT_XCHAR_H_
 
 #include <cwchar>
-#include <tuple>
 
 #include "format.h"
 
@@ -30,9 +29,11 @@
 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
 // Workaround broken conversion on older gcc.
 template <typename... Args> using wformat_string = wstring_view;
+inline auto runtime(wstring_view s) -> wstring_view { return s; }
 #else
 template <typename... Args>
 using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
+inline auto runtime(wstring_view s) -> basic_runtime<wchar_t> { return {{s}}; }
 #endif
 
 template <> struct is_char<wchar_t> : std::true_type {};
@@ -47,12 +48,7 @@
 }
 
 inline namespace literals {
-constexpr auto operator"" _format(const wchar_t* s, size_t n)
-    -> detail::udl_formatter<wchar_t> {
-  return {{s, n}};
-}
-
-#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
+#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
 constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
   return {s};
 }
@@ -87,13 +83,19 @@
   return to_string(buffer);
 }
 
+template <typename... T>
+auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
+  return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
+}
+
 // Pass char_t as a default template parameter instead of using
 // std::basic_string<char_t<S>> to reduce the symbol size.
 template <typename S, typename... Args, typename Char = char_t<S>,
-          FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
+          FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
+                        !std::is_same<Char, wchar_t>::value)>
 auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> {
-  const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
-  return vformat(to_string_view(format_str), vargs);
+  return vformat(detail::to_string_view(format_str),
+                 fmt::make_format_args<buffer_context<Char>>(args...));
 }
 
 template <typename Locale, typename S, typename Char = char_t<S>,
@@ -103,7 +105,7 @@
     const Locale& loc, const S& format_str,
     basic_format_args<buffer_context<type_identity_t<Char>>> args)
     -> std::basic_string<Char> {
-  return detail::vformat(loc, to_string_view(format_str), args);
+  return detail::vformat(loc, detail::to_string_view(format_str), args);
 }
 
 template <typename Locale, typename S, typename... Args,
@@ -112,8 +114,8 @@
                             detail::is_exotic_char<Char>::value)>
 inline auto format(const Locale& loc, const S& format_str, Args&&... args)
     -> std::basic_string<Char> {
-  return detail::vformat(loc, to_string_view(format_str),
-                         fmt::make_args_checked<Args...>(format_str, args...));
+  return detail::vformat(loc, detail::to_string_view(format_str),
+                         fmt::make_format_args<buffer_context<Char>>(args...));
 }
 
 template <typename OutputIt, typename S, typename Char = char_t<S>,
@@ -123,7 +125,7 @@
                 basic_format_args<buffer_context<type_identity_t<Char>>> args)
     -> OutputIt {
   auto&& buf = detail::get_buffer<Char>(out);
-  detail::vformat_to(buf, to_string_view(format_str), args);
+  detail::vformat_to(buf, detail::to_string_view(format_str), args);
   return detail::get_iterator(buf);
 }
 
@@ -132,18 +134,8 @@
           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
                             detail::is_exotic_char<Char>::value)>
 inline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt {
-  const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);
-  return vformat_to(out, to_string_view(fmt), vargs);
-}
-
-template <typename S, typename... Args, typename Char, size_t SIZE,
-          typename Allocator, FMT_ENABLE_IF(detail::is_string<S>::value)>
-FMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf,
-                              const S& format_str, Args&&... args) ->
-    typename buffer_context<Char>::iterator {
-  const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
-  detail::vformat_to(buf, to_string_view(format_str), vargs, {});
-  return detail::buffer_appender<Char>(buf);
+  return vformat_to(out, detail::to_string_view(fmt),
+                    fmt::make_format_args<buffer_context<Char>>(args...));
 }
 
 template <typename Locale, typename S, typename OutputIt, typename... Args,
@@ -155,7 +147,8 @@
     OutputIt out, const Locale& loc, const S& format_str,
     basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt {
   auto&& buf = detail::get_buffer<Char>(out);
-  vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc));
+  vformat_to(buf, detail::to_string_view(format_str), args,
+             detail::locale_ref(loc));
   return detail::get_iterator(buf);
 }
 
@@ -167,8 +160,8 @@
 inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
                       Args&&... args) ->
     typename std::enable_if<enable, OutputIt>::type {
-  const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
-  return vformat_to(out, loc, to_string_view(format_str), vargs);
+  return vformat_to(out, loc, to_string_view(format_str),
+                    fmt::make_format_args<buffer_context<Char>>(args...));
 }
 
 template <typename OutputIt, typename Char, typename... Args,
@@ -190,16 +183,16 @@
                             detail::is_exotic_char<Char>::value)>
 inline auto format_to_n(OutputIt out, size_t n, const S& fmt,
                         const Args&... args) -> format_to_n_result<OutputIt> {
-  const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);
-  return vformat_to_n(out, n, to_string_view(fmt), vargs);
+  return vformat_to_n(out, n, detail::to_string_view(fmt),
+                      fmt::make_format_args<buffer_context<Char>>(args...));
 }
 
 template <typename S, typename... Args, typename Char = char_t<S>,
           FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
 inline auto formatted_size(const S& fmt, Args&&... args) -> size_t {
   detail::counting_buffer<Char> buf;
-  const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...);
-  detail::vformat_to(buf, to_string_view(fmt), vargs);
+  detail::vformat_to(buf, detail::to_string_view(fmt),
+                     fmt::make_format_args<buffer_context<Char>>(args...));
   return buf.count();
 }
 
diff --git a/wpiutil/src/main/native/thirdparty/fmtlib/src/format.cpp b/wpiutil/src/main/native/thirdparty/fmtlib/src/format.cpp
new file mode 100644
index 0000000..99b7e9d
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/src/format.cpp
@@ -0,0 +1,47 @@
+// Formatting library for C++
+//
+// Copyright (c) 2012 - 2016, Victor Zverovich
+// All rights reserved.
+//
+// For the license information refer to format.h.
+
+#include "fmt/format-inl.h"
+
+FMT_BEGIN_NAMESPACE
+namespace detail {
+
+template FMT_API auto dragonbox::to_decimal(float x) noexcept
+    -> dragonbox::decimal_fp<float>;
+template FMT_API auto dragonbox::to_decimal(double x) noexcept
+    -> dragonbox::decimal_fp<double>;
+
+#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
+template FMT_API locale_ref::locale_ref(const std::locale& loc);
+template FMT_API auto locale_ref::get<std::locale>() const -> std::locale;
+#endif
+
+// Explicit instantiations for char.
+
+template FMT_API auto thousands_sep_impl(locale_ref)
+    -> thousands_sep_result<char>;
+template FMT_API auto decimal_point_impl(locale_ref) -> char;
+
+template FMT_API void buffer<char>::append(const char*, const char*);
+
+// DEPRECATED!
+// There is no correspondent extern template in format.h because of
+// incompatibility between clang and gcc (#2377).
+template FMT_API void vformat_to(buffer<char>&, string_view,
+                                 basic_format_args<FMT_BUFFER_CONTEXT(char)>,
+                                 locale_ref);
+
+// Explicit instantiations for wchar_t.
+
+template FMT_API auto thousands_sep_impl(locale_ref)
+    -> thousands_sep_result<wchar_t>;
+template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
+
+template FMT_API void buffer<wchar_t>::append(const wchar_t*, const wchar_t*);
+
+}  // namespace detail
+FMT_END_NAMESPACE
diff --git a/wpiutil/src/main/native/fmtlib/src/os.cpp b/wpiutil/src/main/native/thirdparty/fmtlib/src/os.cpp
similarity index 90%
rename from wpiutil/src/main/native/fmtlib/src/os.cpp
rename to wpiutil/src/main/native/thirdparty/fmtlib/src/os.cpp
index 4eb3e1f..2c49951 100644
--- a/wpiutil/src/main/native/fmtlib/src/os.cpp
+++ b/wpiutil/src/main/native/thirdparty/fmtlib/src/os.cpp
@@ -35,9 +35,15 @@
 #    ifndef S_IRGRP
 #      define S_IRGRP 0
 #    endif
+#    ifndef S_IWGRP
+#      define S_IWGRP 0
+#    endif
 #    ifndef S_IROTH
 #      define S_IROTH 0
 #    endif
+#    ifndef S_IWOTH
+#      define S_IWOTH 0
+#    endif
 #  endif  // _WIN32
 #endif    // FMT_USE_FCNTL
 
@@ -45,10 +51,6 @@
 #  include <windows.h>
 #endif
 
-#ifdef fileno
-#  undef fileno
-#endif
-
 namespace {
 #ifdef _WIN32
 // Return type of read and write functions.
@@ -107,7 +109,7 @@
   unsigned long result_;
   wchar_t* message_;
 
-  static bool is_whitespace(wchar_t c) FMT_NOEXCEPT {
+  static bool is_whitespace(wchar_t c) noexcept {
     return c == L' ' || c == L'\n' || c == L'\r' || c == L'\t' || c == L'\0';
   }
 
@@ -126,15 +128,15 @@
     }
   }
   ~system_message() { LocalFree(message_); }
-  explicit operator bool() const FMT_NOEXCEPT { return result_ != 0; }
-  operator basic_string_view<wchar_t>() const FMT_NOEXCEPT {
+  explicit operator bool() const noexcept { return result_ != 0; }
+  operator basic_string_view<wchar_t>() const noexcept {
     return basic_string_view<wchar_t>(message_, result_);
   }
 };
 
 class utf8_system_category final : public std::error_category {
  public:
-  const char* name() const FMT_NOEXCEPT override { return "system"; }
+  const char* name() const noexcept override { return "system"; }
   std::string message(int error_code) const override {
     system_message msg(error_code);
     if (msg) {
@@ -149,7 +151,7 @@
 
 }  // namespace detail
 
-FMT_API const std::error_category& system_category() FMT_NOEXCEPT {
+FMT_API const std::error_category& system_category() noexcept {
   static const detail::utf8_system_category category;
   return category;
 }
@@ -161,13 +163,13 @@
 }
 
 void detail::format_windows_error(detail::buffer<char>& out, int error_code,
-                                  const char* message) FMT_NOEXCEPT {
+                                  const char* message) noexcept {
   FMT_TRY {
     system_message msg(error_code);
     if (msg) {
       utf16_to_utf8 utf8_message;
       if (utf8_message.convert(msg) == ERROR_SUCCESS) {
-        format_to(buffer_appender<char>(out), "{}: {}", message, utf8_message);
+        fmt::format_to(buffer_appender<char>(out), "{}: {}", message, utf8_message);
         return;
       }
     }
@@ -176,12 +178,12 @@
   format_error_code(out, error_code, message);
 }
 
-void report_windows_error(int error_code, const char* message) FMT_NOEXCEPT {
+void report_windows_error(int error_code, const char* message) noexcept {
   report_error(detail::format_windows_error, error_code, message);
 }
 #endif  // _WIN32
 
-buffered_file::~buffered_file() FMT_NOEXCEPT {
+buffered_file::~buffered_file() noexcept {
   if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
     report_system_error(errno, "cannot close file");
 }
@@ -200,11 +202,8 @@
   if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
 }
 
-// A macro used to prevent expansion of fileno on broken versions of MinGW.
-#define FMT_ARGS
-
-int buffered_file::fileno() const {
-  int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
+int buffered_file::descriptor() const {
+  int fd = FMT_POSIX_CALL(fileno(file_));
   if (fd == -1) FMT_THROW(system_error(errno, "cannot get file descriptor"));
   return fd;
 }
@@ -214,7 +213,8 @@
 #  ifdef _WIN32
   using mode_t = int;
 #  endif
-  mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+  constexpr mode_t mode =
+      S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
 #  if defined(_WIN32) && !defined(__MINGW32__)
   fd_ = -1;
   FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
@@ -225,7 +225,7 @@
     FMT_THROW(system_error(errno, "cannot open file {}", path.c_str()));
 }
 
-file::~file() FMT_NOEXCEPT {
+file::~file() noexcept {
   // Don't retry close in case of EINTR!
   // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
   if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
@@ -298,7 +298,7 @@
   }
 }
 
-void file::dup2(int fd, std::error_code& ec) FMT_NOEXCEPT {
+void file::dup2(int fd, std::error_code& ec) noexcept {
   int result = 0;
   FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
   if (result == -1) ec = std::error_code(errno, std::generic_category());
diff --git a/wpiutil/src/main/native/include/wpi/ghc/filesystem.hpp b/wpiutil/src/main/native/thirdparty/ghc/include/wpi/ghc/filesystem.hpp
similarity index 100%
rename from wpiutil/src/main/native/include/wpi/ghc/filesystem.hpp
rename to wpiutil/src/main/native/thirdparty/ghc/include/wpi/ghc/filesystem.hpp
diff --git a/wpiutil/src/main/native/cpp/json.cpp b/wpiutil/src/main/native/thirdparty/json/cpp/json.cpp
similarity index 100%
rename from wpiutil/src/main/native/cpp/json.cpp
rename to wpiutil/src/main/native/thirdparty/json/cpp/json.cpp
diff --git a/wpiutil/src/main/native/cpp/json_binary_reader.cpp b/wpiutil/src/main/native/thirdparty/json/cpp/json_binary_reader.cpp
similarity index 99%
rename from wpiutil/src/main/native/cpp/json_binary_reader.cpp
rename to wpiutil/src/main/native/thirdparty/json/cpp/json_binary_reader.cpp
index cee5e39..2081359 100644
--- a/wpiutil/src/main/native/cpp/json_binary_reader.cpp
+++ b/wpiutil/src/main/native/thirdparty/json/cpp/json_binary_reader.cpp
@@ -1384,7 +1384,7 @@
     return binary_reader(is).parse_cbor(strict);
 }
 
-json json::from_cbor(span<const uint8_t> arr, const bool strict)
+json json::from_cbor(std::span<const uint8_t> arr, const bool strict)
 {
     raw_mem_istream is(arr);
     return from_cbor(is, strict);
@@ -1395,7 +1395,7 @@
     return binary_reader(is).parse_msgpack(strict);
 }
 
-json json::from_msgpack(span<const uint8_t> arr, const bool strict)
+json json::from_msgpack(std::span<const uint8_t> arr, const bool strict)
 {
     raw_mem_istream is(arr);
     return from_msgpack(is, strict);
@@ -1406,7 +1406,7 @@
     return binary_reader(is).parse_ubjson(strict);
 }
 
-json json::from_ubjson(span<const uint8_t> arr, const bool strict)
+json json::from_ubjson(std::span<const uint8_t> arr, const bool strict)
 {
     raw_mem_istream is(arr);
     return from_ubjson(is, strict);
diff --git a/wpiutil/src/main/native/cpp/json_binary_writer.cpp b/wpiutil/src/main/native/thirdparty/json/cpp/json_binary_writer.cpp
similarity index 98%
rename from wpiutil/src/main/native/cpp/json_binary_writer.cpp
rename to wpiutil/src/main/native/thirdparty/json/cpp/json_binary_writer.cpp
index db23f8d..e25d478 100644
--- a/wpiutil/src/main/native/cpp/json_binary_writer.cpp
+++ b/wpiutil/src/main/native/thirdparty/json/cpp/json_binary_writer.cpp
@@ -813,7 +813,7 @@
         std::reverse(vec.begin(), vec.end());
     }
 
-    o << span{vec.data(), sizeof(NumberType)};
+    o << std::span{vec.data(), sizeof(NumberType)};
 }
 
 template<typename NumberType, typename std::enable_if<
@@ -1004,7 +1004,7 @@
     return result;
 }
 
-span<uint8_t> json::to_cbor(const json& j, std::vector<uint8_t>& buf)
+std::span<uint8_t> json::to_cbor(const json& j, std::vector<uint8_t>& buf)
 {
     buf.clear();
     raw_uvector_ostream os(buf);
@@ -1012,7 +1012,7 @@
     return os.array();
 }
 
-span<uint8_t> json::to_cbor(const json& j, SmallVectorImpl<uint8_t>& buf)
+std::span<uint8_t> json::to_cbor(const json& j, SmallVectorImpl<uint8_t>& buf)
 {
     buf.clear();
     raw_usvector_ostream os(buf);
@@ -1033,7 +1033,7 @@
     return result;
 }
 
-span<uint8_t> json::to_msgpack(const json& j, std::vector<uint8_t>& buf)
+std::span<uint8_t> json::to_msgpack(const json& j, std::vector<uint8_t>& buf)
 {
     buf.clear();
     raw_uvector_ostream os(buf);
@@ -1041,7 +1041,7 @@
     return os.array();
 }
 
-span<uint8_t> json::to_msgpack(const json& j, SmallVectorImpl<uint8_t>& buf)
+std::span<uint8_t> json::to_msgpack(const json& j, SmallVectorImpl<uint8_t>& buf)
 {
     buf.clear();
     raw_usvector_ostream os(buf);
@@ -1064,7 +1064,7 @@
     return result;
 }
 
-span<uint8_t> json::to_ubjson(const json& j, std::vector<uint8_t>& buf,
+std::span<uint8_t> json::to_ubjson(const json& j, std::vector<uint8_t>& buf,
                               const bool use_size, const bool use_type)
 {
     buf.clear();
@@ -1073,7 +1073,7 @@
     return os.array();
 }
 
-span<uint8_t> json::to_ubjson(const json& j, SmallVectorImpl<uint8_t>& buf,
+std::span<uint8_t> json::to_ubjson(const json& j, SmallVectorImpl<uint8_t>& buf,
                               const bool use_size, const bool use_type)
 {
     buf.clear();
diff --git a/wpiutil/src/main/native/cpp/json_parser.cpp b/wpiutil/src/main/native/thirdparty/json/cpp/json_parser.cpp
similarity index 99%
rename from wpiutil/src/main/native/cpp/json_parser.cpp
rename to wpiutil/src/main/native/thirdparty/json/cpp/json_parser.cpp
index db1ed11..3c29489 100644
--- a/wpiutil/src/main/native/cpp/json_parser.cpp
+++ b/wpiutil/src/main/native/thirdparty/json/cpp/json_parser.cpp
@@ -1921,11 +1921,11 @@
                         const parser_callback_t cb,
                         const bool allow_exceptions)
 {
-    raw_mem_istream is(span<const char>(s.data(), s.size()));
+    raw_mem_istream is(std::span<const char>(s.data(), s.size()));
     return parse(is, cb, allow_exceptions);
 }
 
-json json::parse(span<const uint8_t> arr,
+json json::parse(std::span<const uint8_t> arr,
                         const parser_callback_t cb,
                         const bool allow_exceptions)
 {
@@ -1944,11 +1944,11 @@
 
 bool json::accept(std::string_view s)
 {
-    raw_mem_istream is(span<const char>(s.data(), s.size()));
+    raw_mem_istream is(std::span<const char>(s.data(), s.size()));
     return parser(is).accept(true);
 }
 
-bool json::accept(span<const uint8_t> arr)
+bool json::accept(std::span<const uint8_t> arr)
 {
     raw_mem_istream is(arr);
     return parser(is).accept(true);
diff --git a/wpiutil/src/main/native/cpp/json_pointer.cpp b/wpiutil/src/main/native/thirdparty/json/cpp/json_pointer.cpp
similarity index 100%
rename from wpiutil/src/main/native/cpp/json_pointer.cpp
rename to wpiutil/src/main/native/thirdparty/json/cpp/json_pointer.cpp
diff --git a/wpiutil/src/main/native/cpp/json_serializer.cpp b/wpiutil/src/main/native/thirdparty/json/cpp/json_serializer.cpp
similarity index 100%
rename from wpiutil/src/main/native/cpp/json_serializer.cpp
rename to wpiutil/src/main/native/thirdparty/json/cpp/json_serializer.cpp
diff --git a/wpiutil/src/main/native/include/wpi/json.h b/wpiutil/src/main/native/thirdparty/json/include/wpi/json.h
similarity index 99%
rename from wpiutil/src/main/native/include/wpi/json.h
rename to wpiutil/src/main/native/thirdparty/json/include/wpi/json.h
index 1a4e410..1c07deb 100644
--- a/wpiutil/src/main/native/include/wpi/json.h
+++ b/wpiutil/src/main/native/thirdparty/json/include/wpi/json.h
@@ -43,7 +43,6 @@
 #include <algorithm> // all_of, copy, find, for_each, generate_n, min, reverse, remove, fill, none_of, transform
 #include <array> // array
 #include <cassert> // assert
-#include <ciso646> // and, not, or
 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
 #include <exception> // exception
@@ -52,6 +51,7 @@
 #include <iterator>
 #include <limits> // numeric_limits
 #include <memory> // allocator, shared_ptr, make_shared, addressof
+#include <span>
 #include <stdexcept> // runtime_error
 #include <string> // string, char_traits, stoi, to_string
 #include <string_view>
@@ -61,7 +61,6 @@
 #include <vector> // vector
 
 #include "wpi/StringMap.h"
-#include "wpi/span.h"
 
 namespace wpi
 {
@@ -1126,7 +1125,7 @@
     }
 
     template<typename BasicJsonType, typename T>
-    static void construct(BasicJsonType& j, span<T> arr)
+    static void construct(BasicJsonType& j, std::span<T> arr)
     {
         using std::begin;
         using std::end;
@@ -7015,7 +7014,7 @@
                             const parser_callback_t cb = nullptr,
                             const bool allow_exceptions = true);
 
-    static json parse(span<const uint8_t> arr,
+    static json parse(std::span<const uint8_t> arr,
                             const parser_callback_t cb = nullptr,
                             const bool allow_exceptions = true);
 
@@ -7028,7 +7027,7 @@
 
     static bool accept(std::string_view s);
 
-    static bool accept(span<const uint8_t> arr);
+    static bool accept(std::span<const uint8_t> arr);
 
     static bool accept(raw_istream& i);
 
@@ -7206,8 +7205,8 @@
     @since version 2.0.9
     */
     static std::vector<uint8_t> to_cbor(const json& j);
-    static span<uint8_t> to_cbor(const json& j, std::vector<uint8_t>& buf);
-    static span<uint8_t> to_cbor(const json& j, SmallVectorImpl<uint8_t>& buf);
+    static std::span<uint8_t> to_cbor(const json& j, std::vector<uint8_t>& buf);
+    static std::span<uint8_t> to_cbor(const json& j, SmallVectorImpl<uint8_t>& buf);
     static void to_cbor(raw_ostream& os, const json& j);
 
     /*!
@@ -7291,8 +7290,8 @@
     @since version 2.0.9
     */
     static std::vector<uint8_t> to_msgpack(const json& j);
-    static span<uint8_t> to_msgpack(const json& j, std::vector<uint8_t>& buf);
-    static span<uint8_t> to_msgpack(const json& j, SmallVectorImpl<uint8_t>& buf);
+    static std::span<uint8_t> to_msgpack(const json& j, std::vector<uint8_t>& buf);
+    static std::span<uint8_t> to_msgpack(const json& j, SmallVectorImpl<uint8_t>& buf);
     static void to_msgpack(raw_ostream& os, const json& j);
 
     /*!
@@ -7378,9 +7377,9 @@
     static std::vector<uint8_t> to_ubjson(const json& j,
                                           const bool use_size = false,
                                           const bool use_type = false);
-    static span<uint8_t> to_ubjson(const json& j, std::vector<uint8_t>& buf,
+    static std::span<uint8_t> to_ubjson(const json& j, std::vector<uint8_t>& buf,
                                    const bool use_size = false, const bool use_type = false);
-    static span<uint8_t> to_ubjson(const json& j, SmallVectorImpl<uint8_t>& buf,
+    static std::span<uint8_t> to_ubjson(const json& j, SmallVectorImpl<uint8_t>& buf,
                                    const bool use_size = false, const bool use_type = false);
     static void to_ubjson(raw_ostream& os, const json& j,
                           const bool use_size = false, const bool use_type = false);
@@ -7484,7 +7483,7 @@
     /*!
     @copydoc from_cbor(raw_istream&, const bool)
     */
-    static json from_cbor(span<const uint8_t> arr, const bool strict = true);
+    static json from_cbor(std::span<const uint8_t> arr, const bool strict = true);
 
     /*!
     @brief create a JSON value from an input in MessagePack format
@@ -7565,7 +7564,7 @@
     /*!
     @copydoc from_msgpack(raw_istream&, const bool)
     */
-    static json from_msgpack(span<const uint8_t> arr, const bool strict = true);
+    static json from_msgpack(std::span<const uint8_t> arr, const bool strict = true);
 
     /*!
     @brief create a JSON value from an input in UBJSON format
@@ -7623,7 +7622,7 @@
     static json from_ubjson(raw_istream& is,
                                   const bool strict = true);
 
-    static json from_ubjson(span<const uint8_t> arr, const bool strict = true);
+    static json from_ubjson(std::span<const uint8_t> arr, const bool strict = true);
 
     /// @}
 
diff --git a/wpiutil/src/main/native/include/wpi/json_serializer.h b/wpiutil/src/main/native/thirdparty/json/include/wpi/json_serializer.h
similarity index 100%
rename from wpiutil/src/main/native/include/wpi/json_serializer.h
rename to wpiutil/src/main/native/thirdparty/json/include/wpi/json_serializer.h
diff --git a/wpiutil/src/main/native/cpp/llvm/ConvertUTF.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ConvertUTF.cpp
similarity index 98%
rename from wpiutil/src/main/native/cpp/llvm/ConvertUTF.cpp
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ConvertUTF.cpp
index 3050e63..dbf41ab 100644
--- a/wpiutil/src/main/native/cpp/llvm/ConvertUTF.cpp
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ConvertUTF.cpp
@@ -1,9 +1,8 @@
 /*===--- ConvertUTF.c - Universal Character Names conversions ---------------===
  *
- *                     The LLVM Compiler Infrastructure
- *
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  *
  *===------------------------------------------------------------------------=*/
 /*
@@ -755,7 +754,7 @@
     }
 
     utf16.reserve(len + 1);
-    utf16.set_size(len);
+    utf16.resize_for_overwrite(len);
 
     len = ::MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, original.data(),
                                 original.size(), utf16.begin(), utf16.size());
@@ -796,7 +795,7 @@
     }
 
     converted.reserve(len);
-    converted.set_size(len);
+    converted.resize_for_overwrite(len);
 
     // Now do the actual conversion.
     len = ::WideCharToMultiByte(codepage, 0, utf16, utf16_len, converted.data(),
@@ -829,6 +828,6 @@
 
 #endif  // _WIN32
 
-} // namespace llvm
+} // namespace wpi
 
 ConvertUTF_RESTORE_WARNINGS
diff --git a/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ConvertUTFWrapper.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ConvertUTFWrapper.cpp
new file mode 100644
index 0000000..e95c04f
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ConvertUTFWrapper.cpp
@@ -0,0 +1,253 @@
+//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----===
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <span>
+#include "wpi/ConvertUTF.h"
+#include "wpi/SmallVector.h"
+#include "wpi/ErrorHandling.h"
+#include "wpi/SwapByteOrder.h"
+#include <string>
+#include <string_view>
+#include <vector>
+
+namespace wpi {
+
+bool ConvertUTF8toWide(unsigned WideCharWidth, std::string_view Source,
+                       char *&ResultPtr, const UTF8 *&ErrorPtr) {
+  assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4);
+  ConversionResult result = conversionOK;
+  // Copy the character std::span over.
+  if (WideCharWidth == 1) {
+    const UTF8 *Pos = reinterpret_cast<const UTF8*>(Source.data());
+    if (!isLegalUTF8String(&Pos, reinterpret_cast<const UTF8*>(Source.data() + Source.size()))) {
+      result = sourceIllegal;
+      ErrorPtr = Pos;
+    } else {
+      memcpy(ResultPtr, Source.data(), Source.size());
+      ResultPtr += Source.size();
+    }
+  } else if (WideCharWidth == 2) {
+    const UTF8 *sourceStart = (const UTF8*)Source.data();
+    // FIXME: Make the type of the result buffer correct instead of
+    // using reinterpret_cast.
+    UTF16 *targetStart = reinterpret_cast<UTF16*>(ResultPtr);
+    ConversionFlags flags = strictConversion;
+    result = ConvertUTF8toUTF16(
+        &sourceStart, sourceStart + Source.size(),
+        &targetStart, targetStart + Source.size(), flags);
+    if (result == conversionOK)
+      ResultPtr = reinterpret_cast<char*>(targetStart);
+    else
+      ErrorPtr = sourceStart;
+  } else if (WideCharWidth == 4) {
+    const UTF8 *sourceStart = (const UTF8*)Source.data();
+    // FIXME: Make the type of the result buffer correct instead of
+    // using reinterpret_cast.
+    UTF32 *targetStart = reinterpret_cast<UTF32*>(ResultPtr);
+    ConversionFlags flags = strictConversion;
+    result = ConvertUTF8toUTF32(
+        &sourceStart, sourceStart + Source.size(),
+        &targetStart, targetStart + Source.size(), flags);
+    if (result == conversionOK)
+      ResultPtr = reinterpret_cast<char*>(targetStart);
+    else
+      ErrorPtr = sourceStart;
+  }
+  assert((result != targetExhausted)
+         && "ConvertUTF8toUTFXX exhausted target buffer");
+  return result == conversionOK;
+}
+
+bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
+  const UTF32 *SourceStart = &Source;
+  const UTF32 *SourceEnd = SourceStart + 1;
+  UTF8 *TargetStart = reinterpret_cast<UTF8 *>(ResultPtr);
+  UTF8 *TargetEnd = TargetStart + 4;
+  ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd,
+                                           &TargetStart, TargetEnd,
+                                           strictConversion);
+  if (CR != conversionOK)
+    return false;
+
+  ResultPtr = reinterpret_cast<char*>(TargetStart);
+  return true;
+}
+
+bool hasUTF16ByteOrderMark(std::span<const char> S) {
+  return (S.size() >= 2 &&
+          ((S[0] == '\xff' && S[1] == '\xfe') ||
+           (S[0] == '\xfe' && S[1] == '\xff')));
+}
+
+bool convertUTF16ToUTF8String(std::span<const char> SrcBytes, SmallVectorImpl<char> &Out) {
+  assert(Out.empty());
+
+  // Error out on an uneven byte count.
+  if (SrcBytes.size() % 2)
+    return false;
+
+  // Avoid OOB by returning early on empty input.
+  if (SrcBytes.empty())
+    return true;
+
+  const UTF16 *Src = reinterpret_cast<const UTF16 *>(&*SrcBytes.begin());
+  const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(&*SrcBytes.begin() + SrcBytes.size());
+
+  assert((uintptr_t)Src % sizeof(UTF16) == 0);
+
+  // Byteswap if necessary.
+  std::vector<UTF16> ByteSwapped;
+  if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
+    ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
+    for (UTF16 &I : ByteSwapped)
+      I = wpi::ByteSwap_16(I);
+    Src = &ByteSwapped[0];
+    SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
+  }
+
+  // Skip the BOM for conversion.
+  if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE)
+    Src++;
+
+  // Just allocate enough space up front.  We'll shrink it later.  Allocate
+  // enough that we can fit a null terminator without reallocating.
+  Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
+  UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]);
+  UTF8 *DstEnd = Dst + Out.size();
+
+  ConversionResult CR =
+      ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
+  assert(CR != targetExhausted);
+
+  if (CR != conversionOK) {
+    Out.clear();
+    return false;
+  }
+
+  Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]);
+  Out.push_back(0);
+  Out.pop_back();
+  return true;
+}
+
+bool convertUTF16ToUTF8String(std::span<const UTF16> Src, SmallVectorImpl<char> &Out)
+{
+  return convertUTF16ToUTF8String(
+      std::span<const char>(reinterpret_cast<const char *>(Src.data()),
+      Src.size() * sizeof(UTF16)), Out);
+}
+
+bool convertUTF8ToUTF16String(std::string_view SrcUTF8,
+                              SmallVectorImpl<UTF16> &DstUTF16) {
+  assert(DstUTF16.empty());
+
+  // Avoid OOB by returning early on empty input.
+  if (SrcUTF8.empty()) {
+    DstUTF16.push_back(0);
+    DstUTF16.pop_back();
+    return true;
+  }
+
+  const UTF8 *Src = reinterpret_cast<const UTF8 *>(SrcUTF8.data());
+  const UTF8 *SrcEnd = reinterpret_cast<const UTF8 *>(SrcUTF8.data() + SrcUTF8.size());
+
+  // Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding
+  // as UTF-16 should always require the same amount or less code units than the
+  // UTF-8 encoding.  Allocate one extra byte for the null terminator though,
+  // so that someone calling DstUTF16.data() gets a null terminated string.
+  // We resize down later so we don't have to worry that this over allocates.
+  DstUTF16.resize(SrcUTF8.size()+1);
+  UTF16 *Dst = &DstUTF16[0];
+  UTF16 *DstEnd = Dst + DstUTF16.size();
+
+  ConversionResult CR =
+      ConvertUTF8toUTF16(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
+  assert(CR != targetExhausted);
+
+  if (CR != conversionOK) {
+    DstUTF16.clear();
+    return false;
+  }
+
+  DstUTF16.resize(Dst - &DstUTF16[0]);
+  DstUTF16.push_back(0);
+  DstUTF16.pop_back();
+  return true;
+}
+
+static_assert(sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 ||
+                  sizeof(wchar_t) == 4,
+              "Expected wchar_t to be 1, 2, or 4 bytes");
+
+template <typename TResult>
+static inline bool ConvertUTF8toWideInternal(std::string_view Source,
+                                             TResult &Result) {
+  // Even in the case of UTF-16, the number of bytes in a UTF-8 string is
+  // at least as large as the number of elements in the resulting wide
+  // string, because surrogate pairs take at least 4 bytes in UTF-8.
+  Result.resize(Source.size() + 1);
+  char *ResultPtr = reinterpret_cast<char *>(&Result[0]);
+  const UTF8 *ErrorPtr;
+  if (!ConvertUTF8toWide(sizeof(wchar_t), Source, ResultPtr, ErrorPtr)) {
+    Result.clear();
+    return false;
+  }
+  Result.resize(reinterpret_cast<wchar_t *>(ResultPtr) - &Result[0]);
+  return true;
+}
+
+bool ConvertUTF8toWide(std::string_view Source, std::wstring &Result) {
+  return ConvertUTF8toWideInternal(Source, Result);
+}
+
+bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
+  if (!Source) {
+    Result.clear();
+    return true;
+  }
+  return ConvertUTF8toWide(std::string_view(Source), Result);
+}
+
+bool convertWideToUTF8(const std::wstring &Source, SmallVectorImpl<char> &Result) {
+  if (sizeof(wchar_t) == 1) {
+    const UTF8 *Start = reinterpret_cast<const UTF8 *>(Source.data());
+    const UTF8 *End =
+        reinterpret_cast<const UTF8 *>(Source.data() + Source.size());
+    if (!isLegalUTF8String(&Start, End))
+      return false;
+    Result.resize(Source.size());
+    memcpy(&Result[0], Source.data(), Source.size());
+    return true;
+  } else if (sizeof(wchar_t) == 2) {
+    return convertUTF16ToUTF8String(
+        std::span<const UTF16>(reinterpret_cast<const UTF16 *>(Source.data()),
+                              Source.size()),
+        Result);
+  } else if (sizeof(wchar_t) == 4) {
+    const UTF32 *Start = reinterpret_cast<const UTF32 *>(Source.data());
+    const UTF32 *End =
+        reinterpret_cast<const UTF32 *>(Source.data() + Source.size());
+    Result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * Source.size());
+    UTF8 *ResultPtr = reinterpret_cast<UTF8 *>(&Result[0]);
+    UTF8 *ResultEnd = reinterpret_cast<UTF8 *>(&Result[0] + Result.size());
+    if (ConvertUTF32toUTF8(&Start, End, &ResultPtr, ResultEnd,
+                           strictConversion) == conversionOK) {
+      Result.resize(reinterpret_cast<char *>(ResultPtr) - &Result[0]);
+      return true;
+    } else {
+      Result.clear();
+      return false;
+    }
+  } else {
+    wpi_unreachable(
+        "Control should never reach this point; see static_assert further up");
+  }
+}
+
+} // end namespace wpi
+
diff --git a/wpiutil/src/main/native/cpp/llvm/ErrorHandling.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ErrorHandling.cpp
similarity index 85%
rename from wpiutil/src/main/native/cpp/llvm/ErrorHandling.cpp
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ErrorHandling.cpp
index 22ae636..ea89b38 100644
--- a/wpiutil/src/main/native/cpp/llvm/ErrorHandling.cpp
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/ErrorHandling.cpp
@@ -1,9 +1,8 @@
 //===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -14,10 +13,10 @@
 
 #include "wpi/ErrorHandling.h"
 #include "wpi/SmallVector.h"
+#include "wpi/Errc.h"
 #include "wpi/WindowsError.h"
 #include "fmt/format.h"
 #include <cassert>
-#include <cstdio>
 #include <cstdlib>
 #include <mutex>
 #include <new>
@@ -25,7 +24,6 @@
 #ifndef _WIN32
 #include <unistd.h>
 #endif
-
 #if defined(_MSC_VER)
 #include <io.h>
 #endif
@@ -53,7 +51,7 @@
 static std::mutex BadAllocErrorHandlerMutex;
 
 void wpi::install_fatal_error_handler(fatal_error_handler_t handler,
-                                      void *user_data) {
+                                       void *user_data) {
   std::scoped_lock Lock(ErrorHandlerMutex);
   assert(!ErrorHandler && "Error handler already registered!\n");
   ErrorHandler = handler;
@@ -86,7 +84,7 @@
   }
 
   if (handler) {
-    handler(handlerData, std::string{Reason}, GenCrashDiag);
+    handler(handlerData, std::string{Reason}.c_str(), GenCrashDiag);
   } else {
     fmt::print(stderr, "LLVM ERROR: {}\n", Reason);
   }
@@ -95,7 +93,7 @@
 }
 
 void wpi::install_bad_alloc_error_handler(fatal_error_handler_t handler,
-                                          void *user_data) {
+                                           void *user_data) {
   std::scoped_lock Lock(BadAllocErrorHandlerMutex);
   assert(!ErrorHandler && "Bad alloc error handler already registered!\n");
   BadAllocErrorHandler = handler;
@@ -126,13 +124,17 @@
 
   // Don't call the normal error handler. It may allocate memory. Directly write
   // an OOM to stderr and abort.
-  char OOMMessage[] = "LLVM ERROR: out of memory\n";
+  const char *OOMMessage = "LLVM ERROR: out of memory\n";
+  const char *Newline = "\n";
 #ifdef _WIN32
-  int written = ::_write(2, OOMMessage, strlen(OOMMessage));
+  (void)!::_write(2, OOMMessage, strlen(OOMMessage));
+  (void)!::_write(2, Reason, strlen(Reason));
+  (void)!::_write(2, Newline, strlen(Newline));
 #else
-  ssize_t written = ::write(2, OOMMessage, strlen(OOMMessage));
+  (void)!::write(2, OOMMessage, strlen(OOMMessage));
+  (void)!::write(2, Reason, strlen(Reason));
+  (void)!::write(2, Newline, strlen(Newline));
 #endif
-  (void)written;
   abort();
 }
 
@@ -142,28 +144,17 @@
   wpi::report_bad_alloc_error("Allocation failed");
 }
 
-// Installs new handler that causes crash on allocation failure. It does not
-// need to be called explicitly, if this file is linked to application, because
-// in this case it is called during construction of 'new_handler_installer'.
+// Installs new handler that causes crash on allocation failure. It is called by
+// InitLLVM.
 void wpi::install_out_of_memory_new_handler() {
-  static bool out_of_memory_new_handler_installed = false;
-  if (!out_of_memory_new_handler_installed) {
-    std::set_new_handler(out_of_memory_new_handler);
-    out_of_memory_new_handler_installed = true;
-  }
+  std::new_handler old = std::set_new_handler(out_of_memory_new_handler);
+  (void)old;
+  assert((old == nullptr || old == out_of_memory_new_handler) &&
+         "new-handler already installed");
 }
 
-// Static object that causes installation of 'out_of_memory_new_handler' before
-// execution of 'main'.
-static class NewHandlerInstaller {
-public:
-  NewHandlerInstaller() {
-    install_out_of_memory_new_handler();
-  }
-} new_handler_installer;
-
 void wpi::wpi_unreachable_internal(const char *msg, const char *file,
-                                   unsigned line) {
+                                     unsigned line) {
   // This code intentionally doesn't call the ErrorHandler callback, because
   // wpi_unreachable is intended to be used to indicate "impossible"
   // situations, and not legitimate runtime errors.
@@ -172,7 +163,7 @@
   std::fputs("UNREACHABLE executed", stderr);
   if (file)
     fmt::print(stderr, " at {}:{}", file, line);
-  fmt::print(stderr, "{}", "!\n");
+  fmt::print(stderr, "!\n");
   abort();
 #ifdef LLVM_BUILTIN_UNREACHABLE
   // Windows systems and possibly others don't declare abort() to be noreturn,
@@ -183,7 +174,6 @@
 
 #ifdef _WIN32
 
-#include <system_error>
 #include <winerror.h>
 
 // I'd rather not double the line count of the following.
@@ -195,7 +185,10 @@
   switch (EV) {
     MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
     MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
+    MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
+    MAP_ERR_TO_COND(ERROR_BAD_PATHNAME, no_such_file_or_directory);
     MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
+    MAP_ERR_TO_COND(ERROR_BROKEN_PIPE, broken_pipe);
     MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
     MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
     MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
@@ -217,18 +210,20 @@
     MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
     MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
     MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
+    MAP_ERR_TO_COND(ERROR_INVALID_PARAMETER, invalid_argument);
     MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
     MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
     MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
     MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
     MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
     MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
+    MAP_ERR_TO_COND(ERROR_NOT_SUPPORTED, not_supported);
     MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
     MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
     MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
     MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
-    MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
     MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
+    MAP_ERR_TO_COND(ERROR_REPARSE_TAG_INVALID, invalid_argument);
     MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
     MAP_ERR_TO_COND(ERROR_SEEK, io_error);
     MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
diff --git a/wpiutil/src/main/native/cpp/llvm/Hashing.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/Hashing.cpp
similarity index 82%
rename from wpiutil/src/main/native/cpp/llvm/Hashing.cpp
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/Hashing.cpp
index e916751..a719d3f 100644
--- a/wpiutil/src/main/native/cpp/llvm/Hashing.cpp
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/Hashing.cpp
@@ -1,9 +1,8 @@
 //===-------------- lib/Support/Hashing.cpp -------------------------------===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
diff --git a/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/MemAlloc.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/MemAlloc.cpp
new file mode 100644
index 0000000..e2c662c
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/MemAlloc.cpp
@@ -0,0 +1,35 @@
+//===- MemAlloc.cpp - Memory allocation functions -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "wpi/MemAlloc.h"
+#include <new>
+
+// These are out of line to have __cpp_aligned_new not affect ABI.
+
+LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+wpi::allocate_buffer(size_t Size, size_t Alignment) {
+  return ::operator new(Size
+#ifdef __cpp_aligned_new
+                        ,
+                        std::align_val_t(Alignment)
+#endif
+  );
+}
+
+void wpi::deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
+  ::operator delete(Ptr
+#ifdef __cpp_sized_deallocation
+                    ,
+                    Size
+#endif
+#ifdef __cpp_aligned_new
+                    ,
+                    std::align_val_t(Alignment)
+#endif
+  );
+}
diff --git a/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/MemoryBuffer.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/MemoryBuffer.cpp
new file mode 100644
index 0000000..5beeb38
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/MemoryBuffer.cpp
@@ -0,0 +1,522 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the MemoryBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "wpi/MemoryBuffer.h"
+
+#ifdef _MSC_VER
+// no matching operator delete
+#pragma warning(disable : 4291)
+#endif
+
+#ifdef _WIN32
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>  // NOLINT(build/include_order)
+
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef _MSC_VER
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+#include <new>
+#include <system_error>
+
+#include "wpi/Errc.h"
+#include "wpi/Errno.h"
+#include "wpi/MappedFileRegion.h"
+#include "wpi/MathExtras.h"
+#include "wpi/SmallVector.h"
+#include "wpi/SmallVectorMemoryBuffer.h"
+#include "wpi/fs.h"
+
+#ifdef _WIN32
+#include "wpi/WindowsError.h"
+#endif
+
+using namespace wpi;
+
+//===----------------------------------------------------------------------===//
+// MemoryBuffer implementation itself.
+//===----------------------------------------------------------------------===//
+
+MemoryBuffer::~MemoryBuffer() {}
+
+/// init - Initialize this MemoryBuffer as a reference to externally allocated
+/// memory.
+void MemoryBuffer::Init(const uint8_t* bufStart, const uint8_t* bufEnd) {
+  m_bufferStart = bufStart;
+  m_bufferEnd = bufEnd;
+}
+
+//===----------------------------------------------------------------------===//
+// MemoryBufferMem implementation.
+//===----------------------------------------------------------------------===//
+
+/// CopyStringRef - Copies contents of a StringRef into a block of memory and
+/// null-terminates it.
+static void CopyStringView(uint8_t* memory, std::string_view data) {
+  if (!data.empty()) {
+    std::memcpy(memory, data.data(), data.size());
+  }
+  memory[data.size()] = 0;  // Null terminate string.
+}
+
+namespace {
+struct NamedBufferAlloc {
+  std::string_view name;
+  explicit NamedBufferAlloc(std::string_view name) : name(name) {}
+};
+}  // namespace
+
+void* operator new(size_t N, NamedBufferAlloc alloc) {
+  uint8_t* mem = static_cast<uint8_t*>(operator new(N + alloc.name.size() + 1));
+  CopyStringView(mem + N, alloc.name);
+  return mem;
+}
+
+namespace {
+/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
+template <typename MB>
+class MemoryBufferMem : public MB {
+ public:
+  explicit MemoryBufferMem(std::span<const uint8_t> inputData) {
+    MemoryBuffer::Init(inputData.data(), inputData.data() + inputData.size());
+  }
+
+  /// Disable sized deallocation for MemoryBufferMem, because it has
+  /// tail-allocated data.
+  void operator delete(void* p) { ::operator delete(p); }  // NOLINT
+
+  std::string_view GetBufferIdentifier() const override {
+    // The name is stored after the class itself.
+    return std::string_view(reinterpret_cast<const char*>(this + 1));
+  }
+
+  MemoryBuffer::BufferKind GetBufferKind() const override {
+    return MemoryBuffer::MemoryBuffer_Malloc;
+  }
+};
+}  // namespace
+
+template <typename MB>
+static std::unique_ptr<MB> GetFileAux(std::string_view filename,
+                                      std::error_code& ec, int64_t fileSize,
+                                      uint64_t mapSize, uint64_t offset);
+
+std::unique_ptr<MemoryBuffer> MemoryBuffer::GetMemBuffer(
+    std::span<const uint8_t> inputData, std::string_view bufferName) {
+  auto* ret = new (NamedBufferAlloc(bufferName))
+      MemoryBufferMem<MemoryBuffer>(inputData);
+  return std::unique_ptr<MemoryBuffer>(ret);
+}
+
+std::unique_ptr<MemoryBuffer> MemoryBuffer::GetMemBuffer(MemoryBufferRef ref) {
+  return std::unique_ptr<MemoryBuffer>(
+      GetMemBuffer(ref.GetBuffer(), ref.GetBufferIdentifier()));
+}
+
+static std::unique_ptr<WritableMemoryBuffer> GetMemBufferCopyImpl(
+    std::span<const uint8_t> inputData, std::string_view bufferName,
+    std::error_code& ec) {
+  auto buf =
+      WritableMemoryBuffer::GetNewUninitMemBuffer(inputData.size(), bufferName);
+  if (!buf) {
+    ec = make_error_code(errc::not_enough_memory);
+    return nullptr;
+  }
+  std::memcpy(buf->begin(), inputData.data(), inputData.size());
+  return buf;
+}
+
+std::unique_ptr<MemoryBuffer> MemoryBuffer::GetMemBufferCopy(
+    std::span<const uint8_t> inputData, std::string_view bufferName) {
+  std::error_code ec;
+  return GetMemBufferCopyImpl(inputData, bufferName, ec);
+}
+
+std::unique_ptr<MemoryBuffer> MemoryBuffer::GetFileSlice(
+    std::string_view filePath, std::error_code& ec, uint64_t mapSize,
+    uint64_t offset) {
+  return GetFileAux<MemoryBuffer>(filePath, ec, -1, mapSize, offset);
+}
+
+//===----------------------------------------------------------------------===//
+// MemoryBuffer::getFile implementation.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+template <typename MB>
+constexpr auto kMapMode = MappedFileRegion::kReadOnly;
+template <>
+constexpr auto kMapMode<MemoryBuffer> = MappedFileRegion::kReadOnly;
+template <>
+constexpr auto kMapMode<WritableMemoryBuffer> = MappedFileRegion::kPriv;
+template <>
+constexpr auto kMapMode<WriteThroughMemoryBuffer> =
+    MappedFileRegion::kReadWrite;
+
+/// Memory maps a file descriptor using MappedFileRegion.
+///
+/// This handles converting the offset into a legal offset on the platform.
+template <typename MB>
+class MemoryBufferMMapFile : public MB {
+  MappedFileRegion m_mfr;
+
+  static uint64_t getLegalMapOffset(uint64_t offset) {
+    return offset & ~(MappedFileRegion::GetAlignment() - 1);
+  }
+
+  static uint64_t getLegalMapSize(uint64_t len, uint64_t offset) {
+    return len + (offset - getLegalMapOffset(offset));
+  }
+
+  const uint8_t* getStart(uint64_t len, uint64_t offset) {
+    return m_mfr.const_data() + (offset - getLegalMapOffset(offset));
+  }
+
+ public:
+  MemoryBufferMMapFile(fs::file_t f, uint64_t len, uint64_t offset,
+                       std::error_code& ec)
+      : m_mfr(f, getLegalMapSize(len, offset), getLegalMapOffset(offset),
+              kMapMode<MB>, ec) {
+    if (!ec) {
+      const uint8_t* Start = getStart(len, offset);
+      MemoryBuffer::Init(Start, Start + len);
+    }
+  }
+
+  /// Disable sized deallocation for MemoryBufferMMapFile, because it has
+  /// tail-allocated data.
+  void operator delete(void* p) { ::operator delete(p); }  // NOLINT
+
+  std::string_view GetBufferIdentifier() const override {
+    // The name is stored after the class itself.
+    return std::string_view(reinterpret_cast<const char*>(this + 1));
+  }
+
+  MemoryBuffer::BufferKind GetBufferKind() const override {
+    return MemoryBuffer::MemoryBuffer_MMap;
+  }
+};
+}  // namespace
+
+static std::unique_ptr<WritableMemoryBuffer> GetMemoryBufferForStream(
+    fs::file_t f, std::string_view bufferName, std::error_code& ec) {
+  constexpr size_t ChunkSize = 4096 * 4;
+  SmallVector<uint8_t, ChunkSize> buffer;
+#ifdef _WIN32
+  DWORD readBytes;
+#else
+  ssize_t readBytes;
+#endif
+  // Read into Buffer until we hit EOF.
+  do {
+    buffer.resize_for_overwrite(buffer.size() + ChunkSize);
+#ifdef _WIN32
+    if (!ReadFile(f, buffer.end(), ChunkSize, &readBytes, nullptr)) {
+      ec = mapWindowsError(GetLastError());
+      return nullptr;
+    }
+#else
+    readBytes = sys::RetryAfterSignal(-1, ::read, f, buffer.end(), ChunkSize);
+    if (readBytes == -1) {
+      ec = std::error_code(errno, std::generic_category());
+      return nullptr;
+    }
+#endif
+  } while (readBytes != 0);
+
+  return GetMemBufferCopyImpl(buffer, bufferName, ec);
+}
+
+std::unique_ptr<MemoryBuffer> MemoryBuffer::GetFile(std::string_view filename,
+                                                    std::error_code& ec,
+                                                    int64_t fileSize) {
+  return GetFileAux<MemoryBuffer>(filename, ec, fileSize, fileSize, 0);
+}
+
+template <typename MB>
+static std::unique_ptr<MB> GetOpenFileImpl(fs::file_t f,
+                                           std::string_view filename,
+                                           std::error_code& ec,
+                                           uint64_t fileSize, uint64_t mapSize,
+                                           int64_t offset);
+
+template <typename MB>
+static std::unique_ptr<MB> GetFileAux(std::string_view filename,
+                                      std::error_code& ec, int64_t fileSize,
+                                      uint64_t mapSize, uint64_t offset) {
+  fs::file_t F = fs::OpenFileForRead(filename, ec, fs::OF_None);
+  if (ec) {
+    return nullptr;
+  }
+
+  auto Ret = GetOpenFileImpl<MB>(F, filename, ec, fileSize, mapSize, offset);
+  fs::CloseFile(F);
+  return Ret;
+}
+
+std::unique_ptr<WritableMemoryBuffer> WritableMemoryBuffer::GetFile(
+    std::string_view filename, std::error_code& ec, int64_t fileSize) {
+  return GetFileAux<WritableMemoryBuffer>(filename, ec, fileSize, fileSize, 0);
+}
+
+std::unique_ptr<WritableMemoryBuffer> WritableMemoryBuffer::GetFileSlice(
+    std::string_view filename, std::error_code& ec, uint64_t mapSize,
+    uint64_t offset) {
+  return GetFileAux<WritableMemoryBuffer>(filename, ec, -1, mapSize, offset);
+}
+
+std::unique_ptr<WritableMemoryBuffer>
+WritableMemoryBuffer::GetNewUninitMemBuffer(size_t size,
+                                            std::string_view bufferName) {
+  using MemBuffer = MemoryBufferMem<WritableMemoryBuffer>;
+  // Allocate space for the MemoryBuffer, the data and the name. It is important
+  // that MemoryBuffer and data are aligned so PointerIntPair works with them.
+  // TODO: Is 16-byte alignment enough?  We copy small object files with large
+  // alignment expectations into this buffer.
+  size_t alignedStringLen =
+      alignTo(sizeof(MemBuffer) + bufferName.size() + 1, 16);
+  size_t realLen = alignedStringLen + size + 1;
+  uint8_t* mem = static_cast<uint8_t*>(operator new(realLen, std::nothrow));
+  if (!mem) {
+    return nullptr;
+  }
+
+  // The name is stored after the class itself.
+  CopyStringView(mem + sizeof(MemBuffer), bufferName);
+
+  // The buffer begins after the name and must be aligned.
+  uint8_t* buf = mem + alignedStringLen;
+  buf[size] = 0;  // Null terminate buffer.
+
+  auto* ret = new (mem) MemBuffer({buf, size});
+  return std::unique_ptr<WritableMemoryBuffer>(ret);
+}
+
+std::unique_ptr<WritableMemoryBuffer> WritableMemoryBuffer::GetNewMemBuffer(
+    size_t size, std::string_view bufferName) {
+  auto sb = WritableMemoryBuffer::GetNewUninitMemBuffer(size, bufferName);
+  if (!sb) {
+    return nullptr;
+  }
+  std::memset(sb->begin(), 0, size);
+  return sb;
+}
+
+static std::unique_ptr<WriteThroughMemoryBuffer> GetReadWriteFile(
+    std::string_view filename, std::error_code& ec, uint64_t fileSize,
+    uint64_t mapSize, uint64_t offset) {
+  fs::file_t f =
+      fs::OpenFileForReadWrite(filename, ec, fs::CD_OpenExisting, fs::OF_None);
+  if (ec) {
+    return nullptr;
+  }
+
+  // Default is to map the full file.
+  if (mapSize == uint64_t(-1)) {
+    // If we don't know the file size, use fstat to find out.  fstat on an open
+    // file descriptor is cheaper than stat on a random path.
+    if (fileSize == uint64_t(-1)) {
+#ifdef _WIN32
+      // If this not a file or a block device (e.g. it's a named pipe
+      // or character device), we can't mmap it, so error out.
+      if (GetFileType(f) != FILE_TYPE_DISK) {
+        ec = std::error_code(errno, std::generic_category());
+        return nullptr;
+      }
+
+      LARGE_INTEGER fileSizeWin;
+      if (!GetFileSizeEx(f, &fileSizeWin)) {
+        ec = wpi::mapWindowsError(GetLastError());
+        return nullptr;
+      }
+      fileSize = fileSizeWin.QuadPart;
+#else
+      struct stat status;
+      if (fstat(f, &status) < 0) {
+        ec = std::error_code(errno, std::generic_category());
+        return nullptr;
+      }
+
+      // If this not a file or a block device (e.g. it's a named pipe
+      // or character device), we can't mmap it, so error out.
+      if (status.st_mode != S_IFREG && status.st_mode != S_IFBLK) {
+        ec = make_error_code(errc::invalid_argument);
+        return nullptr;
+      }
+
+      fileSize = status.st_size;
+#endif
+    }
+    mapSize = fileSize;
+  }
+
+  std::unique_ptr<WriteThroughMemoryBuffer> result(new (NamedBufferAlloc(
+      filename)) MemoryBufferMMapFile<WriteThroughMemoryBuffer>(f, mapSize,
+                                                                offset, ec));
+  if (ec) {
+    return nullptr;
+  }
+  return result;
+}
+
+std::unique_ptr<WriteThroughMemoryBuffer> WriteThroughMemoryBuffer::GetFile(
+    std::string_view filename, std::error_code& ec, int64_t fileSize) {
+  return GetReadWriteFile(filename, ec, fileSize, fileSize, 0);
+}
+
+/// Map a subrange of the specified file as a WritableMemoryBuffer.
+std::unique_ptr<WriteThroughMemoryBuffer>
+WriteThroughMemoryBuffer::GetFileSlice(std::string_view filename,
+                                       std::error_code& ec, uint64_t mapSize,
+                                       uint64_t offset) {
+  return GetReadWriteFile(filename, ec, -1, mapSize, offset);
+}
+
+template <typename MB>
+static std::unique_ptr<MB> GetOpenFileImpl(fs::file_t f,
+                                           std::string_view filename,
+                                           std::error_code& ec,
+                                           uint64_t fileSize, uint64_t mapSize,
+                                           int64_t offset) {
+  // Default is to map the full file.
+  if (mapSize == uint64_t(-1)) {
+    // If we don't know the file size, use fstat to find out.  fstat on an open
+    // file descriptor is cheaper than stat on a random path.
+    if (fileSize == uint64_t(-1)) {
+#ifdef _WIN32
+      // If this not a file or a block device (e.g. it's a named pipe
+      // or character device), we can't trust the size. Create the memory
+      // buffer by copying off the stream.
+      LARGE_INTEGER fileSizeWin;
+      if (GetFileType(f) != FILE_TYPE_DISK || !GetFileSizeEx(f, &fileSizeWin)) {
+        return GetMemoryBufferForStream(f, filename, ec);
+      }
+      fileSize = fileSizeWin.QuadPart;
+#else
+      struct stat status;
+      if (fstat(f, &status) < 0) {
+        ec = std::error_code(errno, std::generic_category());
+        return nullptr;
+      }
+
+      // If this not a file or a block device (e.g. it's a named pipe
+      // or character device), we can't trust the size. Create the memory
+      // buffer by copying off the stream.
+      if (status.st_mode != S_IFREG && status.st_mode != S_IFBLK) {
+        return GetMemoryBufferForStream(f, filename, ec);
+      }
+
+      fileSize = status.st_size;
+#endif
+    }
+    mapSize = fileSize;
+  }
+
+  // Don't use mmap for small files
+  if (mapSize >= 4 * 4096) {
+    std::unique_ptr<MB> result(new (NamedBufferAlloc(
+        filename)) MemoryBufferMMapFile<MB>(f, mapSize, offset, ec));
+    if (!ec) {
+      return result;
+    }
+  }
+
+  auto buf = WritableMemoryBuffer::GetNewUninitMemBuffer(mapSize, filename);
+  if (!buf) {
+    // Failed to create a buffer. The only way it can fail is if
+    // new(std::nothrow) returns 0.
+    ec = make_error_code(errc::not_enough_memory);
+    return nullptr;
+  }
+
+  uint8_t* bufPtr = buf.get()->begin();
+
+  size_t bytesLeft = mapSize;
+  while (bytesLeft) {
+#ifdef _WIN32
+    LARGE_INTEGER offsetWin;
+    offsetWin.QuadPart = offset;
+    DWORD numRead;
+    if (!SetFilePointerEx(f, offsetWin, nullptr, FILE_BEGIN) ||
+        !ReadFile(f, bufPtr, bytesLeft, &numRead, nullptr)) {
+      ec = mapWindowsError(GetLastError());
+      return nullptr;
+    }
+// TODO
+#else
+    ssize_t numRead = sys::RetryAfterSignal(-1, ::pread, f, bufPtr, bytesLeft,
+                                            mapSize - bytesLeft + offset);
+    if (numRead == -1) {
+      // Error while reading.
+      ec = std::error_code(errno, std::generic_category());
+      return nullptr;
+    }
+#endif
+    if (numRead == 0) {
+      std::memset(bufPtr, 0, bytesLeft);  // zero-initialize rest of the buffer.
+      break;
+    }
+    bytesLeft -= numRead;
+    bufPtr += numRead;
+  }
+
+  return buf;
+}
+
+std::unique_ptr<MemoryBuffer> MemoryBuffer::GetOpenFile(
+    fs::file_t f, std::string_view filename, std::error_code& ec,
+    uint64_t fileSize) {
+  return GetOpenFileImpl<MemoryBuffer>(f, filename, ec, fileSize, fileSize, 0);
+}
+
+std::unique_ptr<MemoryBuffer> MemoryBuffer::GetOpenFileSlice(
+    fs::file_t f, std::string_view filename, std::error_code& ec,
+    uint64_t mapSize, int64_t offset) {
+  assert(mapSize != uint64_t(-1));
+  return GetOpenFileImpl<MemoryBuffer>(f, filename, ec, -1, mapSize, offset);
+}
+
+std::unique_ptr<MemoryBuffer> MemoryBuffer::GetFileAsStream(
+    std::string_view filename, std::error_code& ec) {
+  fs::file_t f = fs::OpenFileForRead(filename, ec, fs::OF_None);
+  if (ec) {
+    return nullptr;
+  }
+  std::unique_ptr<MemoryBuffer> ret = GetMemoryBufferForStream(f, filename, ec);
+  fs::CloseFile(f);
+  return ret;
+}
+
+MemoryBufferRef MemoryBuffer::GetMemBufferRef() const {
+  return MemoryBufferRef(GetBuffer(), GetBufferIdentifier());
+}
+
+SmallVectorMemoryBuffer::~SmallVectorMemoryBuffer() {}
diff --git a/wpiutil/src/main/native/cpp/llvm/SmallPtrSet.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/SmallPtrSet.cpp
similarity index 97%
rename from wpiutil/src/main/native/cpp/llvm/SmallPtrSet.cpp
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/SmallPtrSet.cpp
index 1b33f4c..f356728 100644
--- a/wpiutil/src/main/native/cpp/llvm/SmallPtrSet.cpp
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/SmallPtrSet.cpp
@@ -1,9 +1,8 @@
 //===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -16,7 +15,6 @@
 #include "wpi/DenseMapInfo.h"
 #include "wpi/MathExtras.h"
 #include "wpi/MemAlloc.h"
-#include "wpi/ErrorHandling.h"
 #include <algorithm>
 #include <cassert>
 #include <cstdlib>
@@ -60,6 +58,7 @@
   else
     ++NumNonEmpty; // Track density.
   *Bucket = Ptr;
+  incrementEpoch();
   return std::make_pair(Bucket, true);
 }
 
diff --git a/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/SmallVector.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/SmallVector.cpp
new file mode 100644
index 0000000..04f4e06
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/SmallVector.cpp
@@ -0,0 +1,129 @@
+//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SmallVector class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "wpi/SmallVector.h"
+#include "wpi/MemAlloc.h"
+#include <cstdint>
+#ifdef LLVM_ENABLE_EXCEPTIONS
+#include <stdexcept>
+#endif
+using namespace wpi;
+
+// Check that no bytes are wasted and everything is well-aligned.
+namespace {
+// These structures may cause binary compat warnings on AIX. Suppress the
+// warning since we are only using these types for the static assertions below.
+#if defined(_AIX)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Waix-compat"
+#endif
+struct Struct16B {
+  alignas(16) void *X;
+};
+struct Struct32B {
+  alignas(32) void *X;
+};
+#if defined(_AIX)
+#pragma GCC diagnostic pop
+#endif
+}
+static_assert(sizeof(SmallVector<void *, 0>) ==
+                  sizeof(unsigned) * 2 + sizeof(void *),
+              "wasted space in SmallVector size 0");
+static_assert(alignof(SmallVector<Struct16B, 0>) >= alignof(Struct16B),
+              "wrong alignment for 16-byte aligned T");
+static_assert(alignof(SmallVector<Struct32B, 0>) >= alignof(Struct32B),
+              "wrong alignment for 32-byte aligned T");
+static_assert(sizeof(SmallVector<Struct16B, 0>) >= alignof(Struct16B),
+              "missing padding for 16-byte aligned T");
+static_assert(sizeof(SmallVector<Struct32B, 0>) >= alignof(Struct32B),
+              "missing padding for 32-byte aligned T");
+static_assert(sizeof(SmallVector<void *, 1>) ==
+                  sizeof(unsigned) * 2 + sizeof(void *) * 2,
+              "wasted space in SmallVector size 1");
+
+/// Report that MinSize doesn't fit into this vector's size type. Throws
+/// std::length_error or calls report_fatal_error.
+[[noreturn]] static void report_size_overflow(size_t MinSize, size_t MaxSize);
+static void report_size_overflow(size_t MinSize, size_t MaxSize) {
+  std::string Reason = "SmallVector unable to grow. Requested capacity (" +
+                       std::to_string(MinSize) +
+                       ") is larger than maximum value for size type (" +
+                       std::to_string(MaxSize) + ")";
+#ifdef LLVM_ENABLE_EXCEPTIONS
+  throw std::length_error(Reason);
+#else
+  report_fatal_error(Reason);
+#endif
+}
+
+/// Report that this vector is already at maximum capacity. Throws
+/// std::length_error or calls report_fatal_error.
+[[noreturn]] static void report_at_maximum_capacity(size_t MaxSize);
+static void report_at_maximum_capacity(size_t MaxSize) {
+  std::string Reason =
+      "SmallVector capacity unable to grow. Already at maximum size " +
+      std::to_string(MaxSize);
+#ifdef LLVM_ENABLE_EXCEPTIONS
+  throw std::length_error(Reason);
+#else
+  report_fatal_error(Reason);
+#endif
+}
+
+// Note: Moving this function into the header may cause performance regression.
+static size_t getNewCapacity(size_t MinSize, size_t TSize, size_t OldCapacity) {
+  constexpr size_t MaxSize = std::numeric_limits<unsigned>::max();
+
+  // Ensure we can fit the new capacity.
+  // This is only going to be applicable when the capacity is 32 bit.
+  if (MinSize > MaxSize)
+    report_size_overflow(MinSize, MaxSize);
+
+  // Ensure we can meet the guarantee of space for at least one more element.
+  // The above check alone will not catch the case where grow is called with a
+  // default MinSize of 0, but the current capacity cannot be increased.
+  // This is only going to be applicable when the capacity is 32 bit.
+  if (OldCapacity == MaxSize)
+    report_at_maximum_capacity(MaxSize);
+
+  // In theory 2*capacity can overflow if the capacity is 64 bit, but the
+  // original capacity would never be large enough for this to be a problem.
+  size_t NewCapacity = 2 * OldCapacity + 1; // Always grow.
+  return (std::min)((std::max)(NewCapacity, MinSize), MaxSize);
+}
+
+// Note: Moving this function into the header may cause performance regression.
+void *SmallVectorBase::mallocForGrow(size_t MinSize, size_t TSize,
+                                             size_t &NewCapacity) {
+  NewCapacity = getNewCapacity(MinSize, TSize, this->capacity());
+  return wpi::safe_malloc(NewCapacity * TSize);
+}
+
+// Note: Moving this function into the header may cause performance regression.
+void SmallVectorBase::grow_pod(void *FirstEl, size_t MinSize,
+                                       size_t TSize) {
+  size_t NewCapacity = getNewCapacity(MinSize, TSize, this->capacity());
+  void *NewElts;
+  if (BeginX == FirstEl) {
+    NewElts = safe_malloc(NewCapacity * TSize);
+
+    // Copy the elements over.  No need to run dtors on PODs.
+    memcpy(NewElts, this->BeginX, size() * TSize);
+  } else {
+    // If this wasn't grown from the inline copy, grow the allocated space.
+    NewElts = safe_realloc(this->BeginX, NewCapacity * TSize);
+  }
+
+  this->BeginX = NewElts;
+  this->Capacity = NewCapacity;
+}
diff --git a/wpiutil/src/main/native/cpp/StringExtras.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringExtras.cpp
similarity index 83%
rename from wpiutil/src/main/native/cpp/StringExtras.cpp
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringExtras.cpp
index 968ffc3..9307724 100644
--- a/wpiutil/src/main/native/cpp/StringExtras.cpp
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringExtras.cpp
@@ -358,3 +358,85 @@
   }
   return val;
 }
+
+std::pair<std::string_view, std::string_view> wpi::UnescapeCString(
+    std::string_view str, wpi::SmallVectorImpl<char>& buf) {
+  buf.clear();
+  buf.reserve(str.size());
+  const char* s = str.data();
+  const char* end = str.data() + str.size();
+  for (; s != end && *s != '"'; ++s) {
+    if (*s != '\\' || (s + 1) >= end) {
+      buf.push_back(*s);
+      continue;
+    }
+    switch (*++s) {
+      case 'a':
+        buf.push_back('\a');
+        break;
+      case 'b':
+        buf.push_back('\b');
+        break;
+      case 'f':
+        buf.push_back('\f');
+        break;
+      case 'n':
+        buf.push_back('\n');
+        break;
+      case 'r':
+        buf.push_back('\r');
+        break;
+      case 't':
+        buf.push_back('\t');
+        break;
+      case 'v':
+        buf.push_back('\v');
+        break;
+      case 'x': {
+        // hex escape
+        if ((s + 1) >= end || !isxdigit(*(s + 1))) {
+          buf.push_back('x');  // treat it like a unknown escape
+          break;
+        }
+        unsigned int ch = wpi::hexDigitValue(*++s);
+        if ((s + 1) < end && std::isxdigit(*(s + 1))) {
+          ch <<= 4;
+          ch |= wpi::hexDigitValue(*++s);
+        }
+        buf.push_back(static_cast<char>(ch));
+        break;
+      }
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9': {
+        // octal escape
+        unsigned int ch = *s - '0';
+        if ((s + 1) < end && wpi::isDigit(*(s + 1))) {
+          ch <<= 3;
+          ch |= *++s - '0';
+        }
+        if ((s + 1) < end && wpi::isDigit(*(s + 1))) {
+          ch <<= 3;
+          ch |= *++s - '0';
+        }
+        buf.push_back(static_cast<char>(ch));
+        break;
+      }
+      default:
+        buf.push_back(*s);
+        break;
+    }
+  }
+  if (s == end) {
+    return {{buf.data(), buf.size()}, {}};
+  } else {
+    return {{buf.data(), buf.size()}, {s, static_cast<size_t>(end - s)}};
+  }
+}
diff --git a/wpiutil/src/main/native/cpp/llvm/StringMap.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringMap.cpp
similarity index 78%
rename from wpiutil/src/main/native/cpp/llvm/StringMap.cpp
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringMap.cpp
index 768801d..2405f2f 100644
--- a/wpiutil/src/main/native/cpp/llvm/StringMap.cpp
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringMap.cpp
@@ -1,9 +1,8 @@
 //===--- StringMap.cpp - String Hash table map implementation -------------===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -12,28 +11,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "wpi/StringMap.h"
-#include "wpi/StringExtras.h"
-#include "wpi/Compiler.h"
+#include "wpi/DJB.h"
 #include "wpi/MathExtras.h"
-#include <cassert>
 
 using namespace wpi;
 
-/// HashString - Hash function for strings.
-///
-/// This is the Bernstein hash function.
-//
-// FIXME: Investigate whether a modified bernstein hash function performs
-// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
-//   X*33+c -> X*33^c
-static inline unsigned HashString(std::string_view str,
-                                  unsigned result = 0) noexcept {
-  for (std::string_view::size_type i = 0, e = str.size(); i != e; ++i) {
-    result = result * 33 + static_cast<unsigned char>(str[i]);
-  }
-  return result;
-}
-
 /// Returns the number of buckets to allocate to ensure that the DenseMap can
 /// accommodate \p NumEntries without need to grow().
 static unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
@@ -65,23 +47,22 @@
 }
 
 void StringMapImpl::init(unsigned InitSize) {
-  assert((InitSize & (InitSize-1)) == 0 &&
+  assert((InitSize & (InitSize - 1)) == 0 &&
          "Init Size must be a power of 2 or zero!");
 
   unsigned NewNumBuckets = InitSize ? InitSize : 16;
   NumItems = 0;
   NumTombstones = 0;
 
-  TheTable = static_cast<StringMapEntryBase **>(
-      safe_calloc(NewNumBuckets+1,
-                  sizeof(StringMapEntryBase **) + sizeof(unsigned)));
+  TheTable = static_cast<StringMapEntryBase **>(safe_calloc(
+      NewNumBuckets + 1, sizeof(StringMapEntryBase **) + sizeof(unsigned)));
 
   // Set the member only if TheTable was successfully allocated
   NumBuckets = NewNumBuckets;
 
   // Allocate one extra bucket, set it to look filled so the iterators stop at
   // end.
-  TheTable[NumBuckets] = (StringMapEntryBase*)2;
+  TheTable[NumBuckets] = (StringMapEntryBase *)2;
 }
 
 /// LookupBucketFor - Look up the bucket that the specified string should end
@@ -91,12 +72,12 @@
 /// of the string.
 unsigned StringMapImpl::LookupBucketFor(std::string_view Name) {
   unsigned HTSize = NumBuckets;
-  if (HTSize == 0) {  // Hash table unallocated so far?
+  if (HTSize == 0) { // Hash table unallocated so far?
     init(16);
     HTSize = NumBuckets;
   }
-  unsigned FullHashValue = HashString(Name);
-  unsigned BucketNo = FullHashValue & (HTSize-1);
+  unsigned FullHashValue = djbHash(Name, 0);
+  unsigned BucketNo = FullHashValue & (HTSize - 1);
   unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
 
   unsigned ProbeAmt = 1;
@@ -118,7 +99,8 @@
 
     if (BucketItem == getTombstoneVal()) {
       // Skip over tombstones.  However, remember the first one we see.
-      if (FirstTombstone == -1) FirstTombstone = BucketNo;
+      if (FirstTombstone == -1)
+        FirstTombstone = BucketNo;
     } else if (LLVM_LIKELY(HashTable[BucketNo] == FullHashValue)) {
       // If the full hash value matches, check deeply for a match.  The common
       // case here is that we are only looking at the buckets (for item info
@@ -127,7 +109,7 @@
 
       // Do the comparison like this because Name isn't necessarily
       // null-terminated!
-      char *ItemStr = (char*)BucketItem+ItemSize;
+      char *ItemStr = (char *)BucketItem + ItemSize;
       if (Name == std::string_view(ItemStr, BucketItem->getKeyLength())) {
         // We found a match!
         return BucketNo;
@@ -135,7 +117,7 @@
     }
 
     // Okay, we didn't find the item.  Probe to the next bucket.
-    BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
+    BucketNo = (BucketNo + ProbeAmt) & (HTSize - 1);
 
     // Use quadratic probing, it has fewer clumping artifacts than linear
     // probing and has good cache behavior in the common case.
@@ -148,9 +130,10 @@
 /// This does not modify the map.
 int StringMapImpl::FindKey(std::string_view Key) const {
   unsigned HTSize = NumBuckets;
-  if (HTSize == 0) return -1;  // Really empty table?
-  unsigned FullHashValue = HashString(Key);
-  unsigned BucketNo = FullHashValue & (HTSize-1);
+  if (HTSize == 0)
+    return -1; // Really empty table?
+  unsigned FullHashValue = djbHash(Key, 0);
+  unsigned BucketNo = FullHashValue & (HTSize - 1);
   unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1);
 
   unsigned ProbeAmt = 1;
@@ -170,7 +153,7 @@
 
       // Do the comparison like this because NameStart isn't necessarily
       // null-terminated!
-      char *ItemStr = (char*)BucketItem+ItemSize;
+      char *ItemStr = (char *)BucketItem + ItemSize;
       if (Key == std::string_view(ItemStr, BucketItem->getKeyLength())) {
         // We found a match!
         return BucketNo;
@@ -178,7 +161,7 @@
     }
 
     // Okay, we didn't find the item.  Probe to the next bucket.
-    BucketNo = (BucketNo+ProbeAmt) & (HTSize-1);
+    BucketNo = (BucketNo + ProbeAmt) & (HTSize - 1);
 
     // Use quadratic probing, it has fewer clumping artifacts than linear
     // probing and has good cache behavior in the common case.
@@ -189,7 +172,7 @@
 /// RemoveKey - Remove the specified StringMapEntry from the table, but do not
 /// delete it.  This aborts if the value isn't in the table.
 void StringMapImpl::RemoveKey(StringMapEntryBase *V) {
-  const char *VStr = (char*)V + ItemSize;
+  const char *VStr = (char *)V + ItemSize;
   StringMapEntryBase *V2 = RemoveKey(std::string_view(VStr, V->getKeyLength()));
   (void)V2;
   assert(V == V2 && "Didn't find key?");
@@ -199,7 +182,8 @@
 /// table, returning it.  If the key is not in the table, this returns null.
 StringMapEntryBase *StringMapImpl::RemoveKey(std::string_view Key) {
   int Bucket = FindKey(Key);
-  if (Bucket == -1) return nullptr;
+  if (Bucket == -1)
+    return nullptr;
 
   StringMapEntryBase *Result = TheTable[Bucket];
   TheTable[Bucket] = getTombstoneVal();
@@ -220,7 +204,7 @@
   // the buckets are empty (meaning that many are filled with tombstones),
   // grow/rehash the table.
   if (LLVM_UNLIKELY(NumItems * 4 > NumBuckets * 3)) {
-    NewSize = NumBuckets*2;
+    NewSize = NumBuckets * 2;
   } else if (LLVM_UNLIKELY(NumBuckets - (NumItems + NumTombstones) <=
                            NumBuckets / 8)) {
     NewSize = NumBuckets;
@@ -231,11 +215,11 @@
   unsigned NewBucketNo = BucketNo;
   // Allocate one extra bucket which will always be non-empty.  This allows the
   // iterators to stop at end.
-  auto NewTableArray = static_cast<StringMapEntryBase **>(
-      safe_calloc(NewSize+1, sizeof(StringMapEntryBase *) + sizeof(unsigned)));
+  auto NewTableArray = static_cast<StringMapEntryBase **>(safe_calloc(
+      NewSize + 1, sizeof(StringMapEntryBase *) + sizeof(unsigned)));
 
   unsigned *NewHashArray = (unsigned *)(NewTableArray + NewSize + 1);
-  NewTableArray[NewSize] = (StringMapEntryBase*)2;
+  NewTableArray[NewSize] = (StringMapEntryBase *)2;
 
   // Rehash all the items into their new buckets.  Luckily :) we already have
   // the hash values available, so we don't have to rehash any strings.
@@ -244,10 +228,10 @@
     if (Bucket && Bucket != getTombstoneVal()) {
       // Fast case, bucket available.
       unsigned FullHash = HashTable[I];
-      unsigned NewBucket = FullHash & (NewSize-1);
+      unsigned NewBucket = FullHash & (NewSize - 1);
       if (!NewTableArray[NewBucket]) {
-        NewTableArray[FullHash & (NewSize-1)] = Bucket;
-        NewHashArray[FullHash & (NewSize-1)] = FullHash;
+        NewTableArray[FullHash & (NewSize - 1)] = Bucket;
+        NewHashArray[FullHash & (NewSize - 1)] = FullHash;
         if (I == BucketNo)
           NewBucketNo = NewBucket;
         continue;
@@ -256,7 +240,7 @@
       // Otherwise probe for a spot.
       unsigned ProbeSize = 1;
       do {
-        NewBucket = (NewBucket + ProbeSize++) & (NewSize-1);
+        NewBucket = (NewBucket + ProbeSize++) & (NewSize - 1);
       } while (NewTableArray[NewBucket]);
 
       // Finally found a slot.  Fill it in.
diff --git a/wpiutil/src/main/native/cpp/llvm/Windows/WindowsSupport.h b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/Windows/WindowsSupport.h
similarity index 82%
rename from wpiutil/src/main/native/cpp/llvm/Windows/WindowsSupport.h
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/Windows/WindowsSupport.h
index 7307337..01200e2 100644
--- a/wpiutil/src/main/native/cpp/llvm/Windows/WindowsSupport.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/Windows/WindowsSupport.h
@@ -1,9 +1,8 @@
 //===- WindowsSupport.h - Common Windows Include File -----------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -19,8 +18,8 @@
 //===          is guaranteed to work on *all* Win32 variants.
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
-#define LLVM_SUPPORT_WINDOWSSUPPORT_H
+#ifndef WPIUTIL_WPI_WINDOWSSUPPORT_H
+#define WPIUTIL_WPI_WINDOWSSUPPORT_H
 
 // mingw-w64 tends to define it as 0x0502 in its headers.
 #undef _WIN32_WINNT
@@ -38,10 +37,10 @@
 #include "wpi/StringExtras.h"
 #include "wpi/Chrono.h"
 #include "wpi/Compiler.h"
+#include "wpi/ErrorHandling.h"
 #include "wpi/VersionTuple.h"
 #include <cassert>
 #include <string>
-#include <string_view>
 #include <system_error>
 #define WIN32_NO_STATUS
 #include <windows.h>
@@ -49,6 +48,9 @@
 #include <winternl.h>
 #include <ntstatus.h>
 
+// Must be included after windows.h
+#include <wincrypt.h>
+
 namespace wpi {
 
 /// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
@@ -81,23 +83,19 @@
   return GetWindowsOSVersion() >= wpi::VersionTuple(6, 2, 0, 0);
 }
 
-inline bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
-  if (!ErrMsg)
-    return true;
-  char *buffer = NULL;
-  DWORD LastError = GetLastError();
-  DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                               FORMAT_MESSAGE_FROM_SYSTEM |
-                               FORMAT_MESSAGE_MAX_WIDTH_MASK,
-                           NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
-  if (R)
-    *ErrMsg = prefix + ": " + buffer;
-  else
-    *ErrMsg = prefix + ": Unknown error";
-  *ErrMsg += " (0x" + wpi::utohexstr(LastError) + ")";
+/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
+/// RtlGetVersion or GetVersionEx under the hood depending on what is available.
+/// GetVersionEx is deprecated, but this API exposes the build number which can
+/// be useful for working around certain kernel bugs.
+wpi::VersionTuple GetWindowsOSVersion();
 
-  LocalFree(buffer);
-  return R != 0;
+bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
+
+// Include GetLastError() in a fatal error message.
+[[noreturn]] inline void ReportLastErrorFatal(const char *Msg) {
+  std::string ErrMsg;
+  MakeErrMsg(&ErrMsg, Msg);
+  wpi::report_fatal_error(ErrMsg);
 }
 
 template <typename HandleTraits>
@@ -164,6 +162,22 @@
   }
 };
 
+struct CryptContextTraits : CommonHandleTraits {
+  typedef HCRYPTPROV handle_type;
+
+  static handle_type GetInvalid() {
+    return 0;
+  }
+
+  static void Close(handle_type h) {
+    ::CryptReleaseContext(h, 0);
+  }
+
+  static bool IsValid(handle_type h) {
+    return h != GetInvalid();
+  }
+};
+
 struct RegTraits : CommonHandleTraits {
   typedef HKEY handle_type;
 
@@ -190,6 +204,7 @@
 
 typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
 typedef ScopedHandle<FileHandleTraits>   ScopedFileHandle;
+typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
 typedef ScopedHandle<RegTraits>          ScopedRegHandle;
 typedef ScopedHandle<FindHandleTraits>   ScopedFindHandle;
 typedef ScopedHandle<JobHandleTraits>    ScopedJobHandle;
diff --git a/wpiutil/src/main/native/cpp/llvm/raw_os_ostream.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/raw_os_ostream.cpp
similarity index 79%
rename from wpiutil/src/main/native/cpp/llvm/raw_os_ostream.cpp
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/raw_os_ostream.cpp
index 1fb6c51..682a9a0 100644
--- a/wpiutil/src/main/native/cpp/llvm/raw_os_ostream.cpp
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/raw_os_ostream.cpp
@@ -1,9 +1,8 @@
 //===--- raw_os_ostream.cpp - Implement the raw_os_ostream class ----------===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
diff --git a/wpiutil/src/main/native/cpp/llvm/raw_ostream.cpp b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/raw_ostream.cpp
similarity index 87%
rename from wpiutil/src/main/native/cpp/llvm/raw_ostream.cpp
rename to wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/raw_ostream.cpp
index 622e0bf..a2d586b 100644
--- a/wpiutil/src/main/native/cpp/llvm/raw_ostream.cpp
+++ b/wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/raw_ostream.cpp
@@ -1,9 +1,8 @@
 //===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -21,19 +20,15 @@
 #include "wpi/StringExtras.h"
 #include "wpi/Compiler.h"
 #include "wpi/ErrorHandling.h"
-#include "wpi/MathExtras.h"
-#include "wpi/WindowsError.h"
 #include "wpi/fs.h"
+#include "wpi/MathExtras.h"
 #include <algorithm>
-#include <cctype>
 #include <cerrno>
 #include <cstdio>
-#include <iterator>
 #include <sys/stat.h>
-#include <system_error>
 
 // <fcntl.h> may provide O_BINARY.
-#include <fcntl.h>
+# include <fcntl.h>
 
 #ifndef _WIN32
 #include <unistd.h>
@@ -64,6 +59,17 @@
 
 using namespace wpi;
 
+constexpr raw_ostream::Colors raw_ostream::BLACK;
+constexpr raw_ostream::Colors raw_ostream::RED;
+constexpr raw_ostream::Colors raw_ostream::GREEN;
+constexpr raw_ostream::Colors raw_ostream::YELLOW;
+constexpr raw_ostream::Colors raw_ostream::BLUE;
+constexpr raw_ostream::Colors raw_ostream::MAGENTA;
+constexpr raw_ostream::Colors raw_ostream::CYAN;
+constexpr raw_ostream::Colors raw_ostream::WHITE;
+constexpr raw_ostream::Colors raw_ostream::SAVEDCOLOR;
+constexpr raw_ostream::Colors raw_ostream::RESET;
+
 namespace {
 // Find the length of an array.
 template <class T, std::size_t N>
@@ -78,13 +84,10 @@
   assert(OutBufCur == OutBufStart &&
          "raw_ostream destructor called with non-empty buffer!");
 
-  if (BufferMode == InternalBuffer)
+  if (BufferMode == BufferKind::InternalBuffer)
     delete [] OutBufStart;
 }
 
-// An out of line virtual method to provide a home for the class vtable.
-void raw_ostream::handle() {}
-
 size_t raw_ostream::preferred_buffer_size() const {
   // BUFSIZ is intended to be a reasonable default.
   return BUFSIZ;
@@ -101,14 +104,14 @@
 
 void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
                                    BufferKind Mode) {
-  assert(((Mode == Unbuffered && !BufferStart && Size == 0) ||
-          (Mode != Unbuffered && BufferStart && Size != 0)) &&
+  assert(((Mode == BufferKind::Unbuffered && !BufferStart && Size == 0) ||
+          (Mode != BufferKind::Unbuffered && BufferStart && Size != 0)) &&
          "stream must be unbuffered or have at least one byte");
   // Make sure the current buffer is free of content (we can't flush here; the
   // child buffer management logic will be in write_impl).
   assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");
 
-  if (BufferMode == InternalBuffer)
+  if (BufferMode == BufferKind::InternalBuffer)
     delete [] OutBufStart;
   OutBufStart = BufferStart;
   OutBufEnd = OutBufStart+Size;
@@ -143,7 +146,7 @@
       // Write out the escaped representation.
       if (UseHexEscapes) {
         *this << '\\' << 'x';
-        *this << hexdigit((c >> 4 & 0xF));
+        *this << hexdigit((c >> 4) & 0xF);
         *this << hexdigit((c >> 0) & 0xF);
       } else {
         // Always use a full 3-character octal escape.
@@ -162,15 +165,15 @@
   assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
   size_t Length = OutBufCur - OutBufStart;
   OutBufCur = OutBufStart;
-  write_impl(OutBufStart, Length);
+  flush_tied_then_write(OutBufStart, Length);
 }
 
 raw_ostream &raw_ostream::write(unsigned char C) {
   // Group exceptional cases into a single branch.
   if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) {
     if (LLVM_UNLIKELY(!OutBufStart)) {
-      if (BufferMode == Unbuffered) {
-        write_impl(reinterpret_cast<char*>(&C), 1);
+      if (BufferMode == BufferKind::Unbuffered) {
+        flush_tied_then_write(reinterpret_cast<char *>(&C), 1);
         return *this;
       }
       // Set up a buffer and start over.
@@ -189,8 +192,8 @@
   // Group exceptional cases into a single branch.
   if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) {
     if (LLVM_UNLIKELY(!OutBufStart)) {
-      if (BufferMode == Unbuffered) {
-        write_impl(Ptr, Size);
+      if (BufferMode == BufferKind::Unbuffered) {
+        flush_tied_then_write(Ptr, Size);
         return *this;
       }
       // Set up a buffer and start over.
@@ -206,7 +209,7 @@
     if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) {
       assert(NumBytes != 0 && "undefined behavior");
       size_t BytesToWrite = Size - (Size % NumBytes);
-      write_impl(Ptr, BytesToWrite);
+      flush_tied_then_write(Ptr, BytesToWrite);
       size_t BytesRemaining = Size - BytesToWrite;
       if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) {
         // Too much left over to copy into our buffer.
@@ -247,6 +250,13 @@
   OutBufCur += Size;
 }
 
+void raw_ostream::flush_tied_then_write(const char *Ptr, size_t Size) {
+  if (TiedStream)
+    TiedStream->flush();
+  write_impl(Ptr, Size);
+}
+
+
 template <char C>
 static raw_ostream &write_padding(raw_ostream &OS, unsigned NumChars) {
   static const char Chars[] = {C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
@@ -294,8 +304,7 @@
   // the owner of stdout and may set the "binary" flag globally based on Flags.
   if (Filename == "-") {
     EC = std::error_code();
-    // If user requested binary then put stdout into binary mode if
-    // possible.
+    // Change stdout's text/binary mode based on the Flags.
     if (!(Flags & fs::OF_Text)) {
 #if defined(_WIN32)
       _setmode(_fileno(stdout), _O_BINARY);
@@ -305,11 +314,10 @@
   }
 
   fs::file_t F;
-  if (Access & fs::FA_Read) {
+  if (Access & fs::FA_Read)
     F = fs::OpenFileForReadWrite(fs::path{std::string_view{Filename.data(), Filename.size()}}, EC, Disp, Flags);
-  } else {
+  else
     F = fs::OpenFileForWrite(fs::path{std::string_view{Filename.data(), Filename.size()}}, EC, Disp, Flags);
-  }
   if (EC)
     return -1;
   int FD = fs::FileToFd(F, EC, Flags);
@@ -345,13 +353,16 @@
 
 /// FD is the file descriptor that this writes to.  If ShouldClose is true, this
 /// closes the file when the stream is destroyed.
-raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)
-    : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose) {
+raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,
+                               OStreamKind K)
+    : raw_pwrite_stream(unbuffered, K), FD(fd), ShouldClose(shouldClose) {
   if (FD < 0 ) {
     ShouldClose = false;
     return;
   }
 
+  enable_colors(true);
+
   // Do not attempt to close stdout or stderr. We used to try to maintain the
   // property that tools that support writing file to stdout should not also
   // write informational output to stdout, but in practice we were never able to
@@ -370,10 +381,9 @@
   // Get the starting position.
   off_t loc = ::lseek(FD, 0, SEEK_CUR);
 #ifdef _WIN32
-  // MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes.
   SupportsSeeking = loc != (off_t)-1 && ::GetFileType(reinterpret_cast<HANDLE>(::_get_osfhandle(FD))) != FILE_TYPE_PIPE;
 #else
-  SupportsSeeking = loc != (off_t)-1;
+  SupportsSeeking = !EC && loc != (off_t)-1;
 #endif
   if (!SupportsSeeking)
     pos = 0;
@@ -402,7 +412,7 @@
   // destructing raw_ostream objects which may have errors.
   if (has_error())
     report_fatal_error("IO failure on output stream: " + error().message(),
-                       /*GenCrashDiag=*/false);
+                       /*gen_crash_diag=*/false);
 }
 
 #if defined(_WIN32)
@@ -565,7 +575,7 @@
   // If this is a terminal, don't use buffering. Line buffering
   // would be a more traditional thing to do, but it's not worth
   // the complexity.
-  if (S_ISCHR(statbuf.st_mode) && isatty(FD))
+  if (S_ISCHR(statbuf.st_mode) && is_displayed())
     return 0;
   // Return the preferred block size.
   return statbuf.st_blksize;
@@ -580,38 +590,50 @@
 //  outs(), errs(), nulls()
 //===----------------------------------------------------------------------===//
 
-/// outs() - This returns a reference to a raw_ostream for standard output.
-/// Use it like: outs() << "foo" << "bar";
-raw_ostream &wpi::outs() {
+raw_fd_ostream &wpi::outs() {
   // Set buffer settings to model stdout behavior.
   std::error_code EC;
-  static raw_fd_ostream* S = new raw_fd_ostream("-", EC, fs::F_None);
+  static raw_fd_ostream* S = new raw_fd_ostream("-", EC, fs::OF_None);
   assert(!EC);
   return *S;
 }
 
-/// errs() - This returns a reference to a raw_ostream for standard error.
-/// Use it like: errs() << "foo" << "bar";
-raw_ostream &wpi::errs() {
-  // Set standard error to be unbuffered by default.
+raw_fd_ostream &wpi::errs() {
+  // Set standard error to be unbuffered and tied to outs() by default.
   static raw_fd_ostream* S = new raw_fd_ostream(STDERR_FILENO, false, true);
   return *S;
 }
 
 /// nulls() - This returns a reference to a raw_ostream which discards output.
 raw_ostream &wpi::nulls() {
-  static raw_null_ostream* S = new raw_null_ostream;
-  return *S;
+  static raw_null_ostream S;
+  return S;
+}
+
+//===----------------------------------------------------------------------===//
+// File Streams
+//===----------------------------------------------------------------------===//
+
+raw_fd_stream::raw_fd_stream(std::string_view Filename, std::error_code &EC)
+    : raw_fd_ostream(getFD(Filename, EC, fs::CD_CreateAlways,
+                           fs::FA_Write | fs::FA_Read,
+                           fs::OF_None),
+                     true, false, OStreamKind::OK_FDStream) {
+  if (EC)
+    return;
+
+  if (!isRegularFile())
+    EC = std::make_error_code(std::errc::invalid_argument);
+}
+
+bool raw_fd_stream::classof(const raw_ostream *OS) {
+  return OS->get_kind() == OStreamKind::OK_FDStream;
 }
 
 //===----------------------------------------------------------------------===//
 //  raw_string_ostream
 //===----------------------------------------------------------------------===//
 
-raw_string_ostream::~raw_string_ostream() {
-  flush();
-}
-
 void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {
   OS.append(Ptr, Size);
 }
@@ -691,15 +713,18 @@
 #endif
 }
 
-void raw_null_ostream::write_impl(const char * /*Ptr*/, size_t /*Size*/) {}
+void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {
+}
 
 uint64_t raw_null_ostream::current_pos() const {
   return 0;
 }
 
-void raw_null_ostream::pwrite_impl(const char * /*Ptr*/, size_t /*Size*/,
-                                   uint64_t /*Offset*/) {}
+void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size,
+                                   uint64_t Offset) {}
 
 void raw_pwrite_stream::anchor() {}
 
 void buffer_ostream::anchor() {}
+
+void buffer_unique_ostream::anchor() {}
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/AlignOf.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/AlignOf.h
new file mode 100644
index 0000000..5d400e4
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/AlignOf.h
@@ -0,0 +1,34 @@
+//===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the AlignedCharArrayUnion class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_ALIGNOF_H
+#define WPIUTIL_WPI_ALIGNOF_H
+
+#include <type_traits>
+
+namespace wpi {
+
+/// A suitably aligned and sized character array member which can hold elements
+/// of any type.
+///
+/// This template is equivalent to std::aligned_union_t<1, ...>, but we cannot
+/// use it due to a bug in the MSVC x86 compiler:
+/// https://github.com/microsoft/STL/issues/1533
+/// Using `alignas` here works around the bug.
+template <typename T, typename... Ts> struct AlignedCharArrayUnion {
+  using AlignedUnion = std::aligned_union_t<1, T, Ts...>;
+  alignas(alignof(AlignedUnion)) char buffer[sizeof(AlignedUnion)];
+};
+
+} // end namespace wpi
+
+#endif // WPIUTIL_WPI_ALIGNOF_H
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/AllocatorBase.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/AllocatorBase.h
new file mode 100644
index 0000000..29ba16f
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/AllocatorBase.h
@@ -0,0 +1,104 @@
+//===- AllocatorBase.h - Simple memory allocation abstraction ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines MallocAllocator. MallocAllocator conforms to the LLVM
+/// "Allocator" concept which consists of an Allocate method accepting a size
+/// and alignment, and a Deallocate accepting a pointer and size. Further, the
+/// LLVM "Allocator" concept has overloads of Allocate and Deallocate for
+/// setting size and alignment based on the final type. These overloads are
+/// typically provided by a base class template \c AllocatorBase.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_ALLOCATORBASE_H
+#define WPIUTIL_WPI_ALLOCATORBASE_H
+
+#include "wpi/Compiler.h"
+#include "wpi/MemAlloc.h"
+#include <type_traits>
+
+namespace wpi {
+
+/// CRTP base class providing obvious overloads for the core \c
+/// Allocate() methods of LLVM-style allocators.
+///
+/// This base class both documents the full public interface exposed by all
+/// LLVM-style allocators, and redirects all of the overloads to a single core
+/// set of methods which the derived class must define.
+template <typename DerivedT> class AllocatorBase {
+public:
+  /// Allocate \a Size bytes of \a Alignment aligned memory. This method
+  /// must be implemented by \c DerivedT.
+  void *Allocate(size_t Size, size_t Alignment) {
+#ifdef __clang__
+    static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
+                      &AllocatorBase::Allocate) !=
+                      static_cast<void *(DerivedT::*)(size_t, size_t)>(
+                          &DerivedT::Allocate),
+                  "Class derives from AllocatorBase without implementing the "
+                  "core Allocate(size_t, size_t) overload!");
+#endif
+    return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
+  }
+
+  /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
+  /// allocator.
+  void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
+#ifdef __clang__
+    static_assert(
+        static_cast<void (AllocatorBase::*)(const void *, size_t, size_t)>(
+            &AllocatorBase::Deallocate) !=
+            static_cast<void (DerivedT::*)(const void *, size_t, size_t)>(
+                &DerivedT::Deallocate),
+        "Class derives from AllocatorBase without implementing the "
+        "core Deallocate(void *) overload!");
+#endif
+    return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size, Alignment);
+  }
+
+  // The rest of these methods are helpers that redirect to one of the above
+  // core methods.
+
+  /// Allocate space for a sequence of objects without constructing them.
+  template <typename T> T *Allocate(size_t Num = 1) {
+    return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
+  }
+
+  /// Deallocate space for a sequence of objects without constructing them.
+  template <typename T>
+  std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value, void>
+  Deallocate(T *Ptr, size_t Num = 1) {
+    Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T), alignof(T));
+  }
+};
+
+class MallocAllocator : public AllocatorBase<MallocAllocator> {
+public:
+  void Reset() {}
+
+  LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) {
+    return allocate_buffer(Size, Alignment);
+  }
+
+  // Pull in base class overloads.
+  using AllocatorBase<MallocAllocator>::Allocate;
+
+  void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
+    deallocate_buffer(const_cast<void *>(Ptr), Size, Alignment);
+  }
+
+  // Pull in base class overloads.
+  using AllocatorBase<MallocAllocator>::Deallocate;
+
+  void PrintStats() const {}
+};
+
+} // namespace wpi
+
+#endif // WPIUTIL_WPI_ALLOCATORBASE_H
diff --git a/wpiutil/src/main/native/include/wpi/Chrono.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Chrono.h
similarity index 70%
rename from wpiutil/src/main/native/include/wpi/Chrono.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/Chrono.h
index 33341c6..221f6dc 100644
--- a/wpiutil/src/main/native/include/wpi/Chrono.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Chrono.h
@@ -1,9 +1,8 @@
 //===- llvm/Support/Chrono.h - Utilities for Timing Manipulation-*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 
@@ -14,6 +13,7 @@
 
 #include <chrono>
 #include <ctime>
+#include <ratio>
 
 namespace wpi {
 
@@ -23,31 +23,31 @@
 
 /// A time point on the system clock. This is provided for two reasons:
 /// - to insulate us against subtle differences in behavior to differences in
-///   system clock precision (which is implementation-defined and differs between
-///   platforms).
+///   system clock precision (which is implementation-defined and differs
+///   between platforms).
 /// - to shorten the type name
-/// The default precision is nanoseconds. If need a specific precision specify
-/// it explicitly. If unsure, use the default. If you need a time point on a
-/// clock other than the system_clock, use std::chrono directly.
+/// The default precision is nanoseconds. If you need a specific precision
+/// specify it explicitly. If unsure, use the default. If you need a time point
+/// on a clock other than the system_clock, use std::chrono directly.
 template <typename D = std::chrono::nanoseconds>
 using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
 
 /// Convert a TimePoint to std::time_t
-LLVM_ATTRIBUTE_ALWAYS_INLINE std::time_t toTimeT(TimePoint<> TP) {
+inline std::time_t toTimeT(TimePoint<> TP) {
   using namespace std::chrono;
   return system_clock::to_time_t(
       time_point_cast<system_clock::time_point::duration>(TP));
 }
 
 /// Convert a std::time_t to a TimePoint
-LLVM_ATTRIBUTE_ALWAYS_INLINE TimePoint<std::chrono::seconds>
+inline TimePoint<std::chrono::seconds>
 toTimePoint(std::time_t T) {
   using namespace std::chrono;
   return time_point_cast<seconds>(system_clock::from_time_t(T));
 }
 
 /// Convert a std::time_t + nanoseconds to a TimePoint
-LLVM_ATTRIBUTE_ALWAYS_INLINE TimePoint<>
+inline TimePoint<>
 toTimePoint(std::time_t T, uint32_t nsec) {
   using namespace std::chrono;
   return time_point_cast<nanoseconds>(system_clock::from_time_t(T))
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Compiler.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Compiler.h
new file mode 100644
index 0000000..c98386e
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Compiler.h
@@ -0,0 +1,619 @@
+//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines several macros, based on the current compiler.  This allows
+// use of compiler-specific features in a way that remains portable. This header
+// can be included from either C or C++.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_COMPILER_H
+#define WPIUTIL_WPI_COMPILER_H
+
+
+#include <stddef.h>
+
+#if defined(_MSC_VER)
+#include <sal.h>
+#endif
+
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+#ifndef __has_extension
+# define __has_extension(x) 0
+#endif
+
+#ifndef __has_attribute
+# define __has_attribute(x) 0
+#endif
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+// Only use __has_cpp_attribute in C++ mode. GCC defines __has_cpp_attribute in
+// C mode, but the :: in __has_cpp_attribute(scoped::attribute) is invalid.
+#ifndef LLVM_HAS_CPP_ATTRIBUTE
+#if defined(__cplusplus) && defined(__has_cpp_attribute)
+# define LLVM_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+# define LLVM_HAS_CPP_ATTRIBUTE(x) 0
+#endif
+#endif
+
+/// \macro LLVM_GNUC_PREREQ
+/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't
+/// available.
+#ifndef LLVM_GNUC_PREREQ
+# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
+#  define LLVM_GNUC_PREREQ(maj, min, patch) \
+    ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
+     ((maj) << 20) + ((min) << 10) + (patch))
+# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
+#  define LLVM_GNUC_PREREQ(maj, min, patch) \
+    ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
+# else
+#  define LLVM_GNUC_PREREQ(maj, min, patch) 0
+# endif
+#endif
+
+/// \macro LLVM_MSC_PREREQ
+/// Is the compiler MSVC of at least the specified version?
+/// The common \param version values to check for are:
+/// * 1910: VS2017, version 15.1 & 15.2
+/// * 1911: VS2017, version 15.3 & 15.4
+/// * 1912: VS2017, version 15.5
+/// * 1913: VS2017, version 15.6
+/// * 1914: VS2017, version 15.7
+/// * 1915: VS2017, version 15.8
+/// * 1916: VS2017, version 15.9
+/// * 1920: VS2019, version 16.0
+/// * 1921: VS2019, version 16.1
+/// * 1922: VS2019, version 16.2
+/// * 1923: VS2019, version 16.3
+/// * 1924: VS2019, version 16.4
+/// * 1925: VS2019, version 16.5
+/// * 1926: VS2019, version 16.6
+/// * 1927: VS2019, version 16.7
+/// * 1928: VS2019, version 16.8 + 16.9
+/// * 1929: VS2019, version 16.10 + 16.11
+/// * 1930: VS2022, version 17.0
+#ifndef LLVM_MSC_PREREQ
+#ifdef _MSC_VER
+#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
+
+// We require at least VS 2019.
+#if !defined(LLVM_FORCE_USE_OLD_TOOLCHAIN)
+#if !LLVM_MSC_PREREQ(1920)
+#error LLVM requires at least VS 2019.
+#endif
+#endif
+
+#else
+#define LLVM_MSC_PREREQ(version) 0
+#endif
+#endif
+
+/// Does the compiler support ref-qualifiers for *this?
+///
+/// Sadly, this is separate from just rvalue reference support because GCC
+/// and MSVC implemented this later than everything else. This appears to be
+/// corrected in MSVC 2019 but not MSVC 2017.
+/// FIXME: Remove LLVM_HAS_RVALUE_REFERENCE_THIS macro
+#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
+
+/// Expands to '&' if ref-qualifiers for *this are supported.
+///
+/// This can be used to provide lvalue/rvalue overrides of member functions.
+/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS
+#ifndef LLVM_LVALUE_FUNCTION
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+#define LLVM_LVALUE_FUNCTION &
+#else
+#define LLVM_LVALUE_FUNCTION
+#endif
+#endif
+
+/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked
+/// into a shared library, then the class should be private to the library and
+/// not accessible from outside it.  Can also be used to mark variables and
+/// functions, making them private to any shared library they are linked into.
+/// On PE/COFF targets, library visibility is the default, so this isn't needed.
+///
+/// LLVM_EXTERNAL_VISIBILITY - classes, functions, and variables marked with
+/// this attribute will be made public and visible outside of any shared library
+/// they are linked in to.
+#if __has_attribute(visibility) && !defined(__MINGW32__) &&                    \
+    !defined(__CYGWIN__) && !defined(_WIN32)
+#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
+#if defined(LLVM_BUILD_LLVM_DYLIB) || defined(LLVM_BUILD_SHARED_LIBS)
+#define LLVM_EXTERNAL_VISIBILITY __attribute__((visibility("default")))
+#else
+#define LLVM_EXTERNAL_VISIBILITY
+#endif
+#else
+#define LLVM_LIBRARY_VISIBILITY
+#define LLVM_EXTERNAL_VISIBILITY
+#endif
+
+#ifndef LLVM_PREFETCH
+#if defined(__GNUC__)
+#define LLVM_PREFETCH(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
+#else
+#define LLVM_PREFETCH(addr, rw, locality)
+#endif
+#endif
+
+#ifndef LLVM_ATTRIBUTE_USED
+#if __has_attribute(used)
+#define LLVM_ATTRIBUTE_USED __attribute__((__used__))
+#else
+#define LLVM_ATTRIBUTE_USED
+#endif
+#endif
+
+/// LLVM_NODISCARD - Warn if a type or return value is discarded.
+
+// Use the 'nodiscard' attribute in C++17 or newer mode.
+#ifndef LLVM_NODISCARD
+#if defined(__cplusplus) && __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
+#define LLVM_NODISCARD [[nodiscard]]
+#elif LLVM_HAS_CPP_ATTRIBUTE(clang::warn_unused_result)
+#define LLVM_NODISCARD [[clang::warn_unused_result]]
+// Clang in C++14 mode claims that it has the 'nodiscard' attribute, but also
+// warns in the pedantic mode that 'nodiscard' is a C++17 extension (PR33518).
+// Use the 'nodiscard' attribute in C++14 mode only with GCC.
+// TODO: remove this workaround when PR33518 is resolved.
+#elif defined(__GNUC__) && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
+#define LLVM_NODISCARD [[nodiscard]]
+#else
+#define LLVM_NODISCARD
+#endif
+#endif
+
+// Indicate that a non-static, non-const C++ member function reinitializes
+// the entire object to a known state, independent of the previous state of
+// the object.
+//
+// The clang-tidy check bugprone-use-after-move recognizes this attribute as a
+// marker that a moved-from object has left the indeterminate state and can be
+// reused.
+#if LLVM_HAS_CPP_ATTRIBUTE(clang::reinitializes)
+#define LLVM_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
+#else
+#define LLVM_ATTRIBUTE_REINITIALIZES
+#endif
+
+// Some compilers warn about unused functions. When a function is sometimes
+// used or not depending on build settings (e.g. a function only called from
+// within "assert"), this attribute can be used to suppress such warnings.
+//
+// However, it shouldn't be used for unused *variables*, as those have a much
+// more portable solution:
+//   (void)unused_var_name;
+// Prefer cast-to-void wherever it is sufficient.
+#ifndef LLVM_ATTRIBUTE_UNUSED
+#if __has_attribute(unused)
+#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__))
+#else
+#define LLVM_ATTRIBUTE_UNUSED
+#endif
+#endif
+
+// FIXME: Provide this for PE/COFF targets.
+#if __has_attribute(weak) && !defined(__MINGW32__) && !defined(__CYGWIN__) &&  \
+    !defined(_WIN32)
+#define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__))
+#else
+#define LLVM_ATTRIBUTE_WEAK
+#endif
+
+#ifndef LLVM_READNONE
+// Prior to clang 3.2, clang did not accept any spelling of
+// __has_attribute(const), so assume it is supported.
+#if defined(__clang__) || defined(__GNUC__)
+// aka 'CONST' but following LLVM Conventions.
+#define LLVM_READNONE __attribute__((__const__))
+#else
+#define LLVM_READNONE
+#endif
+#endif
+
+#ifndef LLVM_READONLY
+#if __has_attribute(pure) || defined(__GNUC__)
+// aka 'PURE' but following LLVM Conventions.
+#define LLVM_READONLY __attribute__((__pure__))
+#else
+#define LLVM_READONLY
+#endif
+#endif
+
+#if __has_attribute(minsize)
+#define LLVM_ATTRIBUTE_MINSIZE __attribute__((minsize))
+#else
+#define LLVM_ATTRIBUTE_MINSIZE
+#endif
+
+#ifndef LLVM_LIKELY
+#if __has_builtin(__builtin_expect) || defined(__GNUC__)
+#define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true)
+#define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)
+#else
+#define LLVM_LIKELY(EXPR) (EXPR)
+#define LLVM_UNLIKELY(EXPR) (EXPR)
+#endif
+#endif
+
+/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so,
+/// mark a method "not for inlining".
+#ifndef LLVM_ATTRIBUTE_NOINLINE
+#if __has_attribute(noinline)
+#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline)
+#else
+#define LLVM_ATTRIBUTE_NOINLINE
+#endif
+#endif
+
+/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do
+/// so, mark a method "always inline" because it is performance sensitive.
+#ifndef LLVM_ATTRIBUTE_ALWAYS_INLINE
+#if __has_attribute(always_inline)
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline
+#else
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline
+#endif
+#endif
+
+/// LLVM_ATTRIBUTE_NO_DEBUG - On compilers where we have a directive to do
+/// so, mark a method "no debug" because debug info makes the debugger
+/// experience worse.
+#if __has_attribute(nodebug)
+#define LLVM_ATTRIBUTE_NODEBUG __attribute__((nodebug))
+#else
+#define LLVM_ATTRIBUTE_NODEBUG
+#endif
+
+#ifndef LLVM_ATTRIBUTE_RETURNS_NONNULL
+#if __has_attribute(returns_nonnull)
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_
+#else
+#define LLVM_ATTRIBUTE_RETURNS_NONNULL
+#endif
+#endif
+
+/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a
+/// pointer that does not alias any other valid pointer.
+#ifndef LLVM_ATTRIBUTE_RETURNS_NOALIAS
+#ifdef __GNUC__
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
+#elif defined(_MSC_VER)
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
+#else
+#define LLVM_ATTRIBUTE_RETURNS_NOALIAS
+#endif
+#endif
+
+/// LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
+#ifndef LLVM_FALLTHROUGH
+#if defined(__cplusplus) && __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(fallthrough)
+#define LLVM_FALLTHROUGH [[fallthrough]]
+#elif LLVM_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
+#define LLVM_FALLTHROUGH [[gnu::fallthrough]]
+#elif __has_attribute(fallthrough)
+#define LLVM_FALLTHROUGH __attribute__((fallthrough))
+#elif LLVM_HAS_CPP_ATTRIBUTE(clang::fallthrough)
+#define LLVM_FALLTHROUGH [[clang::fallthrough]]
+#else
+#define LLVM_FALLTHROUGH
+#endif
+#endif
+
+/// LLVM_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that
+/// they are constant initialized.
+#if LLVM_HAS_CPP_ATTRIBUTE(clang::require_constant_initialization)
+#define LLVM_REQUIRE_CONSTANT_INITIALIZATION                                   \
+  [[clang::require_constant_initialization]]
+#else
+#define LLVM_REQUIRE_CONSTANT_INITIALIZATION
+#endif
+
+/// LLVM_GSL_OWNER - Apply this to owning classes like SmallVector to enable
+/// lifetime warnings.
+#if LLVM_HAS_CPP_ATTRIBUTE(gsl::Owner)
+#define LLVM_GSL_OWNER [[gsl::Owner]]
+#else
+#define LLVM_GSL_OWNER
+#endif
+
+/// LLVM_GSL_POINTER - Apply this to non-owning classes like
+/// std::string_view to enable lifetime warnings.
+#if LLVM_HAS_CPP_ATTRIBUTE(gsl::Pointer)
+#define LLVM_GSL_POINTER [[gsl::Pointer]]
+#else
+#define LLVM_GSL_POINTER
+#endif
+
+/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
+/// pedantic diagnostics.
+#ifndef LLVM_EXTENSION
+#ifdef __GNUC__
+#define LLVM_EXTENSION __extension__
+#else
+#define LLVM_EXTENSION
+#endif
+#endif
+
+// LLVM_ATTRIBUTE_DEPRECATED(decl, "message")
+// This macro will be removed.
+// Use C++14's attribute instead: [[deprecated("message")]]
+#ifndef LLVM_ATTRIBUTE_DEPRECATED
+#define LLVM_ATTRIBUTE_DEPRECATED(decl, message) [[deprecated(message)]] decl
+#endif
+
+/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
+/// to an expression which states that it is undefined behavior for the
+/// compiler to reach this point.  Otherwise is not defined.
+#ifndef LLVM_BUILTIN_UNREACHABLE
+#if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
+# define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable()
+#elif defined(_MSC_VER)
+# define LLVM_BUILTIN_UNREACHABLE __assume(false)
+#else
+# define LLVM_BUILTIN_UNREACHABLE
+#endif
+#endif
+
+/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression
+/// which causes the program to exit abnormally.
+#ifndef LLVM_BUILTIN_TRAP
+#if __has_builtin(__builtin_trap) || defined(__GNUC__)
+# define LLVM_BUILTIN_TRAP __builtin_trap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC, does not require forward
+// declarations involving platform-specific typedefs (unlike RaiseException),
+// results in a call to vectored exception handlers, and encodes to a short
+// instruction that still causes the trapping behavior we want.
+# define LLVM_BUILTIN_TRAP __debugbreak()
+#else
+# define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0
+#endif
+#endif
+
+/// LLVM_BUILTIN_DEBUGTRAP - On compilers which support it, expands to
+/// an expression which causes the program to break while running
+/// under a debugger.
+#ifndef LLVM_BUILTIN_DEBUGTRAP
+#if __has_builtin(__builtin_debugtrap)
+# define LLVM_BUILTIN_DEBUGTRAP __builtin_debugtrap()
+#elif defined(_MSC_VER)
+// The __debugbreak intrinsic is supported by MSVC and breaks while
+// running under the debugger, and also supports invoking a debugger
+// when the OS is configured appropriately.
+# define LLVM_BUILTIN_DEBUGTRAP __debugbreak()
+#else
+// Just continue execution when built with compilers that have no
+// support. This is a debugging aid and not intended to force the
+// program to abort if encountered.
+# define LLVM_BUILTIN_DEBUGTRAP
+#endif
+#endif
+
+/// \macro LLVM_ASSUME_ALIGNED
+/// Returns a pointer with an assumed alignment.
+#ifndef LLVM_ASSUME_ALIGNED
+#if __has_builtin(__builtin_assume_aligned) || defined(__GNUC__)
+# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
+#elif defined(LLVM_BUILTIN_UNREACHABLE)
+# define LLVM_ASSUME_ALIGNED(p, a) \
+           (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p)))
+#else
+# define LLVM_ASSUME_ALIGNED(p, a) (p)
+#endif
+#endif
+
+/// \macro LLVM_PACKED
+/// Used to specify a packed structure.
+/// LLVM_PACKED(
+///    struct A {
+///      int i;
+///      int j;
+///      int k;
+///      long long l;
+///   });
+///
+/// LLVM_PACKED_START
+/// struct B {
+///   int i;
+///   int j;
+///   int k;
+///   long long l;
+/// };
+/// LLVM_PACKED_END
+#ifndef LLVM_PACKED
+#ifdef _MSC_VER
+# define LLVM_PACKED(d) __pragma(pack(push, 1)) d __pragma(pack(pop))
+# define LLVM_PACKED_START __pragma(pack(push, 1))
+# define LLVM_PACKED_END   __pragma(pack(pop))
+#else
+# define LLVM_PACKED(d) d __attribute__((packed))
+# define LLVM_PACKED_START _Pragma("pack(push, 1)")
+# define LLVM_PACKED_END   _Pragma("pack(pop)")
+#endif
+#endif
+
+/// \macro LLVM_PTR_SIZE
+/// A constant integer equivalent to the value of sizeof(void*).
+/// Generally used in combination with alignas or when doing computation in the
+/// preprocessor.
+#ifndef LLVM_PTR_SIZE
+#ifdef __SIZEOF_POINTER__
+# define LLVM_PTR_SIZE __SIZEOF_POINTER__
+#elif defined(_WIN64)
+# define LLVM_PTR_SIZE 8
+#elif defined(_WIN32)
+# define LLVM_PTR_SIZE 4
+#elif defined(_MSC_VER)
+# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC"
+#else
+# define LLVM_PTR_SIZE sizeof(void *)
+#endif
+#endif
+
+/// \macro LLVM_MEMORY_SANITIZER_BUILD
+/// Whether LLVM itself is built with MemorySanitizer instrumentation.
+#if __has_feature(memory_sanitizer)
+# define LLVM_MEMORY_SANITIZER_BUILD 1
+# include <sanitizer/msan_interface.h>
+# define LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE __attribute__((no_sanitize_memory))
+#else
+# define LLVM_MEMORY_SANITIZER_BUILD 0
+# define __msan_allocated_memory(p, size)
+# define __msan_unpoison(p, size)
+# define LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE
+#endif
+
+/// \macro LLVM_ADDRESS_SANITIZER_BUILD
+/// Whether LLVM itself is built with AddressSanitizer instrumentation.
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+# define LLVM_ADDRESS_SANITIZER_BUILD 1
+# include <sanitizer/asan_interface.h>
+#else
+# define LLVM_ADDRESS_SANITIZER_BUILD 0
+# define __asan_poison_memory_region(p, size)
+# define __asan_unpoison_memory_region(p, size)
+#endif
+
+/// \macro LLVM_THREAD_SANITIZER_BUILD
+/// Whether LLVM itself is built with ThreadSanitizer instrumentation.
+#if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+# define LLVM_THREAD_SANITIZER_BUILD 1
+#else
+# define LLVM_THREAD_SANITIZER_BUILD 0
+#endif
+
+#if LLVM_THREAD_SANITIZER_BUILD
+// Thread Sanitizer is a tool that finds races in code.
+// See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations .
+// tsan detects these exact functions by name.
+#ifdef __cplusplus
+extern "C" {
+#endif
+void AnnotateHappensAfter(const char *file, int line, const volatile void *cv);
+void AnnotateHappensBefore(const char *file, int line, const volatile void *cv);
+void AnnotateIgnoreWritesBegin(const char *file, int line);
+void AnnotateIgnoreWritesEnd(const char *file, int line);
+#ifdef __cplusplus
+}
+#endif
+
+// This marker is used to define a happens-before arc. The race detector will
+// infer an arc from the begin to the end when they share the same pointer
+// argument.
+# define TsanHappensBefore(cv) AnnotateHappensBefore(__FILE__, __LINE__, cv)
+
+// This marker defines the destination of a happens-before arc.
+# define TsanHappensAfter(cv) AnnotateHappensAfter(__FILE__, __LINE__, cv)
+
+// Ignore any races on writes between here and the next TsanIgnoreWritesEnd.
+# define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+
+// Resume checking for racy writes.
+# define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+#else
+# define TsanHappensBefore(cv)
+# define TsanHappensAfter(cv)
+# define TsanIgnoreWritesBegin()
+# define TsanIgnoreWritesEnd()
+#endif
+
+/// \macro LLVM_NO_SANITIZE
+/// Disable a particular sanitizer for a function.
+#ifndef LLVM_NO_SANITIZE
+#if __has_attribute(no_sanitize)
+#define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND)))
+#else
+#define LLVM_NO_SANITIZE(KIND)
+#endif
+#endif
+
+/// Mark debug helper function definitions like dump() that should not be
+/// stripped from debug builds.
+/// Note that you should also surround dump() functions with
+/// `#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)` so they do always
+/// get stripped in release builds.
+// FIXME: Move this to a private config.h as it's not usable in public headers.
+#ifndef LLVM_DUMP_METHOD
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED
+#else
+#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE
+#endif
+#endif
+
+/// \macro LLVM_PRETTY_FUNCTION
+/// Gets a user-friendly looking function signature for the current scope
+/// using the best available method on each platform.  The exact format of the
+/// resulting string is implementation specific and non-portable, so this should
+/// only be used, for example, for logging or diagnostics.
+#ifndef LLVM_PRETTY_FUNCTION
+#if defined(_MSC_VER)
+#define LLVM_PRETTY_FUNCTION __FUNCSIG__
+#elif defined(__GNUC__) || defined(__clang__)
+#define LLVM_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#else
+#define LLVM_PRETTY_FUNCTION __func__
+#endif
+#endif
+
+/// \macro LLVM_THREAD_LOCAL
+/// A thread-local storage specifier which can be used with globals,
+/// extern globals, and static globals.
+///
+/// This is essentially an extremely restricted analog to C++11's thread_local
+/// support. It uses thread_local if available, falling back on gcc __thread
+/// if not. __thread doesn't support many of the C++11 thread_local's
+/// features. You should only use this for PODs that you can statically
+/// initialize to some constant value. In almost all circumstances this is most
+/// appropriate for use with a pointer, integer, or small aggregation of
+/// pointers and integers.
+#if __has_feature(cxx_thread_local) || defined(_MSC_VER)
+#define LLVM_THREAD_LOCAL thread_local
+#else
+// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
+// we only need the restricted functionality that provides.
+#define LLVM_THREAD_LOCAL __thread
+#endif
+
+/// \macro LLVM_ENABLE_EXCEPTIONS
+/// Whether LLVM is built with exception support.
+#if __has_feature(cxx_exceptions)
+#define LLVM_ENABLE_EXCEPTIONS 1
+#elif defined(__GNUC__) && defined(__EXCEPTIONS)
+#define LLVM_ENABLE_EXCEPTIONS 1
+#elif defined(_MSC_VER) && defined(_CPPUNWIND)
+#define LLVM_ENABLE_EXCEPTIONS 1
+#endif
+
+/// \macro LLVM_NO_PROFILE_INSTRUMENT_FUNCTION
+/// Disable the profile instrument for a function.
+#if __has_attribute(no_profile_instrument_function)
+#define LLVM_NO_PROFILE_INSTRUMENT_FUNCTION                                    \
+  __attribute__((no_profile_instrument_function))
+#else
+#define LLVM_NO_PROFILE_INSTRUMENT_FUNCTION
+#endif
+
+#endif
diff --git a/wpiutil/src/main/native/include/wpi/ConvertUTF.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/ConvertUTF.h
similarity index 79%
rename from wpiutil/src/main/native/include/wpi/ConvertUTF.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/ConvertUTF.h
index aa113b1..436bc6d 100644
--- a/wpiutil/src/main/native/include/wpi/ConvertUTF.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/ConvertUTF.h
@@ -1,9 +1,8 @@
 /*===--- ConvertUTF.h - Universal Character Names conversions ---------------===
  *
- *                     The LLVM Compiler Infrastructure
- *
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  *
  *==------------------------------------------------------------------------==*/
 /*
@@ -87,24 +86,21 @@
 
 ------------------------------------------------------------------------ */
 
-#ifndef LLVM_SUPPORT_CONVERTUTF_H
-#define LLVM_SUPPORT_CONVERTUTF_H
+#ifndef WPIUTIL_WPI_CONVERTUTF_H
+#define WPIUTIL_WPI_CONVERTUTF_H
 
-#include "wpi/span.h"
+#include <span>
 
 #include <cstddef>
 #include <string>
 #include <string_view>
 #include <system_error>
 
-// Wrap everything in namespace wpi so that programs can link with wpiutil and
+// Wrap everything in namespace wpi so that programs can link with llvm and
 // their own version of the unicode libraries.
 
 namespace wpi {
 
-template <typename T>
-class SmallVectorImpl;
-
 /* ---------------------------------------------------------------------
     The following 4 definitions are compiler-specific.
     The C standard does not guarantee that wchar_t has at least
@@ -187,6 +183,38 @@
 /*************************************************************************/
 /* Below are LLVM-specific wrappers of the functions above. */
 
+template <typename T> class SmallVectorImpl;
+
+/**
+ * Convert an UTF8 string_view to UTF8, UTF16, or UTF32 depending on
+ * WideCharWidth. The converted data is written to ResultPtr, which needs to
+ * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success,
+ * ResultPtr will point one after the end of the copied string. On failure,
+ * ResultPtr will not be changed, and ErrorPtr will be set to the location of
+ * the first character which could not be converted.
+ * \return true on success.
+ */
+bool ConvertUTF8toWide(unsigned WideCharWidth, std::string_view Source,
+                       char *&ResultPtr, const UTF8 *&ErrorPtr);
+
+/**
+* Converts a UTF-8 string_view to a std::wstring.
+* \return true on success.
+*/
+bool ConvertUTF8toWide(std::string_view Source, std::wstring &Result);
+
+/**
+* Converts a UTF-8 C-string to a std::wstring.
+* \return true on success.
+*/
+bool ConvertUTF8toWide(const char *Source, std::wstring &Result);
+
+/**
+* Converts a std::wstring to a UTF-8 encoded std::string.
+* \return true on success.
+*/
+bool convertWideToUTF8(const std::wstring &Source, SmallVectorImpl<char> &Result);
+
 
 /**
  * Convert an Unicode code point to UTF8 sequence.
@@ -215,10 +243,10 @@
  *
  * \sa ConvertUTF8toUTF32
  */
-static inline ConversionResult convertUTF8Sequence(const UTF8 **source,
-                                                   const UTF8 *sourceEnd,
-                                                   UTF32 *target,
-                                                   ConversionFlags flags) {
+inline ConversionResult convertUTF8Sequence(const UTF8 **source,
+                                            const UTF8 *sourceEnd,
+                                            UTF32 *target,
+                                            ConversionFlags flags) {
   if (*source == sourceEnd)
     return sourceExhausted;
   unsigned size = getNumBytesForUTF8(**source);
@@ -231,15 +259,25 @@
  * Returns true if a blob of text starts with a UTF-16 big or little endian byte
  * order mark.
  */
-bool hasUTF16ByteOrderMark(span<const char> SrcBytes);
+bool hasUTF16ByteOrderMark(std::span<const char> SrcBytes);
 
 /**
- * Converts a UTF-16 string into a UTF-8 string.
+ * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.
  *
+ * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text.
+ * \param [out] Out Converted UTF-8 is stored here on success.
  * \returns true on success
  */
-bool convertUTF16ToUTF8String(span<const UTF16> SrcUTF16,
-                              SmallVectorImpl<char> &DstUTF8);
+bool convertUTF16ToUTF8String(std::span<const char> SrcBytes, SmallVectorImpl<char> &Out);
+
+/**
+* Converts a UTF16 string into a UTF8 std::string.
+*
+* \param [in] Src A buffer of UTF-16 encoded text.
+* \param [out] Out Converted UTF-8 is stored here on success.
+* \returns true on success
+*/
+bool convertUTF16ToUTF8String(std::span<const UTF16> Src, SmallVectorImpl<char> &Out);
 
 /**
  * Converts a UTF-8 string into a UTF-16 string with native endianness.
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/DJB.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/DJB.h
new file mode 100644
index 0000000..2615bba
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/DJB.h
@@ -0,0 +1,29 @@
+//===-- llvm/Support/DJB.h ---DJB Hash --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for the DJ Bernstein hash function.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_DJB_H
+#define WPIUTIL_WPI_DJB_H
+
+#include <string_view>
+
+namespace wpi {
+
+/// The Bernstein hash function used by the DWARF accelerator tables.
+inline uint32_t djbHash(std::string_view Buffer, uint32_t H = 5381) {
+  for (unsigned char C : Buffer)
+    H = (H << 5) + H + C;
+  return H;
+}
+
+} // namespace wpi
+
+#endif // WPIUTIL_WPI_DJB_H
diff --git a/wpiutil/src/main/native/include/wpi/DenseMap.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/DenseMap.h
similarity index 83%
rename from wpiutil/src/main/native/include/wpi/DenseMap.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/DenseMap.h
index 12bb712..b1ffd43 100644
--- a/wpiutil/src/main/native/include/wpi/DenseMap.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/DenseMap.h
@@ -1,14 +1,14 @@
 //===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// This file defines the DenseMap class.
-//
+///
+/// \file
+/// This file defines the DenseMap class.
+///
 //===----------------------------------------------------------------------===//
 
 #ifndef WPIUTIL_WPI_DENSEMAP_H
@@ -19,12 +19,14 @@
 #include "wpi/AlignOf.h"
 #include "wpi/Compiler.h"
 #include "wpi/MathExtras.h"
-#include "wpi/PointerLikeTypeTraits.h"
+#include "wpi/MemAlloc.h"
+#include "wpi/ReverseIteration.h"
 #include "wpi/type_traits.h"
 #include <algorithm>
 #include <cassert>
 #include <cstddef>
 #include <cstring>
+#include <initializer_list>
 #include <iterator>
 #include <new>
 #include <type_traits>
@@ -38,6 +40,8 @@
 // implementation without requiring two members.
 template <typename KeyT, typename ValueT>
 struct DenseMapPair : public std::pair<KeyT, ValueT> {
+  using std::pair<KeyT, ValueT>::pair;
+
   KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; }
   const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; }
   ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; }
@@ -73,6 +77,8 @@
     // empty buckets.
     if (empty())
       return end();
+    if (shouldReverseIterate<KeyT>())
+      return makeIterator(getBucketsEnd() - 1, getBuckets(), *this);
     return makeIterator(getBuckets(), getBucketsEnd(), *this);
   }
   inline iterator end() {
@@ -81,6 +87,8 @@
   inline const_iterator begin() const {
     if (empty())
       return end();
+    if (shouldReverseIterate<KeyT>())
+      return makeConstIterator(getBucketsEnd() - 1, getBuckets(), *this);
     return makeConstIterator(getBuckets(), getBucketsEnd(), *this);
   }
   inline const_iterator end() const {
@@ -113,8 +121,8 @@
     }
 
     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
-    if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) {
-      // Use a simpler loop when these are trivial types.
+    if (std::is_trivially_destructible<ValueT>::value) {
+      // Use a simpler loop when values don't need destruction.
       for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
         P->getFirst() = EmptyKey;
     } else {
@@ -143,13 +151,19 @@
   iterator find(const_arg_type_t<KeyT> Val) {
     BucketT *TheBucket;
     if (LookupBucketFor(Val, TheBucket))
-      return makeIterator(TheBucket, getBucketsEnd(), *this, true);
+      return makeIterator(TheBucket,
+                          shouldReverseIterate<KeyT>() ? getBuckets()
+                                                       : getBucketsEnd(),
+                          *this, true);
     return end();
   }
   const_iterator find(const_arg_type_t<KeyT> Val) const {
     const BucketT *TheBucket;
     if (LookupBucketFor(Val, TheBucket))
-      return makeConstIterator(TheBucket, getBucketsEnd(), *this, true);
+      return makeConstIterator(TheBucket,
+                               shouldReverseIterate<KeyT>() ? getBuckets()
+                                                            : getBucketsEnd(),
+                               *this, true);
     return end();
   }
 
@@ -162,14 +176,20 @@
   iterator find_as(const LookupKeyT &Val) {
     BucketT *TheBucket;
     if (LookupBucketFor(Val, TheBucket))
-      return makeIterator(TheBucket, getBucketsEnd(), *this, true);
+      return makeIterator(TheBucket,
+                          shouldReverseIterate<KeyT>() ? getBuckets()
+                                                       : getBucketsEnd(),
+                          *this, true);
     return end();
   }
   template<class LookupKeyT>
   const_iterator find_as(const LookupKeyT &Val) const {
     const BucketT *TheBucket;
     if (LookupBucketFor(Val, TheBucket))
-      return makeConstIterator(TheBucket, getBucketsEnd(), *this, true);
+      return makeConstIterator(TheBucket,
+                               shouldReverseIterate<KeyT>() ? getBuckets()
+                                                            : getBucketsEnd(),
+                               *this, true);
     return end();
   }
 
@@ -203,16 +223,22 @@
   std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&... Args) {
     BucketT *TheBucket;
     if (LookupBucketFor(Key, TheBucket))
-      return std::make_pair(
-               makeIterator(TheBucket, getBucketsEnd(), *this, true),
-               false); // Already in map.
+      return std::make_pair(makeIterator(TheBucket,
+                                         shouldReverseIterate<KeyT>()
+                                             ? getBuckets()
+                                             : getBucketsEnd(),
+                                         *this, true),
+                            false); // Already in map.
 
     // Otherwise, insert the new element.
     TheBucket =
         InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...);
-    return std::make_pair(
-             makeIterator(TheBucket, getBucketsEnd(), *this, true),
-             true);
+    return std::make_pair(makeIterator(TheBucket,
+                                       shouldReverseIterate<KeyT>()
+                                           ? getBuckets()
+                                           : getBucketsEnd(),
+                                       *this, true),
+                          true);
   }
 
   // Inserts key,value pair into the map if the key isn't already in the map.
@@ -222,15 +248,21 @@
   std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&... Args) {
     BucketT *TheBucket;
     if (LookupBucketFor(Key, TheBucket))
-      return std::make_pair(
-               makeIterator(TheBucket, getBucketsEnd(), *this, true),
-               false); // Already in map.
+      return std::make_pair(makeIterator(TheBucket,
+                                         shouldReverseIterate<KeyT>()
+                                             ? getBuckets()
+                                             : getBucketsEnd(),
+                                         *this, true),
+                            false); // Already in map.
 
     // Otherwise, insert the new element.
     TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...);
-    return std::make_pair(
-             makeIterator(TheBucket, getBucketsEnd(), *this, true),
-             true);
+    return std::make_pair(makeIterator(TheBucket,
+                                       shouldReverseIterate<KeyT>()
+                                           ? getBuckets()
+                                           : getBucketsEnd(),
+                                       *this, true),
+                          true);
   }
 
   /// Alternate version of insert() which allows a different, and possibly
@@ -243,16 +275,22 @@
                                       const LookupKeyT &Val) {
     BucketT *TheBucket;
     if (LookupBucketFor(Val, TheBucket))
-      return std::make_pair(
-               makeIterator(TheBucket, getBucketsEnd(), *this, true),
-               false); // Already in map.
+      return std::make_pair(makeIterator(TheBucket,
+                                         shouldReverseIterate<KeyT>()
+                                             ? getBuckets()
+                                             : getBucketsEnd(),
+                                         *this, true),
+                            false); // Already in map.
 
     // Otherwise, insert the new element.
     TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first),
                                            std::move(KV.second), Val);
-    return std::make_pair(
-             makeIterator(TheBucket, getBucketsEnd(), *this, true),
-             true);
+    return std::make_pair(makeIterator(TheBucket,
+                                       shouldReverseIterate<KeyT>()
+                                           ? getBuckets()
+                                           : getBucketsEnd(),
+                                       *this, true),
+                          true);
   }
 
   /// insert - Range insertion of pairs.
@@ -389,7 +427,8 @@
     setNumEntries(other.getNumEntries());
     setNumTombstones(other.getNumTombstones());
 
-    if (isPodLike<KeyT>::value && isPodLike<ValueT>::value)
+    if (std::is_trivially_copyable<KeyT>::value &&
+        std::is_trivially_copyable<ValueT>::value)
       memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(),
              getNumBuckets() * sizeof(BucketT));
     else
@@ -426,12 +465,20 @@
   iterator makeIterator(BucketT *P, BucketT *E,
                         DebugEpochBase &Epoch,
                         bool NoAdvance=false) {
+    if (shouldReverseIterate<KeyT>()) {
+      BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1;
+      return iterator(B, E, Epoch, NoAdvance);
+    }
     return iterator(P, E, Epoch, NoAdvance);
   }
 
   const_iterator makeConstIterator(const BucketT *P, const BucketT *E,
                                    const DebugEpochBase &Epoch,
                                    const bool NoAdvance=false) const {
+    if (shouldReverseIterate<KeyT>()) {
+      const BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1;
+      return const_iterator(B, E, Epoch, NoAdvance);
+    }
     return const_iterator(P, E, Epoch, NoAdvance);
   }
 
@@ -679,7 +726,7 @@
   unsigned NumBuckets;
 
 public:
-  /// Create a DenseMap wth an optional \p InitialReserve that guarantee that
+  /// Create a DenseMap with an optional \p InitialReserve that guarantee that
   /// this number of elements can be inserted in the map without grow()
   explicit DenseMap(unsigned InitialReserve = 0) { init(InitialReserve); }
 
@@ -706,7 +753,7 @@
 
   ~DenseMap() {
     this->destroyAll();
-    operator delete(Buckets);
+    deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
   }
 
   void swap(DenseMap& RHS) {
@@ -726,7 +773,7 @@
 
   DenseMap& operator=(DenseMap &&other) {
     this->destroyAll();
-    operator delete(Buckets);
+    deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
     init(0);
     swap(other);
     return *this;
@@ -734,7 +781,7 @@
 
   void copyFrom(const DenseMap& other) {
     this->destroyAll();
-    operator delete(Buckets);
+    deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
     if (allocateBuckets(other.NumBuckets)) {
       this->BaseT::copyFrom(other);
     } else {
@@ -767,10 +814,12 @@
     this->moveFromOldBuckets(OldBuckets, OldBuckets+OldNumBuckets);
 
     // Free the old table.
-    operator delete(OldBuckets);
+    deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets,
+                      alignof(BucketT));
   }
 
   void shrink_and_clear() {
+    unsigned OldNumBuckets = NumBuckets;
     unsigned OldNumEntries = NumEntries;
     this->destroyAll();
 
@@ -783,7 +832,8 @@
       return;
     }
 
-    operator delete(Buckets);
+    deallocate_buffer(Buckets, sizeof(BucketT) * OldNumBuckets,
+                      alignof(BucketT));
     init(NewNumBuckets);
   }
 
@@ -819,7 +869,8 @@
       return false;
     }
 
-    Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets));
+    Buckets = static_cast<BucketT *>(
+        allocate_buffer(sizeof(BucketT) * NumBuckets, alignof(BucketT)));
     return true;
   }
 };
@@ -874,6 +925,9 @@
     this->insert(I, E);
   }
 
+  SmallDenseMap(std::initializer_list<typename BaseT::value_type> Vals)
+      : SmallDenseMap(Vals.begin(), Vals.end()) {}
+
   ~SmallDenseMap() {
     this->destroyAll();
     deallocateBuckets();
@@ -904,7 +958,7 @@
           std::swap(*LHSB, *RHSB);
           continue;
         }
-        // Swap separately and handle any assymetry.
+        // Swap separately and handle any asymmetry.
         std::swap(LHSB->getFirst(), RHSB->getFirst());
         if (hasLHSValue) {
           ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond()));
@@ -986,16 +1040,13 @@
   }
 
   void grow(unsigned AtLeast) {
-    if (AtLeast >= InlineBuckets)
+    if (AtLeast > InlineBuckets)
       AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast-1));
 
     if (Small) {
-      if (AtLeast < InlineBuckets)
-        return; // Nothing to do.
-
       // First move the inline buckets into a temporary storage.
       AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage;
-      BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer);
+      BucketT *TmpBegin = reinterpret_cast<BucketT *>(&TmpStorage);
       BucketT *TmpEnd = TmpBegin;
 
       // Loop over the buckets, moving non-empty, non-tombstones into the
@@ -1015,10 +1066,13 @@
         P->getFirst().~KeyT();
       }
 
-      // Now make this map use the large rep, and move all the entries back
-      // into it.
-      Small = false;
-      new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
+      // AtLeast == InlineBuckets can happen if there are many tombstones,
+      // and grow() is used to remove them. Usually we always switch to the
+      // large rep here.
+      if (AtLeast > InlineBuckets) {
+        Small = false;
+        new (getLargeRep()) LargeRep(allocateBuckets(AtLeast));
+      }
       this->moveFromOldBuckets(TmpBegin, TmpEnd);
       return;
     }
@@ -1034,7 +1088,8 @@
     this->moveFromOldBuckets(OldRep.Buckets, OldRep.Buckets+OldRep.NumBuckets);
 
     // Free the old table.
-    operator delete(OldRep.Buckets);
+    deallocate_buffer(OldRep.Buckets, sizeof(BucketT) * OldRep.NumBuckets,
+                      alignof(BucketT));
   }
 
   void shrink_and_clear() {
@@ -1081,8 +1136,8 @@
     assert(Small);
     // Note that this cast does not violate aliasing rules as we assert that
     // the memory's dynamic type is the small, inline bucket buffer, and the
-    // 'storage.buffer' static type is 'char *'.
-    return reinterpret_cast<const BucketT *>(storage.buffer);
+    // 'storage' is a POD containing a char buffer.
+    return reinterpret_cast<const BucketT *>(&storage);
   }
 
   BucketT *getInlineBuckets() {
@@ -1093,7 +1148,7 @@
   const LargeRep *getLargeRep() const {
     assert(!Small);
     // Note, same rule about aliasing as with getInlineBuckets.
-    return reinterpret_cast<const LargeRep *>(storage.buffer);
+    return reinterpret_cast<const LargeRep *>(&storage);
   }
 
   LargeRep *getLargeRep() {
@@ -1118,15 +1173,17 @@
     if (Small)
       return;
 
-    operator delete(getLargeRep()->Buckets);
+    deallocate_buffer(getLargeRep()->Buckets,
+                      sizeof(BucketT) * getLargeRep()->NumBuckets,
+                      alignof(BucketT));
     getLargeRep()->~LargeRep();
   }
 
   LargeRep allocateBuckets(unsigned Num) {
     assert(Num > InlineBuckets && "Must allocate more buckets than are inline");
-    LargeRep Rep = {
-      static_cast<BucketT*>(operator new(sizeof(BucketT) * Num)), Num
-    };
+    LargeRep Rep = {static_cast<BucketT *>(allocate_buffer(
+                        sizeof(BucketT) * Num, alignof(BucketT))),
+                    Num};
     return Rep;
   }
 };
@@ -1137,8 +1194,6 @@
   friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
   friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
 
-  using ConstIterator = DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
-
 public:
   using difference_type = ptrdiff_t;
   using value_type =
@@ -1160,6 +1215,10 @@
     assert(isHandleInSync() && "invalid construction!");
 
     if (NoAdvance) return;
+    if (shouldReverseIterate<KeyT>()) {
+      RetreatPastEmptyBuckets();
+      return;
+    }
     AdvancePastEmptyBuckets();
   }
 
@@ -1167,37 +1226,48 @@
   // for const iterator destinations so it doesn't end up as a user defined copy
   // constructor.
   template <bool IsConstSrc,
-            typename = typename std::enable_if<!IsConstSrc && IsConst>::type>
+            typename = std::enable_if_t<!IsConstSrc && IsConst>>
   DenseMapIterator(
       const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I)
       : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
 
   reference operator*() const {
     assert(isHandleInSync() && "invalid iterator access!");
+    assert(Ptr != End && "dereferencing end() iterator");
+    if (shouldReverseIterate<KeyT>())
+      return Ptr[-1];
     return *Ptr;
   }
   pointer operator->() const {
     assert(isHandleInSync() && "invalid iterator access!");
+    assert(Ptr != End && "dereferencing end() iterator");
+    if (shouldReverseIterate<KeyT>())
+      return &(Ptr[-1]);
     return Ptr;
   }
 
-  bool operator==(const ConstIterator &RHS) const {
-    assert((!Ptr || isHandleInSync()) && "handle not in sync!");
+  friend bool operator==(const DenseMapIterator &LHS,
+                         const DenseMapIterator &RHS) {
+    assert((!LHS.Ptr || LHS.isHandleInSync()) && "handle not in sync!");
     assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
-    assert(getEpochAddress() == RHS.getEpochAddress() &&
+    assert(LHS.getEpochAddress() == RHS.getEpochAddress() &&
            "comparing incomparable iterators!");
-    return Ptr == RHS.Ptr;
+    return LHS.Ptr == RHS.Ptr;
   }
-  bool operator!=(const ConstIterator &RHS) const {
-    assert((!Ptr || isHandleInSync()) && "handle not in sync!");
-    assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
-    assert(getEpochAddress() == RHS.getEpochAddress() &&
-           "comparing incomparable iterators!");
-    return Ptr != RHS.Ptr;
+
+  friend bool operator!=(const DenseMapIterator &LHS,
+                         const DenseMapIterator &RHS) {
+    return !(LHS == RHS);
   }
 
   inline DenseMapIterator& operator++() {  // Preincrement
     assert(isHandleInSync() && "invalid iterator access!");
+    assert(Ptr != End && "incrementing end() iterator");
+    if (shouldReverseIterate<KeyT>()) {
+      --Ptr;
+      RetreatPastEmptyBuckets();
+      return *this;
+    }
     ++Ptr;
     AdvancePastEmptyBuckets();
     return *this;
@@ -1236,4 +1306,4 @@
 
 } // end namespace wpi
 
-#endif // LLVM_ADT_DENSEMAP_H
+#endif // WPIUTIL_WPI_DENSEMAP_H
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/DenseMapInfo.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/DenseMapInfo.h
new file mode 100644
index 0000000..0ff8fc9
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/DenseMapInfo.h
@@ -0,0 +1,293 @@
+//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines DenseMapInfo traits for DenseMap.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_DENSEMAPINFO_H
+#define WPIUTIL_WPI_DENSEMAPINFO_H
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <tuple>
+#include <utility>
+
+namespace wpi {
+
+namespace detail {
+
+/// Simplistic combination of 32-bit hash values into 32-bit hash values.
+static inline unsigned combineHashValue(unsigned a, unsigned b) {
+  uint64_t key = (uint64_t)a << 32 | (uint64_t)b;
+  key += ~(key << 32);
+  key ^= (key >> 22);
+  key += ~(key << 13);
+  key ^= (key >> 8);
+  key += (key << 3);
+  key ^= (key >> 15);
+  key += ~(key << 27);
+  key ^= (key >> 31);
+  return (unsigned)key;
+}
+
+} // end namespace detail
+
+/// An information struct used to provide DenseMap with the various necessary
+/// components for a given value type `T`. `Enable` is an optional additional
+/// parameter that is used to support SFINAE (generally using std::enable_if_t)
+/// in derived DenseMapInfo specializations; in non-SFINAE use cases this should
+/// just be `void`.
+template<typename T, typename Enable = void>
+struct DenseMapInfo {
+  //static inline T getEmptyKey();
+  //static inline T getTombstoneKey();
+  //static unsigned getHashValue(const T &Val);
+  //static bool isEqual(const T &LHS, const T &RHS);
+};
+
+// Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
+// that are aligned to alignof(T) bytes, but try to avoid requiring T to be
+// complete. This allows clients to instantiate DenseMap<T*, ...> with forward
+// declared key types. Assume that no pointer key type requires more than 4096
+// bytes of alignment.
+template<typename T>
+struct DenseMapInfo<T*> {
+  // The following should hold, but it would require T to be complete:
+  // static_assert(alignof(T) <= (1 << Log2MaxAlign),
+  //               "DenseMap does not support pointer keys requiring more than "
+  //               "Log2MaxAlign bits of alignment");
+  static constexpr uintptr_t Log2MaxAlign = 12;
+
+  static inline T* getEmptyKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-1);
+    Val <<= Log2MaxAlign;
+    return reinterpret_cast<T*>(Val);
+  }
+
+  static inline T* getTombstoneKey() {
+    uintptr_t Val = static_cast<uintptr_t>(-2);
+    Val <<= Log2MaxAlign;
+    return reinterpret_cast<T*>(Val);
+  }
+
+  static unsigned getHashValue(const T *PtrVal) {
+    return (unsigned((uintptr_t)PtrVal) >> 4) ^
+           (unsigned((uintptr_t)PtrVal) >> 9);
+  }
+
+  static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
+};
+
+// Provide DenseMapInfo for chars.
+template<> struct DenseMapInfo<char> {
+  static inline char getEmptyKey() { return ~0; }
+  static inline char getTombstoneKey() { return ~0 - 1; }
+  static unsigned getHashValue(const char& Val) { return Val * 37U; }
+
+  static bool isEqual(const char &LHS, const char &RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for unsigned chars.
+template <> struct DenseMapInfo<unsigned char> {
+  static inline unsigned char getEmptyKey() { return ~0; }
+  static inline unsigned char getTombstoneKey() { return ~0 - 1; }
+  static unsigned getHashValue(const unsigned char &Val) { return Val * 37U; }
+
+  static bool isEqual(const unsigned char &LHS, const unsigned char &RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for unsigned shorts.
+template <> struct DenseMapInfo<unsigned short> {
+  static inline unsigned short getEmptyKey() { return 0xFFFF; }
+  static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
+  static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
+
+  static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for unsigned ints.
+template<> struct DenseMapInfo<unsigned> {
+  static inline unsigned getEmptyKey() { return ~0U; }
+  static inline unsigned getTombstoneKey() { return ~0U - 1; }
+  static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
+
+  static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for unsigned longs.
+template<> struct DenseMapInfo<unsigned long> {
+  static inline unsigned long getEmptyKey() { return ~0UL; }
+  static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
+
+  static unsigned getHashValue(const unsigned long& Val) {
+    return (unsigned)(Val * 37UL);
+  }
+
+  static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for unsigned long longs.
+template<> struct DenseMapInfo<unsigned long long> {
+  static inline unsigned long long getEmptyKey() { return ~0ULL; }
+  static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
+
+  static unsigned getHashValue(const unsigned long long& Val) {
+    return (unsigned)(Val * 37ULL);
+  }
+
+  static bool isEqual(const unsigned long long& LHS,
+                      const unsigned long long& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for shorts.
+template <> struct DenseMapInfo<short> {
+  static inline short getEmptyKey() { return 0x7FFF; }
+  static inline short getTombstoneKey() { return -0x7FFF - 1; }
+  static unsigned getHashValue(const short &Val) { return Val * 37U; }
+  static bool isEqual(const short &LHS, const short &RHS) { return LHS == RHS; }
+};
+
+// Provide DenseMapInfo for ints.
+template<> struct DenseMapInfo<int> {
+  static inline int getEmptyKey() { return 0x7fffffff; }
+  static inline int getTombstoneKey() { return -0x7fffffff - 1; }
+  static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
+
+  static bool isEqual(const int& LHS, const int& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for longs.
+template<> struct DenseMapInfo<long> {
+  static inline long getEmptyKey() {
+    return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
+  }
+
+  static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
+
+  static unsigned getHashValue(const long& Val) {
+    return (unsigned)(Val * 37UL);
+  }
+
+  static bool isEqual(const long& LHS, const long& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for long longs.
+template<> struct DenseMapInfo<long long> {
+  static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
+  static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
+
+  static unsigned getHashValue(const long long& Val) {
+    return (unsigned)(Val * 37ULL);
+  }
+
+  static bool isEqual(const long long& LHS,
+                      const long long& RHS) {
+    return LHS == RHS;
+  }
+};
+
+// Provide DenseMapInfo for all pairs whose members have info.
+template<typename T, typename U>
+struct DenseMapInfo<std::pair<T, U>> {
+  using Pair = std::pair<T, U>;
+  using FirstInfo = DenseMapInfo<T>;
+  using SecondInfo = DenseMapInfo<U>;
+
+  static inline Pair getEmptyKey() {
+    return std::make_pair(FirstInfo::getEmptyKey(),
+                          SecondInfo::getEmptyKey());
+  }
+
+  static inline Pair getTombstoneKey() {
+    return std::make_pair(FirstInfo::getTombstoneKey(),
+                          SecondInfo::getTombstoneKey());
+  }
+
+  static unsigned getHashValue(const Pair& PairVal) {
+    return detail::combineHashValue(FirstInfo::getHashValue(PairVal.first),
+                                    SecondInfo::getHashValue(PairVal.second));
+  }
+
+  static bool isEqual(const Pair &LHS, const Pair &RHS) {
+    return FirstInfo::isEqual(LHS.first, RHS.first) &&
+           SecondInfo::isEqual(LHS.second, RHS.second);
+  }
+};
+
+// Provide DenseMapInfo for all tuples whose members have info.
+template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> {
+  using Tuple = std::tuple<Ts...>;
+
+  static inline Tuple getEmptyKey() {
+    return Tuple(DenseMapInfo<Ts>::getEmptyKey()...);
+  }
+
+  static inline Tuple getTombstoneKey() {
+    return Tuple(DenseMapInfo<Ts>::getTombstoneKey()...);
+  }
+
+  template <unsigned I>
+  static unsigned getHashValueImpl(const Tuple &values, std::false_type) {
+    using EltType = typename std::tuple_element<I, Tuple>::type;
+    std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
+    return detail::combineHashValue(
+        DenseMapInfo<EltType>::getHashValue(std::get<I>(values)),
+        getHashValueImpl<I + 1>(values, atEnd));
+  }
+
+  template <unsigned I>
+  static unsigned getHashValueImpl(const Tuple &, std::true_type) {
+    return 0;
+  }
+
+  static unsigned getHashValue(const std::tuple<Ts...> &values) {
+    std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
+    return getHashValueImpl<0>(values, atEnd);
+  }
+
+  template <unsigned I>
+  static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::false_type) {
+    using EltType = typename std::tuple_element<I, Tuple>::type;
+    std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd;
+    return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), std::get<I>(rhs)) &&
+           isEqualImpl<I + 1>(lhs, rhs, atEnd);
+  }
+
+  template <unsigned I>
+  static bool isEqualImpl(const Tuple &, const Tuple &, std::true_type) {
+    return true;
+  }
+
+  static bool isEqual(const Tuple &lhs, const Tuple &rhs) {
+    std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd;
+    return isEqualImpl<0>(lhs, rhs, atEnd);
+  }
+};
+
+} // end namespace wpi
+
+#endif // WPIUTIL_WPI_DENSEMAPINFO_H
diff --git a/wpiutil/src/main/native/include/wpi/Endian.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Endian.h
similarity index 85%
rename from wpiutil/src/main/native/include/wpi/Endian.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/Endian.h
index b31cb2d..d243a13 100644
--- a/wpiutil/src/main/native/include/wpi/Endian.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Endian.h
@@ -1,9 +1,8 @@
 //===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -14,14 +13,8 @@
 #ifndef WPIUTIL_WPI_ENDIAN_H
 #define WPIUTIL_WPI_ENDIAN_H
 
-#include "wpi/AlignOf.h"
 #include "wpi/Compiler.h"
 #include "wpi/SwapByteOrder.h"
-
-#if defined(__linux__) || defined(__GNU__)
-#include <endian.h>
-#endif
-
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -38,7 +31,7 @@
 
 namespace detail {
 
-// value is either alignment, or alignof(T) if alignment is 0.
+/// ::value is either alignment, or alignof(T) if alignment is 0.
 template<class T, int alignment>
 struct PickAlignment {
  enum { value = alignment == 0 ? alignof(T) : alignment };
@@ -49,13 +42,7 @@
 namespace endian {
 
 constexpr endianness system_endianness() {
-#ifdef _WIN32
-  return little;
-#elif defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN
-  return big;
-#else
-  return little;
-#endif
+  return sys::IsBigEndianHost ? big : little;
 }
 
 template <typename value_type>
@@ -89,13 +76,7 @@
          endianness endian,
          std::size_t alignment>
 inline value_type read(const void *memory) {
-  value_type ret;
-
-  memcpy(&ret,
-         LLVM_ASSUME_ALIGNED(
-             memory, (detail::PickAlignment<value_type, alignment>::value)),
-         sizeof(value_type));
-  return byte_swap<value_type, endian>(ret);
+  return read<value_type, alignment>(memory, endian);
 }
 
 /// Read a value of a particular endianness from a buffer, and increment the
@@ -110,9 +91,7 @@
 template<typename value_type, endianness endian, std::size_t alignment,
          typename CharT>
 inline value_type readNext(const CharT *&memory) {
-  value_type ret = read<value_type, endian, alignment>(memory);
-  memory += sizeof(value_type);
-  return ret;
+  return readNext<value_type, alignment, CharT>(memory, endian);
 }
 
 /// Write a value to memory with a particular endianness.
@@ -128,12 +107,12 @@
          endianness endian,
          std::size_t alignment>
 inline void write(void *memory, value_type value) {
-  value = byte_swap<value_type, endian>(value);
-  memcpy(LLVM_ASSUME_ALIGNED(
-             memory, (detail::PickAlignment<value_type, alignment>::value)),
-         &value, sizeof(value_type));
+  write<value_type, alignment>(memory, value, endian);
 }
 
+template <typename value_type>
+using make_unsigned_t = std::make_unsigned_t<value_type>;
+
 /// Read a value of a particular endianness from memory, for a location
 /// that starts at the given bit offset within the first byte.
 template <typename value_type, endianness endian, std::size_t alignment>
@@ -152,15 +131,15 @@
     val[1] = byte_swap<value_type, endian>(val[1]);
 
     // Shift bits from the lower value into place.
-    std::make_unsigned_t<value_type> lowerVal = val[0] >> startBit;
+    make_unsigned_t<value_type> lowerVal = val[0] >> startBit;
     // Mask off upper bits after right shift in case of signed type.
-    std::make_unsigned_t<value_type> numBitsFirstVal =
+    make_unsigned_t<value_type> numBitsFirstVal =
         (sizeof(value_type) * 8) - startBit;
-    lowerVal &= ((std::make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1;
+    lowerVal &= ((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1;
 
     // Get the bits from the upper value.
-    std::make_unsigned_t<value_type> upperVal =
-        val[1] & (((std::make_unsigned_t<value_type>)1 << startBit) - 1);
+    make_unsigned_t<value_type> upperVal =
+        val[1] & (((make_unsigned_t<value_type>)1 << startBit) - 1);
     // Shift them in to place.
     upperVal <<= numBitsFirstVal;
 
@@ -188,15 +167,15 @@
 
     // Mask off any existing bits in the upper part of the lower value that
     // we want to replace.
-    val[0] &= ((std::make_unsigned_t<value_type>)1 << startBit) - 1;
-    std::make_unsigned_t<value_type> numBitsFirstVal =
+    val[0] &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
+    make_unsigned_t<value_type> numBitsFirstVal =
         (sizeof(value_type) * 8) - startBit;
-    std::make_unsigned_t<value_type> lowerVal = value;
+    make_unsigned_t<value_type> lowerVal = value;
     if (startBit > 0) {
       // Mask off the upper bits in the new value that are not going to go into
       // the lower value. This avoids a left shift of a negative value, which
       // is undefined behavior.
-      lowerVal &= (((std::make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1);
+      lowerVal &= (((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1);
       // Now shift the new bits into place
       lowerVal <<= startBit;
     }
@@ -204,11 +183,11 @@
 
     // Mask off any existing bits in the lower part of the upper value that
     // we want to replace.
-    val[1] &= ~(((std::make_unsigned_t<value_type>)1 << startBit) - 1);
+    val[1] &= ~(((make_unsigned_t<value_type>)1 << startBit) - 1);
     // Next shift the bits that go into the upper value into position.
-    std::make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal;
+    make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal;
     // Mask off upper bits after right shift in case of signed type.
-    upperVal &= ((std::make_unsigned_t<value_type>)1 << startBit) - 1;
+    upperVal &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
     val[1] |= upperVal;
 
     // Finally, rewrite values.
@@ -224,10 +203,13 @@
 
 namespace detail {
 
-template<typename value_type,
-         endianness endian,
-         std::size_t alignment>
+template <typename ValueType, endianness Endian, std::size_t Alignment,
+          std::size_t ALIGN = PickAlignment<ValueType, Alignment>::value>
 struct packed_endian_specific_integral {
+  using value_type = ValueType;
+  static constexpr endianness endian = Endian;
+  static constexpr std::size_t alignment = Alignment;
+
   packed_endian_specific_integral() = default;
 
   explicit packed_endian_specific_integral(value_type val) { *this = val; }
@@ -263,8 +245,9 @@
   }
 
 private:
-  AlignedCharArray<PickAlignment<value_type, alignment>::value,
-                   sizeof(value_type)> Value;
+  struct {
+    alignas(ALIGN) char buffer[sizeof(value_type)];
+  } Value;
 
 public:
   struct ref {
@@ -355,6 +338,17 @@
 using unaligned_int64_t =
     detail::packed_endian_specific_integral<int64_t, native, unaligned>;
 
+template <typename T>
+using little_t = detail::packed_endian_specific_integral<T, little, unaligned>;
+template <typename T>
+using big_t = detail::packed_endian_specific_integral<T, big, unaligned>;
+
+template <typename T>
+using aligned_little_t =
+    detail::packed_endian_specific_integral<T, little, aligned>;
+template <typename T>
+using aligned_big_t = detail::packed_endian_specific_integral<T, big, aligned>;
+
 namespace endian {
 
 template <typename T> inline T read(const void *P, endianness E) {
diff --git a/wpiutil/src/main/native/include/wpi/EpochTracker.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/EpochTracker.h
similarity index 83%
rename from wpiutil/src/main/native/include/wpi/EpochTracker.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/EpochTracker.h
index b26800b..6417c05 100644
--- a/wpiutil/src/main/native/include/wpi/EpochTracker.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/EpochTracker.h
@@ -1,41 +1,27 @@
 //===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
-// These can be used to write iterators that are fail-fast when LLVM is built
-// with asserts enabled.
-//
+///
+/// \file
+/// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
+/// These can be used to write iterators that are fail-fast when LLVM is built
+/// with asserts enabled.
+///
 //===----------------------------------------------------------------------===//
 
-#ifndef WPIUTIL_WPI_EPOCH_TRACKER_H
-#define WPIUTIL_WPI_EPOCH_TRACKER_H
+#ifndef WPIUTIL_WPI_EPOCHTRACKER_H
+#define WPIUTIL_WPI_EPOCHTRACKER_H
+
 
 #include <cstdint>
 
 namespace wpi {
 
-#ifdef NDEBUG //ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
-
-class DebugEpochBase {
-public:
-  void incrementEpoch() {}
-
-  class HandleBase {
-  public:
-    HandleBase() = default;
-    explicit HandleBase(const DebugEpochBase *) {}
-    bool isHandleInSync() const { return true; }
-    const void *getEpochAddress() const { return nullptr; }
-  };
-};
-
-#else
+#ifndef NDEBUG //ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
 
 /// A base class for data structure classes wishing to make iterators
 /// ("handles") pointing into themselves fail-fast.  When building without
@@ -90,6 +76,21 @@
   };
 };
 
+#else
+
+class DebugEpochBase {
+public:
+  void incrementEpoch() {}
+
+  class HandleBase {
+  public:
+    HandleBase() = default;
+    explicit HandleBase(const DebugEpochBase *) {}
+    bool isHandleInSync() const { return true; }
+    const void *getEpochAddress() const { return nullptr; }
+  };
+};
+
 #endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
 
 } // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/Errc.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Errc.h
similarity index 88%
rename from wpiutil/src/main/native/include/wpi/Errc.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/Errc.h
index ebce58a..dee28df 100644
--- a/wpiutil/src/main/native/include/wpi/Errc.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Errc.h
@@ -1,9 +1,8 @@
-//===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- C++ -*-===//
+//===- llvm/Support/Errc.h - Defines the wpi::errc enum --------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -11,7 +10,7 @@
 // some problems with std::errc that can be avoided by using our own
 // enumeration:
 //
-// * std::errc is a namespace in some implementations. That meas that ADL
+// * std::errc is a namespace in some implementations. That means that ADL
 //   doesn't work and it is sometimes necessary to write std::make_error_code
 //   or in templates:
 //   using std::make_error_code;
@@ -23,7 +22,7 @@
 //   the intersection of all the ones we support.
 //
 // * std::errc is just marked with is_error_condition_enum. This means that
-//   common patters like AnErrorCode == errc::no_such_file_or_directory take
+//   common patterns like AnErrorCode == errc::no_such_file_or_directory take
 //   4 virtual calls instead of two comparisons.
 //===----------------------------------------------------------------------===//
 
diff --git a/wpiutil/src/main/native/include/wpi/Errno.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Errno.h
similarity index 66%
rename from wpiutil/src/main/native/include/wpi/Errno.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/Errno.h
index 042d432..febfc37 100644
--- a/wpiutil/src/main/native/include/wpi/Errno.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Errno.h
@@ -1,9 +1,8 @@
 //===- llvm/Support/Errno.h - Portable+convenient errno handling -*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -22,8 +21,8 @@
 namespace sys {
 
 template <typename FailT, typename Fun, typename... Args>
-inline auto RetryAfterSignal(const FailT &Fail, const Fun &F,
-                             const Args &... As) -> decltype(F(As...)) {
+inline decltype(auto) RetryAfterSignal(const FailT &Fail, const Fun &F,
+                                       const Args &... As) {
   decltype(F(As...)) Res;
   do {
     errno = 0;
@@ -35,4 +34,4 @@
 }  // namespace sys
 }  // namespace wpi
 
-#endif  // WPIUTIL_WPI_ERRNO_H
+#endif // WPIUTIL_WPI_ERRNO_H
diff --git a/wpiutil/src/main/native/include/wpi/ErrorHandling.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/ErrorHandling.h
similarity index 79%
rename from wpiutil/src/main/native/include/wpi/ErrorHandling.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/ErrorHandling.h
index da9af4b..7b43671 100644
--- a/wpiutil/src/main/native/include/wpi/ErrorHandling.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/ErrorHandling.h
@@ -1,9 +1,8 @@
 //===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -20,9 +19,10 @@
 #include <string_view>
 
 namespace wpi {
+
   /// An error handler callback.
   typedef void (*fatal_error_handler_t)(void *user_data,
-                                        const std::string& reason,
+                                        const char *reason,
                                         bool gen_crash_diag);
 
   /// install_fatal_error_handler - Installs a new error handler to be used
@@ -65,14 +65,14 @@
 ///
 /// If no error handler is installed the default is to print the message to
 /// standard error, followed by a newline.
-/// After the error handler is called this function will call exit(1), it
+/// After the error handler is called this function will call abort(), it
 /// does not return.
-LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason,
-                                                bool gen_crash_diag = true);
-LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason,
-                                                bool gen_crash_diag = true);
-LLVM_ATTRIBUTE_NORETURN void report_fatal_error(std::string_view reason,
-                                                bool gen_crash_diag = true);
+[[noreturn]] void report_fatal_error(const char *reason,
+                                     bool gen_crash_diag = true);
+[[noreturn]] void report_fatal_error(const std::string &reason,
+                                     bool gen_crash_diag = true);
+[[noreturn]] void report_fatal_error(std::string_view reason,
+                                     bool gen_crash_diag = true);
 
 /// Installs a new bad alloc error handler that should be used whenever a
 /// bad alloc error, e.g. failing malloc/calloc, is encountered by LLVM.
@@ -100,31 +100,32 @@
 
 /// Reports a bad alloc error, calling any user defined bad alloc
 /// error handler. In contrast to the generic 'report_fatal_error'
-/// functions, this function is expected to return, e.g. the user
-/// defined error handler throws an exception.
+/// functions, this function might not terminate, e.g. the user
+/// defined error handler throws an exception, but it won't return.
 ///
 /// Note: When throwing an exception in the bad alloc handler, make sure that
 /// the following unwind succeeds, e.g. do not trigger additional allocations
 /// in the unwind chain.
 ///
-/// If no error handler is installed (default), then a bad_alloc exception
-/// is thrown, if LLVM is compiled with exception support, otherwise an
-/// assertion is called.
-void report_bad_alloc_error(const char *Reason, bool GenCrashDiag = true);
+/// If no error handler is installed (default), throws a bad_alloc exception
+/// if LLVM is compiled with exception support. Otherwise prints the error
+/// to standard error and calls abort().
+[[noreturn]] void report_bad_alloc_error(const char *Reason,
+                                         bool GenCrashDiag = true);
 
 /// This function calls abort(), and prints the optional message to stderr.
 /// Use the wpi_unreachable macro (that adds location info), instead of
 /// calling this function directly.
-LLVM_ATTRIBUTE_NORETURN void
+[[noreturn]] void
 wpi_unreachable_internal(const char *msg = nullptr, const char *file = nullptr,
-                         unsigned line = 0);
+                          unsigned line = 0);
 }
 
 /// Marks that the current location is not supposed to be reachable.
 /// In !NDEBUG builds, prints the message and location info to stderr.
 /// In NDEBUG builds, becomes an optimizer hint that the current location
 /// is not supposed to be reachable.  On compilers that don't support
-/// such hints, prints a reduced message instead.
+/// such hints, prints a reduced message instead and aborts the program.
 ///
 /// Use this instead of assert(0).  It conveys intent more clearly and
 /// allows compilers to omit some unnecessary code.
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/FunctionExtras.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/FunctionExtras.h
new file mode 100644
index 0000000..681b87e
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/FunctionExtras.h
@@ -0,0 +1,427 @@
+//===- FunctionExtras.h - Function type erasure utilities -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides a collection of function (or more generally, callable)
+/// type erasure utilities supplementing those provided by the standard library
+/// in `<function>`.
+///
+/// It provides `unique_function`, which works like `std::function` but supports
+/// move-only callable objects and const-qualification.
+///
+/// Future plans:
+/// - Add a `function` that provides ref-qualified support, which doesn't work
+///   with `std::function`.
+/// - Provide support for specifying multiple signatures to type erase callable
+///   objects with an overload set, such as those produced by generic lambdas.
+/// - Expand to include a copyable utility that directly replaces std::function
+///   but brings the above improvements.
+///
+/// Note that LLVM's utilities are greatly simplified by not supporting
+/// allocators.
+///
+/// If the standard library ever begins to provide comparable facilities we can
+/// consider switching to those.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_FUNCTIONEXTRAS_H
+#define WPIUTIL_WPI_FUNCTIONEXTRAS_H
+
+#include "wpi/PointerIntPair.h"
+#include "wpi/PointerUnion.h"
+#include "wpi/STLForwardCompat.h"
+#include "wpi/MemAlloc.h"
+#include "wpi/type_traits.h"
+#include <cstring>
+#include <memory>
+#include <type_traits>
+
+namespace wpi {
+
+/// unique_function is a type-erasing functor similar to std::function.
+///
+/// It can hold move-only function objects, like lambdas capturing unique_ptrs.
+/// Accordingly, it is movable but not copyable.
+///
+/// It supports const-qualification:
+/// - unique_function<int() const> has a const operator().
+///   It can only hold functions which themselves have a const operator().
+/// - unique_function<int()> has a non-const operator().
+///   It can hold functions with a non-const operator(), like mutable lambdas.
+template <typename FunctionT> class unique_function;
+
+// GCC warns on OutOfLineStorage
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+
+namespace detail {
+
+template <typename T>
+using EnableIfTrivial =
+    std::enable_if_t<wpi::is_trivially_move_constructible<T>::value &&
+                     std::is_trivially_destructible<T>::value>;
+template <typename CallableT, typename ThisT>
+using EnableUnlessSameType =
+    std::enable_if_t<!std::is_same<remove_cvref_t<CallableT>, ThisT>::value>;
+template <typename CallableT, typename Ret, typename... Params>
+using EnableIfCallable = std::enable_if_t<wpi::disjunction<
+    std::is_void<Ret>,
+    std::is_same<decltype(std::declval<CallableT>()(std::declval<Params>()...)),
+                 Ret>,
+    std::is_same<const decltype(std::declval<CallableT>()(
+                     std::declval<Params>()...)),
+                 Ret>,
+    std::is_convertible<decltype(std::declval<CallableT>()(
+                            std::declval<Params>()...)),
+                        Ret>>::value>;
+
+template <typename ReturnT, typename... ParamTs> class UniqueFunctionBase {
+protected:
+  static constexpr size_t InlineStorageSize = sizeof(void *) * 4;
+
+  template <typename T, class = void>
+  struct IsSizeLessThanThresholdT : std::false_type {};
+
+  template <typename T>
+  struct IsSizeLessThanThresholdT<
+      T, std::enable_if_t<sizeof(T) <= 2 * sizeof(void *)>> : std::true_type {};
+
+  // Provide a type function to map parameters that won't observe extra copies
+  // or moves and which are small enough to likely pass in register to values
+  // and all other types to l-value reference types. We use this to compute the
+  // types used in our erased call utility to minimize copies and moves unless
+  // doing so would force things unnecessarily into memory.
+  //
+  // The heuristic used is related to common ABI register passing conventions.
+  // It doesn't have to be exact though, and in one way it is more strict
+  // because we want to still be able to observe either moves *or* copies.
+  template <typename T> struct AdjustedParamTBase {
+    static_assert(!std::is_reference<T>::value,
+                  "references should be handled by template specialization");
+    using type = typename std::conditional<
+        wpi::is_trivially_copy_constructible<T>::value &&
+            wpi::is_trivially_move_constructible<T>::value &&
+            IsSizeLessThanThresholdT<T>::value,
+        T, T &>::type;
+  };
+
+  // This specialization ensures that 'AdjustedParam<V<T>&>' or
+  // 'AdjustedParam<V<T>&&>' does not trigger a compile-time error when 'T' is
+  // an incomplete type and V a templated type.
+  template <typename T> struct AdjustedParamTBase<T &> { using type = T &; };
+  template <typename T> struct AdjustedParamTBase<T &&> { using type = T &; };
+
+  template <typename T>
+  using AdjustedParamT = typename AdjustedParamTBase<T>::type;
+
+  // The type of the erased function pointer we use as a callback to dispatch to
+  // the stored callable when it is trivial to move and destroy.
+  using CallPtrT = ReturnT (*)(void *CallableAddr,
+                               AdjustedParamT<ParamTs>... Params);
+  using MovePtrT = void (*)(void *LHSCallableAddr, void *RHSCallableAddr);
+  using DestroyPtrT = void (*)(void *CallableAddr);
+
+  /// A struct to hold a single trivial callback with sufficient alignment for
+  /// our bitpacking.
+  struct alignas(8) TrivialCallback {
+    CallPtrT CallPtr;
+  };
+
+  /// A struct we use to aggregate three callbacks when we need full set of
+  /// operations.
+  struct alignas(8) NonTrivialCallbacks {
+    CallPtrT CallPtr;
+    MovePtrT MovePtr;
+    DestroyPtrT DestroyPtr;
+  };
+
+  // Create a pointer union between either a pointer to a static trivial call
+  // pointer in a struct or a pointer to a static struct of the call, move, and
+  // destroy pointers.
+  using CallbackPointerUnionT =
+      PointerUnion<TrivialCallback *, NonTrivialCallbacks *>;
+
+  // The main storage buffer. This will either have a pointer to out-of-line
+  // storage or an inline buffer storing the callable.
+  union StorageUnionT {
+    // For out-of-line storage we keep a pointer to the underlying storage and
+    // the size. This is enough to deallocate the memory.
+    struct OutOfLineStorageT {
+      void *StoragePtr;
+      size_t Size;
+      size_t Alignment;
+    } OutOfLineStorage;
+    static_assert(
+        sizeof(OutOfLineStorageT) <= InlineStorageSize,
+        "Should always use all of the out-of-line storage for inline storage!");
+
+    // For in-line storage, we just provide an aligned character buffer. We
+    // provide four pointers worth of storage here.
+    // This is mutable as an inlined `const unique_function<void() const>` may
+    // still modify its own mutable members.
+    mutable
+        typename std::aligned_storage<InlineStorageSize, alignof(void *)>::type
+            InlineStorage;
+  } StorageUnion;
+
+  // A compressed pointer to either our dispatching callback or our table of
+  // dispatching callbacks and the flag for whether the callable itself is
+  // stored inline or not.
+  PointerIntPair<CallbackPointerUnionT, 1, bool> CallbackAndInlineFlag;
+
+  bool isInlineStorage() const { return CallbackAndInlineFlag.getInt(); }
+
+  bool isTrivialCallback() const {
+    return CallbackAndInlineFlag.getPointer().template is<TrivialCallback *>();
+  }
+
+  CallPtrT getTrivialCallback() const {
+    return CallbackAndInlineFlag.getPointer().template get<TrivialCallback *>()->CallPtr;
+  }
+
+  NonTrivialCallbacks *getNonTrivialCallbacks() const {
+    return CallbackAndInlineFlag.getPointer()
+        .template get<NonTrivialCallbacks *>();
+  }
+
+  CallPtrT getCallPtr() const {
+    return isTrivialCallback() ? getTrivialCallback()
+                               : getNonTrivialCallbacks()->CallPtr;
+  }
+
+  // These three functions are only const in the narrow sense. They return
+  // mutable pointers to function state.
+  // This allows unique_function<T const>::operator() to be const, even if the
+  // underlying functor may be internally mutable.
+  //
+  // const callers must ensure they're only used in const-correct ways.
+  void *getCalleePtr() const {
+    return isInlineStorage() ? getInlineStorage() : getOutOfLineStorage();
+  }
+  void *getInlineStorage() const { return &StorageUnion.InlineStorage; }
+  void *getOutOfLineStorage() const {
+    return StorageUnion.OutOfLineStorage.StoragePtr;
+  }
+
+  size_t getOutOfLineStorageSize() const {
+    return StorageUnion.OutOfLineStorage.Size;
+  }
+  size_t getOutOfLineStorageAlignment() const {
+    return StorageUnion.OutOfLineStorage.Alignment;
+  }
+
+  void setOutOfLineStorage(void *Ptr, size_t Size, size_t Alignment) {
+    StorageUnion.OutOfLineStorage = {Ptr, Size, Alignment};
+  }
+
+  template <typename CalledAsT>
+  static ReturnT CallImpl(void *CallableAddr,
+                          AdjustedParamT<ParamTs>... Params) {
+    auto &Func = *reinterpret_cast<CalledAsT *>(CallableAddr);
+    return Func(std::forward<ParamTs>(Params)...);
+  }
+
+  template <typename CallableT>
+  static void MoveImpl(void *LHSCallableAddr, void *RHSCallableAddr) noexcept {
+    new (LHSCallableAddr)
+        CallableT(std::move(*reinterpret_cast<CallableT *>(RHSCallableAddr)));
+  }
+
+  template <typename CallableT>
+  static void DestroyImpl(void *CallableAddr) noexcept {
+    reinterpret_cast<CallableT *>(CallableAddr)->~CallableT();
+  }
+
+  // The pointers to call/move/destroy functions are determined for each
+  // callable type (and called-as type, which determines the overload chosen).
+  // (definitions are out-of-line).
+
+  // By default, we need an object that contains all the different
+  // type erased behaviors needed. Create a static instance of the struct type
+  // here and each instance will contain a pointer to it.
+  // Wrap in a struct to avoid https://gcc.gnu.org/PR71954
+  template <typename CallableT, typename CalledAs, typename Enable = void>
+  struct CallbacksHolder {
+    static NonTrivialCallbacks Callbacks;
+  };
+  // See if we can create a trivial callback. We need the callable to be
+  // trivially moved and trivially destroyed so that we don't have to store
+  // type erased callbacks for those operations.
+  template <typename CallableT, typename CalledAs>
+  struct CallbacksHolder<CallableT, CalledAs, EnableIfTrivial<CallableT>> {
+    static TrivialCallback Callbacks;
+  };
+
+  // A simple tag type so the call-as type to be passed to the constructor.
+  template <typename T> struct CalledAs {};
+
+  // Essentially the "main" unique_function constructor, but subclasses
+  // provide the qualified type to be used for the call.
+  // (We always store a T, even if the call will use a pointer to const T).
+  template <typename CallableT, typename CalledAsT>
+  UniqueFunctionBase(CallableT Callable, CalledAs<CalledAsT>) {
+    bool IsInlineStorage = true;
+    void *CallableAddr = getInlineStorage();
+    if (sizeof(CallableT) > InlineStorageSize ||
+        alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) {
+      IsInlineStorage = false;
+      // Allocate out-of-line storage. FIXME: Use an explicit alignment
+      // parameter in C++17 mode.
+      auto Size = sizeof(CallableT);
+      auto Alignment = alignof(CallableT);
+      CallableAddr = allocate_buffer(Size, Alignment);
+      setOutOfLineStorage(CallableAddr, Size, Alignment);
+    }
+
+    // Now move into the storage.
+    new (CallableAddr) CallableT(std::move(Callable));
+    CallbackAndInlineFlag.setPointerAndInt(
+        &CallbacksHolder<CallableT, CalledAsT>::Callbacks, IsInlineStorage);
+  }
+
+  ~UniqueFunctionBase() {
+    if (!CallbackAndInlineFlag.getPointer())
+      return;
+
+    // Cache this value so we don't re-check it after type-erased operations.
+    bool IsInlineStorage = isInlineStorage();
+
+    if (!isTrivialCallback())
+      getNonTrivialCallbacks()->DestroyPtr(
+          IsInlineStorage ? getInlineStorage() : getOutOfLineStorage());
+
+    if (!IsInlineStorage)
+      deallocate_buffer(getOutOfLineStorage(), getOutOfLineStorageSize(),
+                        getOutOfLineStorageAlignment());
+  }
+
+  UniqueFunctionBase(UniqueFunctionBase &&RHS) noexcept {
+    // Copy the callback and inline flag.
+    CallbackAndInlineFlag = RHS.CallbackAndInlineFlag;
+
+    // If the RHS is empty, just copying the above is sufficient.
+    if (!RHS)
+      return;
+
+    if (!isInlineStorage()) {
+      // The out-of-line case is easiest to move.
+      StorageUnion.OutOfLineStorage = RHS.StorageUnion.OutOfLineStorage;
+    } else if (isTrivialCallback()) {
+      // Move is trivial, just memcpy the bytes across.
+      memcpy(getInlineStorage(), RHS.getInlineStorage(), InlineStorageSize);
+    } else {
+      // Non-trivial move, so dispatch to a type-erased implementation.
+      getNonTrivialCallbacks()->MovePtr(getInlineStorage(),
+                                        RHS.getInlineStorage());
+    }
+
+    // Clear the old callback and inline flag to get back to as-if-null.
+    RHS.CallbackAndInlineFlag = {};
+
+#ifndef NDEBUG
+    // In debug builds, we also scribble across the rest of the storage.
+    memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize);
+#endif
+  }
+
+  UniqueFunctionBase &operator=(UniqueFunctionBase &&RHS) noexcept {
+    if (this == &RHS)
+      return *this;
+
+    // Because we don't try to provide any exception safety guarantees we can
+    // implement move assignment very simply by first destroying the current
+    // object and then move-constructing over top of it.
+    this->~UniqueFunctionBase();
+    new (this) UniqueFunctionBase(std::move(RHS));
+    return *this;
+  }
+
+  UniqueFunctionBase() = default;
+
+public:
+  explicit operator bool() const {
+    return (bool)CallbackAndInlineFlag.getPointer();
+  }
+};
+
+template <typename R, typename... P>
+template <typename CallableT, typename CalledAsT, typename Enable>
+typename UniqueFunctionBase<R, P...>::NonTrivialCallbacks UniqueFunctionBase<
+    R, P...>::CallbacksHolder<CallableT, CalledAsT, Enable>::Callbacks = {
+    &CallImpl<CalledAsT>, &MoveImpl<CallableT>, &DestroyImpl<CallableT>};
+
+template <typename R, typename... P>
+template <typename CallableT, typename CalledAsT>
+typename UniqueFunctionBase<R, P...>::TrivialCallback
+    UniqueFunctionBase<R, P...>::CallbacksHolder<
+        CallableT, CalledAsT, EnableIfTrivial<CallableT>>::Callbacks{
+        &CallImpl<CalledAsT>};
+
+} // namespace detail
+
+template <typename R, typename... P>
+class unique_function<R(P...)> : public detail::UniqueFunctionBase<R, P...> {
+  using Base = detail::UniqueFunctionBase<R, P...>;
+
+public:
+  unique_function() = default;
+  unique_function(std::nullptr_t) {}
+  unique_function(unique_function &&) = default;
+  unique_function(const unique_function &) = delete;
+  unique_function &operator=(unique_function &&) = default;
+  unique_function &operator=(const unique_function &) = delete;
+
+  template <typename CallableT>
+  unique_function(
+      CallableT Callable,
+      detail::EnableUnlessSameType<CallableT, unique_function> * = nullptr,
+      detail::EnableIfCallable<CallableT, R, P...> * = nullptr)
+      : Base(std::forward<CallableT>(Callable),
+             typename Base::template CalledAs<CallableT>{}) {}
+
+  R operator()(P... Params) {
+    return this->getCallPtr()(this->getCalleePtr(), Params...);
+  }
+};
+
+template <typename R, typename... P>
+class unique_function<R(P...) const>
+    : public detail::UniqueFunctionBase<R, P...> {
+  using Base = detail::UniqueFunctionBase<R, P...>;
+
+public:
+  unique_function() = default;
+  unique_function(std::nullptr_t) {}
+  unique_function(unique_function &&) = default;
+  unique_function(const unique_function &) = delete;
+  unique_function &operator=(unique_function &&) = default;
+  unique_function &operator=(const unique_function &) = delete;
+
+  template <typename CallableT>
+  unique_function(
+      CallableT Callable,
+      detail::EnableUnlessSameType<CallableT, unique_function> * = nullptr,
+      detail::EnableIfCallable<const CallableT, R, P...> * = nullptr)
+      : Base(std::forward<CallableT>(Callable),
+             typename Base::template CalledAs<const CallableT>{}) {}
+
+  R operator()(P... Params) const {
+    return this->getCallPtr()(this->getCalleePtr(), Params...);
+  }
+};
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+} // end namespace wpi
+
+#endif // WPIUTIL_WPI_FUNCTIONEXTRAS_H
diff --git a/wpiutil/src/main/native/include/wpi/Hashing.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Hashing.h
similarity index 90%
rename from wpiutil/src/main/native/include/wpi/Hashing.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/Hashing.h
index e58bfdd..0d4a4c6 100644
--- a/wpiutil/src/main/native/include/wpi/Hashing.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/Hashing.h
@@ -1,9 +1,8 @@
 //===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -45,15 +44,14 @@
 #ifndef WPIUTIL_WPI_HASHING_H
 #define WPIUTIL_WPI_HASHING_H
 
-#include "wpi/Endian.h"
+#include "wpi/ErrorHandling.h"
 #include "wpi/SwapByteOrder.h"
 #include "wpi/type_traits.h"
-#include <stdint.h>
 #include <algorithm>
 #include <cassert>
 #include <cstring>
 #include <string>
-#include <string_view>
+#include <tuple>
 #include <utility>
 
 #ifdef _WIN32
@@ -62,6 +60,7 @@
 #endif
 
 namespace wpi {
+template <typename T, typename Enable> struct DenseMapInfo;
 
 /// An opaque object representing a hash code.
 ///
@@ -108,8 +107,7 @@
 /// differing argument types even if they would implicit promote to a common
 /// type without changing the value.
 template <typename T>
-typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
-hash_value(T value);
+std::enable_if_t<is_integral_or_enum<T>::value, hash_code> hash_value(T value);
 
 /// Compute a hash_code for a pointer's address.
 ///
@@ -120,6 +118,10 @@
 template <typename T, typename U>
 hash_code hash_value(const std::pair<T, U> &arg);
 
+/// Compute a hash_code for a tuple.
+template <typename... Ts>
+hash_code hash_value(const std::tuple<Ts...> &arg);
+
 /// Compute a hash_code for a standard string.
 template <typename T>
 hash_code hash_value(const std::basic_string<T> &arg);
@@ -151,7 +153,7 @@
 inline uint64_t fetch64(const char *p) {
   uint64_t result;
   memcpy(&result, p, sizeof(result));
-  if (support::endian::system_endianness() == support::big)
+  if (sys::IsBigEndianHost)
     sys::swapByteOrder(result);
   return result;
 }
@@ -159,16 +161,16 @@
 inline uint32_t fetch32(const char *p) {
   uint32_t result;
   memcpy(&result, p, sizeof(result));
-  if (support::endian::system_endianness() == support::big)
+  if (sys::IsBigEndianHost)
     sys::swapByteOrder(result);
   return result;
 }
 
 /// Some primes between 2^63 and 2^64 for various uses.
-static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
-static const uint64_t k1 = 0xb492b66fbe98f273ULL;
-static const uint64_t k2 = 0x9ae16a3b2f90404fULL;
-static const uint64_t k3 = 0xc949d7c7509e6557ULL;
+static constexpr uint64_t k0 = 0xc3a5c85c97cb3127ULL;
+static constexpr uint64_t k1 = 0xb492b66fbe98f273ULL;
+static constexpr uint64_t k2 = 0x9ae16a3b2f90404fULL;
+static constexpr uint64_t k3 = 0xc949d7c7509e6557ULL;
 
 /// Bitwise right rotate.
 /// Normally this will compile to a single instruction, especially if the
@@ -198,7 +200,7 @@
   uint8_t b = s[len >> 1];
   uint8_t c = s[len - 1];
   uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
-  uint32_t z = static_cast<uint32_t>(len + (static_cast<uint64_t>(c) << 2));
+  uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2);
   return shift_mix(y * k2 ^ z * k3 ^ seed) * k2;
 }
 
@@ -264,7 +266,7 @@
 /// Currently, the algorithm for computing hash codes is based on CityHash and
 /// keeps 56 bytes of arbitrary state.
 struct hash_state {
-  uint64_t h0, h1, h2, h3, h4, h5, h6;
+  uint64_t h0 = 0, h1 = 0, h2 = 0, h3 = 0, h4 = 0, h5 = 0, h6 = 0;
 
   /// Create a new hash_state structure and initialize it based on the
   /// seed and the first 64-byte chunk.
@@ -367,7 +369,7 @@
 /// Helper to get the hashable data representation for a type.
 /// This variant is enabled when the type itself can be used.
 template <typename T>
-typename std::enable_if<is_hashable_data<T>::value, T>::type
+std::enable_if_t<is_hashable_data<T>::value, T>
 get_hashable_data(const T &value) {
   return value;
 }
@@ -375,7 +377,7 @@
 /// This variant is enabled when we must first call hash_value and use the
 /// result as our data.
 template <typename T>
-typename std::enable_if<!is_hashable_data<T>::value, size_t>::type
+std::enable_if_t<!is_hashable_data<T>::value, size_t>
 get_hashable_data(const T &value) {
   using ::wpi::hash_value;
   return hash_value(value);
@@ -449,7 +451,7 @@
 /// are stored in contiguous memory, this routine avoids copying each value
 /// and directly reads from the underlying memory.
 template <typename ValueT>
-typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type
+std::enable_if_t<is_hashable_data<ValueT>::value, hash_code>
 hash_combine_range_impl(ValueT *first, ValueT *last) {
   const uint64_t seed = get_execution_seed();
   const char *s_begin = reinterpret_cast<const char *>(first);
@@ -499,7 +501,7 @@
 /// useful at minimizing the code in the recursive calls to ease the pain
 /// caused by a lack of variadic functions.
 struct hash_combine_recursive_helper {
-  char buffer[64];
+  char buffer[64] = {};
   hash_state state;
   const uint64_t seed;
 
@@ -547,7 +549,7 @@
       // store types smaller than the buffer.
       if (!store_and_advance(buffer_ptr, buffer_end, data,
                              partial_store_size))
-        abort();
+        wpi_unreachable("buffer smaller than stored type");
     }
     return buffer_ptr;
   }
@@ -574,7 +576,7 @@
     // Check whether the entire set of values fit in the buffer. If so, we'll
     // use the optimized short hashing routine and skip state entirely.
     if (length == 0)
-      return static_cast<size_t>(hash_short(buffer, buffer_ptr - buffer, seed));
+      return hash_short(buffer, buffer_ptr - buffer, seed);
 
     // Mix the final buffer, rotating it if we did a partial fill in order to
     // simulate doing a mix of the last 64-bytes. That is how the algorithm
@@ -586,7 +588,7 @@
     state.mix(buffer);
     length += buffer_ptr - buffer;
 
-    return static_cast<size_t>(state.finalize(length));
+    return state.finalize(length);
   }
 };
 
@@ -625,7 +627,7 @@
   const uint64_t seed = get_execution_seed();
   const char *s = reinterpret_cast<const char *>(&value);
   const uint64_t a = fetch32(s);
-  return static_cast<size_t>(hash_16_bytes(seed + (a << 3), fetch32(s + 4)));
+  return hash_16_bytes(seed + (a << 3), fetch32(s + 4));
 }
 
 } // namespace detail
@@ -634,8 +636,7 @@
 // Declared and documented above, but defined here so that any of the hashing
 // infrastructure is available.
 template <typename T>
-typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type
-hash_value(T value) {
+std::enable_if_t<is_integral_or_enum<T>::value, hash_code> hash_value(T value) {
   return ::wpi::hashing::detail::hash_integer_value(
       static_cast<uint64_t>(value));
 }
@@ -654,6 +655,26 @@
   return hash_combine(arg.first, arg.second);
 }
 
+// Implementation details for the hash_value overload for std::tuple<...>(...).
+namespace hashing {
+namespace detail {
+
+template <typename... Ts, std::size_t... Indices>
+hash_code hash_value_tuple_helper(const std::tuple<Ts...> &arg,
+                                  std::index_sequence<Indices...>) {
+  return hash_combine(std::get<Indices>(arg)...);
+}
+
+} // namespace detail
+} // namespace hashing
+
+template <typename... Ts>
+hash_code hash_value(const std::tuple<Ts...> &arg) {
+  // TODO: Use std::apply when LLVM starts using C++17.
+  return ::wpi::hashing::detail::hash_value_tuple_helper(
+      arg, typename std::index_sequence_for<Ts...>());
+}
+
 // Declared and documented above, but defined here so that any of the hashing
 // infrastructure is available.
 template <typename T>
@@ -661,10 +682,12 @@
   return hash_combine_range(arg.begin(), arg.end());
 }
 
-template <typename T>
-hash_code hash_value(const std::basic_string_view<T> &arg) {
-  return hash_combine_range(arg.begin(), arg.end());
-}
+template <> struct DenseMapInfo<hash_code, void> {
+  static inline hash_code getEmptyKey() { return hash_code(-1); }
+  static inline hash_code getTombstoneKey() { return hash_code(-2); }
+  static unsigned getHashValue(hash_code val) { return val; }
+  static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
+};
 
 } // namespace wpi
 
diff --git a/wpiutil/src/main/native/include/wpi/MapVector.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MapVector.h
similarity index 93%
rename from wpiutil/src/main/native/include/wpi/MapVector.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/MapVector.h
index 34e0267..e4706c7 100644
--- a/wpiutil/src/main/native/include/wpi/MapVector.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MapVector.h
@@ -1,17 +1,17 @@
 //===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// This file implements a map that provides insertion order iteration. The
-// interface is purposefully minimal. The key is assumed to be cheap to copy
-// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
-// a std::vector.
-//
+///
+/// \file
+/// This file implements a map that provides insertion order iteration. The
+/// interface is purposefully minimal. The key is assumed to be cheap to copy
+/// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
+/// a std::vector.
+///
 //===----------------------------------------------------------------------===//
 
 #ifndef WPIUTIL_WPI_MAPVECTOR_H
@@ -19,7 +19,6 @@
 
 #include "wpi/DenseMap.h"
 #include "wpi/SmallVector.h"
-#include <algorithm>
 #include <cassert>
 #include <cstddef>
 #include <iterator>
@@ -44,6 +43,7 @@
       "The mapped_type of the specified Map must be an integral type");
 
 public:
+  using key_type = KeyT;
   using value_type = typename VectorType::value_type;
   using size_type = typename VectorType::size_type;
 
@@ -237,4 +237,4 @@
 
 } // end namespace wpi
 
-#endif // LLVM_ADT_MAPVECTOR_H
+#endif // WPIUTIL_WPI_MAPVECTOR_H
diff --git a/wpiutil/src/main/native/include/wpi/MathExtras.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MathExtras.h
similarity index 81%
rename from wpiutil/src/main/native/include/wpi/MathExtras.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/MathExtras.h
index ac88cb9..ea669ee 100644
--- a/wpiutil/src/main/native/include/wpi/MathExtras.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MathExtras.h
@@ -1,9 +1,8 @@
 //===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -15,15 +14,18 @@
 #define WPIUTIL_WPI_MATHEXTRAS_H
 
 #include "wpi/Compiler.h"
-#include <cstdint>
-#include <algorithm>
 #include <cassert>
 #include <climits>
 #include <cmath>
+#include <cstdint>
 #include <cstring>
 #include <limits>
 #include <type_traits>
 
+#ifdef __ANDROID_NDK__
+#include <android/api-level.h>
+#endif
+
 #ifdef _MSC_VER
 // Declare these intrinsics manually rather including intrin.h. It's very
 // expensive, and MathExtras.h is popular.
@@ -37,6 +39,7 @@
 #endif
 
 namespace wpi {
+
 /// The behavior an operation has on an input of 0.
 enum ZeroBehavior {
   /// The returned value is undefined.
@@ -49,14 +52,14 @@
 
 namespace detail {
 template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
-  static std::size_t count(T Val, ZeroBehavior) {
+  static unsigned count(T Val, ZeroBehavior) {
     if (!Val)
       return std::numeric_limits<T>::digits;
     if (Val & 0x1)
       return 0;
 
     // Bisection method.
-    std::size_t ZeroBits = 0;
+    unsigned ZeroBits = 0;
     T Shift = std::numeric_limits<T>::digits >> 1;
     T Mask = (std::numeric_limits<T>::max)() >> Shift;
     while (Shift) {
@@ -71,13 +74,13 @@
   }
 };
 
-#if __GNUC__ >= 4 || defined(_MSC_VER)
+#if defined(__GNUC__) || defined(_MSC_VER)
 template <typename T> struct TrailingZerosCounter<T, 4> {
-  static std::size_t count(T Val, ZeroBehavior ZB) {
+  static unsigned count(T Val, ZeroBehavior ZB) {
     if (ZB != ZB_Undefined && Val == 0)
       return 32;
 
-#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0)
+#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
     return __builtin_ctz(Val);
 #elif defined(_MSC_VER)
     unsigned long Index;
@@ -89,11 +92,11 @@
 
 #if !defined(_MSC_VER) || defined(_M_X64)
 template <typename T> struct TrailingZerosCounter<T, 8> {
-  static std::size_t count(T Val, ZeroBehavior ZB) {
+  static unsigned count(T Val, ZeroBehavior ZB) {
     if (ZB != ZB_Undefined && Val == 0)
       return 64;
 
-#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0)
+#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
     return __builtin_ctzll(Val);
 #elif defined(_MSC_VER)
     unsigned long Index;
@@ -114,7 +117,7 @@
 /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
 ///   valid arguments.
 template <typename T>
-std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+unsigned countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
   static_assert(std::numeric_limits<T>::is_integer &&
                     !std::numeric_limits<T>::is_signed,
                 "Only unsigned integral types are allowed.");
@@ -123,12 +126,12 @@
 
 namespace detail {
 template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
-  static std::size_t count(T Val, ZeroBehavior) {
+  static unsigned count(T Val, ZeroBehavior) {
     if (!Val)
       return std::numeric_limits<T>::digits;
 
     // Bisection method.
-    std::size_t ZeroBits = 0;
+    unsigned ZeroBits = 0;
     for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
       T Tmp = Val >> Shift;
       if (Tmp)
@@ -140,13 +143,13 @@
   }
 };
 
-#if __GNUC__ >= 4 || defined(_MSC_VER)
+#if defined(__GNUC__) || defined(_MSC_VER)
 template <typename T> struct LeadingZerosCounter<T, 4> {
-  static std::size_t count(T Val, ZeroBehavior ZB) {
+  static unsigned count(T Val, ZeroBehavior ZB) {
     if (ZB != ZB_Undefined && Val == 0)
       return 32;
 
-#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0)
+#if __has_builtin(__builtin_clz) || defined(__GNUC__)
     return __builtin_clz(Val);
 #elif defined(_MSC_VER)
     unsigned long Index;
@@ -158,11 +161,11 @@
 
 #if !defined(_MSC_VER) || defined(_M_X64)
 template <typename T> struct LeadingZerosCounter<T, 8> {
-  static std::size_t count(T Val, ZeroBehavior ZB) {
+  static unsigned count(T Val, ZeroBehavior ZB) {
     if (ZB != ZB_Undefined && Val == 0)
       return 64;
 
-#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0)
+#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
     return __builtin_clzll(Val);
 #elif defined(_MSC_VER)
     unsigned long Index;
@@ -183,7 +186,7 @@
 /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
 ///   valid arguments.
 template <typename T>
-std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+unsigned countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
   static_assert(std::numeric_limits<T>::is_integer &&
                     !std::numeric_limits<T>::is_signed,
                 "Only unsigned integral types are allowed.");
@@ -273,6 +276,34 @@
   return Val;
 }
 
+#if __has_builtin(__builtin_bitreverse8)
+template<>
+inline uint8_t reverseBits<uint8_t>(uint8_t Val) {
+  return __builtin_bitreverse8(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse16)
+template<>
+inline uint16_t reverseBits<uint16_t>(uint16_t Val) {
+  return __builtin_bitreverse16(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse32)
+template<>
+inline uint32_t reverseBits<uint32_t>(uint32_t Val) {
+  return __builtin_bitreverse32(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse64)
+template<>
+inline uint64_t reverseBits<uint64_t>(uint64_t Val) {
+  return __builtin_bitreverse64(Val);
+}
+#endif
+
 // NOTE: The following support functions use the _32/_64 extensions instead of
 // type overloading so that signed and unsigned integers can be used without
 // ambiguity.
@@ -325,14 +356,12 @@
 /// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting
 /// left too many places.
 template <unsigned N>
-constexpr inline typename std::enable_if<(N < 64), bool>::type
-isUInt(uint64_t X) {
+constexpr inline std::enable_if_t<(N < 64), bool> isUInt(uint64_t X) {
   static_assert(N > 0, "isUInt<0> doesn't make sense");
   return X < (UINT64_C(1) << (N));
 }
 template <unsigned N>
-constexpr inline typename std::enable_if<N >= 64, bool>::type
-isUInt(uint64_t X) {
+constexpr inline std::enable_if_t<N >= 64, bool> isUInt(uint64_t) {
   return true;
 }
 
@@ -379,7 +408,7 @@
 inline int64_t minIntN(int64_t N) {
   assert(N > 0 && N <= 64 && "integer width out of range");
 
-  return -(UINT64_C(1)<<(N-1));
+  return UINT64_C(1) + ~(UINT64_C(1) << (N - 1));
 }
 
 #ifdef _WIN32
@@ -450,7 +479,7 @@
 /// \param ZB the behavior on an input of all ones. Only ZB_Width and
 /// ZB_Undefined are valid arguments.
 template <typename T>
-std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+unsigned countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
   static_assert(std::numeric_limits<T>::is_integer &&
                     !std::numeric_limits<T>::is_signed,
                 "Only unsigned integral types are allowed.");
@@ -466,7 +495,7 @@
 /// \param ZB the behavior on an input of all ones. Only ZB_Width and
 /// ZB_Undefined are valid arguments.
 template <typename T>
-std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+unsigned countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
   static_assert(std::numeric_limits<T>::is_integer &&
                     !std::numeric_limits<T>::is_signed,
                 "Only unsigned integral types are allowed.");
@@ -478,7 +507,7 @@
   static unsigned count(T Value) {
     // Generic version, forward to 32 bits.
     static_assert(SizeOfT <= 4, "Not implemented!");
-#if __GNUC__ >= 4
+#if defined(__GNUC__)
     return __builtin_popcount(Value);
 #else
     uint32_t v = Value;
@@ -491,7 +520,7 @@
 
 template <typename T> struct PopulationCounter<T, 8> {
   static unsigned count(T Value) {
-#if __GNUC__ >= 4
+#if defined(__GNUC__)
     return __builtin_popcountll(Value);
 #else
     uint64_t v = Value;
@@ -515,6 +544,16 @@
   return detail::PopulationCounter<T, sizeof(T)>::count(Value);
 }
 
+/// Compile time Log2.
+/// Valid only for positive powers of two.
+template <size_t kValue> constexpr inline size_t CTLog2() {
+  static_assert(kValue > 0 && wpi::isPowerOf2_64(kValue),
+                "Value is not a valid power of 2");
+  return 1 + CTLog2<kValue / 2>();
+}
+
+template <> constexpr inline size_t CTLog2<1>() { return 0; }
+
 /// Return the log base 2 of the specified value.
 inline double Log2(double Value) {
 #if defined(__ANDROID_API__) && __ANDROID_API__ < 18
@@ -551,15 +590,20 @@
 }
 
 /// Return the greatest common divisor of the values using Euclid's algorithm.
-inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
+template <typename T>
+inline T greatestCommonDivisor(T A, T B) {
   while (B) {
-    uint64_t T = B;
+    T Tmp = B;
     B = A % B;
-    A = T;
+    A = Tmp;
   }
   return A;
 }
 
+inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
+  return greatestCommonDivisor<uint64_t>(A, B);
+}
+
 /// This function takes a 64-bit integer and returns the bit equivalent double.
 inline double BitsToDouble(uint64_t Bits) {
   double D;
@@ -607,25 +651,6 @@
   return (A | B) & (1 + ~(A | B));
 }
 
-/// Aligns \c Addr to \c Alignment bytes, rounding up.
-///
-/// Alignment should be a power of two.  This method rounds up, so
-/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8.
-inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
-  assert(Alignment && isPowerOf2_64((uint64_t)Alignment) &&
-         "Alignment is not a power of two!");
-
-  assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr);
-
-  return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1));
-}
-
-/// Returns the necessary adjustment for aligning \c Ptr to \c Alignment
-/// bytes, rounding up.
-inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
-  return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
-}
-
 /// Returns the next power of two (in 64-bits) that is strictly greater than A.
 /// Returns zero on overflow.
 inline uint64_t NextPowerOf2(uint64_t A) {
@@ -691,18 +716,10 @@
   return alignTo(Numerator, Denominator) / Denominator;
 }
 
-/// \c alignTo for contexts where a constant expression is required.
-/// \sa alignTo
-///
-/// \todo FIXME: remove when \c constexpr becomes really \c constexpr
-template <uint64_t Align>
-struct AlignTo {
-  static_assert(Align != 0u, "Align must be non-zero");
-  template <uint64_t Value>
-  struct from_value {
-    static const uint64_t value = (Value + Align - 1) / Align * Align;
-  };
-};
+/// Returns the integer nearest(Numerator / Denominator).
+inline uint64_t divideNearest(uint64_t Numerator, uint64_t Denominator) {
+  return (Numerator + (Denominator / 2)) / Denominator;
+}
 
 /// Returns the largest uint64_t less than or equal to \p Value and is
 /// \p Skew mod \p Align. \p Align must be non-zero
@@ -712,13 +729,6 @@
   return (Value - Skew) / Align * Align + Skew;
 }
 
-/// Returns the offset to the next integer (mod 2**64) that is greater than
-/// or equal to \p Value and is a multiple of \p Align. \p Align must be
-/// non-zero.
-inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) {
-  return alignTo(Value, Align) - Value;
-}
-
 /// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
 /// Requires 0 < B <= 32.
 template <unsigned B> constexpr inline int32_t SignExtend32(uint32_t X) {
@@ -728,7 +738,7 @@
 }
 
 /// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
-/// Requires 0 < B < 32.
+/// Requires 0 < B <= 32.
 inline int32_t SignExtend32(uint32_t X, unsigned B) {
   assert(B > 0 && "Bit width can't be 0.");
   assert(B <= 32 && "Bit width out of range.");
@@ -736,7 +746,7 @@
 }
 
 /// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
-/// Requires 0 < B < 64.
+/// Requires 0 < B <= 64.
 template <unsigned B> constexpr inline int64_t SignExtend64(uint64_t x) {
   static_assert(B > 0, "Bit width can't be 0.");
   static_assert(B <= 64, "Bit width out of range.");
@@ -744,7 +754,7 @@
 }
 
 /// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
-/// Requires 0 < B < 64.
+/// Requires 0 < B <= 64.
 inline int64_t SignExtend64(uint64_t X, unsigned B) {
   assert(B > 0 && "Bit width can't be 0.");
   assert(B <= 64 && "Bit width out of range.");
@@ -754,16 +764,15 @@
 /// Subtract two unsigned integers, X and Y, of type T and return the absolute
 /// value of the result.
 template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
-AbsoluteDifference(T X, T Y) {
-  return (std::max)(X, Y) - (std::min)(X, Y);
+std::enable_if_t<std::is_unsigned<T>::value, T> AbsoluteDifference(T X, T Y) {
+  return X > Y ? (X - Y) : (Y - X);
 }
 
 /// Add two unsigned integers, X and Y, of type T.  Clamp the result to the
 /// maximum representable value of T on overflow.  ResultOverflowed indicates if
 /// the result is larger than the maximum representable value of type T.
 template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
 SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
   bool Dummy;
   bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -780,7 +789,7 @@
 /// maximum representable value of T on overflow.  ResultOverflowed indicates if
 /// the result is larger than the maximum representable value of type T.
 template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
 SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
   bool Dummy;
   bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -826,7 +835,7 @@
 /// overflow. ResultOverflowed indicates if the result is larger than the
 /// maximum representable value of type T.
 template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
 SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
   bool Dummy;
   bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -838,6 +847,89 @@
   return SaturatingAdd(A, Product, &Overflowed);
 }
 
+/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
+extern const float huge_valf;
+
+
+/// Add two signed integers, computing the two's complement truncated result,
+/// returning true if overflow occured.
+template <typename T>
+std::enable_if_t<std::is_signed<T>::value, T> AddOverflow(T X, T Y, T &Result) {
+#if __has_builtin(__builtin_add_overflow)
+  return __builtin_add_overflow(X, Y, &Result);
+#else
+  // Perform the unsigned addition.
+  using U = std::make_unsigned_t<T>;
+  const U UX = static_cast<U>(X);
+  const U UY = static_cast<U>(Y);
+  const U UResult = UX + UY;
+
+  // Convert to signed.
+  Result = static_cast<T>(UResult);
+
+  // Adding two positive numbers should result in a positive number.
+  if (X > 0 && Y > 0)
+    return Result <= 0;
+  // Adding two negatives should result in a negative number.
+  if (X < 0 && Y < 0)
+    return Result >= 0;
+  return false;
+#endif
+}
+
+/// Subtract two signed integers, computing the two's complement truncated
+/// result, returning true if an overflow ocurred.
+template <typename T>
+std::enable_if_t<std::is_signed<T>::value, T> SubOverflow(T X, T Y, T &Result) {
+#if __has_builtin(__builtin_sub_overflow)
+  return __builtin_sub_overflow(X, Y, &Result);
+#else
+  // Perform the unsigned addition.
+  using U = std::make_unsigned_t<T>;
+  const U UX = static_cast<U>(X);
+  const U UY = static_cast<U>(Y);
+  const U UResult = UX - UY;
+
+  // Convert to signed.
+  Result = static_cast<T>(UResult);
+
+  // Subtracting a positive number from a negative results in a negative number.
+  if (X <= 0 && Y > 0)
+    return Result >= 0;
+  // Subtracting a negative number from a positive results in a positive number.
+  if (X >= 0 && Y < 0)
+    return Result <= 0;
+  return false;
+#endif
+}
+
+/// Multiply two signed integers, computing the two's complement truncated
+/// result, returning true if an overflow ocurred.
+template <typename T>
+std::enable_if_t<std::is_signed<T>::value, T> MulOverflow(T X, T Y, T &Result) {
+  // Perform the unsigned multiplication on absolute values.
+  using U = std::make_unsigned_t<T>;
+  const U UX = X < 0 ? (0 - static_cast<U>(X)) : static_cast<U>(X);
+  const U UY = Y < 0 ? (0 - static_cast<U>(Y)) : static_cast<U>(Y);
+  const U UResult = UX * UY;
+
+  // Convert to signed.
+  const bool IsNegative = (X < 0) ^ (Y < 0);
+  Result = IsNegative ? (0 - UResult) : UResult;
+
+  // If any of the args was 0, result is 0 and no overflow occurs.
+  if (UX == 0 || UY == 0)
+    return false;
+
+  // UX and UY are in [1, 2^n], where n is the number of digits.
+  // Check how the max allowed absolute value (2^n for negative, 2^(n-1) for
+  // positive) divided by an argument compares to the other.
+  if (IsNegative)
+    return UX > (static_cast<U>((std::numeric_limits<T>::max)()) + U(1)) / UY;
+  else
+    return UX > (static_cast<U>((std::numeric_limits<T>::max)())) / UY;
+}
+
 // Typesafe implementation of the signum function.
 // Returns -1 if negative, 1 if positive, 0 if 0.
 template <typename T>
@@ -858,7 +950,6 @@
 constexpr T Lerp(const T& startValue, const T& endValue, double t) {
   return startValue + (endValue - startValue) * t;
 }
-
-} // namespace wpi
+} // End wpi namespace
 
 #endif
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MemAlloc.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MemAlloc.h
new file mode 100644
index 0000000..32909ff
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MemAlloc.h
@@ -0,0 +1,100 @@
+//===- MemAlloc.h - Memory allocation functions -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines counterparts of C library allocation functions defined in
+/// the namespace 'std'. The new allocation functions crash on allocation
+/// failure instead of returning null pointer.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_MEMALLOC_H
+#define WPIUTIL_WPI_MEMALLOC_H
+
+#include "wpi/Compiler.h"
+#include "wpi/ErrorHandling.h"
+#include <cstdlib>
+
+namespace wpi {
+
+#ifdef _WIN32
+#pragma warning(push)
+// Warning on NONNULL, report is not known to abort
+#pragma warning(disable : 6387)
+#pragma warning(disable : 28196)
+#pragma warning(disable : 28183)
+#endif
+
+LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_malloc(size_t Sz) {
+  void *Result = std::malloc(Sz);
+  if (Result == nullptr) {
+    // It is implementation-defined whether allocation occurs if the space
+    // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+    // non-zero, if the space requested was zero.
+    if (Sz == 0)
+      return safe_malloc(1);
+    report_bad_alloc_error("Allocation failed");
+  }
+  return Result;
+}
+
+LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_calloc(size_t Count,
+                                                        size_t Sz) {
+  void *Result = std::calloc(Count, Sz);
+  if (Result == nullptr) {
+    // It is implementation-defined whether allocation occurs if the space
+    // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+    // non-zero, if the space requested was zero.
+    if (Count == 0 || Sz == 0)
+      return safe_malloc(1);
+    report_bad_alloc_error("Allocation failed");
+  }
+  return Result;
+}
+
+LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
+  void *Result = std::realloc(Ptr, Sz);
+  if (Result == nullptr) {
+    // It is implementation-defined whether allocation occurs if the space
+    // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+    // non-zero, if the space requested was zero.
+    if (Sz == 0)
+      return safe_malloc(1);
+    report_bad_alloc_error("Allocation failed");
+  }
+  return Result;
+}
+
+/// Allocate a buffer of memory with the given size and alignment.
+///
+/// When the compiler supports aligned operator new, this will use it to to
+/// handle even over-aligned allocations.
+///
+/// However, this doesn't make any attempt to leverage the fancier techniques
+/// like posix_memalign due to portability. It is mostly intended to allow
+/// compatibility with platforms that, after aligned allocation was added, use
+/// reduced default alignment.
+LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+allocate_buffer(size_t Size, size_t Alignment);
+
+/// Deallocate a buffer of memory with the given size and alignment.
+///
+/// If supported, this will used the sized delete operator. Also if supported,
+/// this will pass the alignment to the delete operator.
+///
+/// The pointer must have been allocated with the corresponding new operator,
+/// most likely using the above helper.
+void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment);
+
+} // namespace wpi
+
+#ifdef _WIN32
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MemoryBuffer.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MemoryBuffer.h
new file mode 100644
index 0000000..7907c07
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/MemoryBuffer.h
@@ -0,0 +1,239 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the MemoryBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <stdint.h>
+
+#include <cstddef>
+#include <memory>
+#include <span>
+#include <string_view>
+#include <system_error>
+
+// Duplicated from fs.h to avoid a dependency
+namespace fs {
+#if defined(_WIN32)
+// A Win32 HANDLE is a typedef of void*
+using file_t = void*;
+#else
+using file_t = int;
+#endif
+}  // namespace fs
+
+namespace wpi {
+
+class MemoryBufferRef;
+
+/// This interface provides simple read-only access to a block of memory, and
+/// provides simple methods for reading files and standard input into a memory
+/// buffer.
+class MemoryBuffer {
+  const uint8_t* m_bufferStart;  // Start of the buffer.
+  const uint8_t* m_bufferEnd;    // End of the buffer.
+
+ protected:
+  MemoryBuffer() = default;
+
+  void Init(const uint8_t* bufStart, const uint8_t* bufEnd);
+
+ public:
+  MemoryBuffer(const MemoryBuffer&) = delete;
+  MemoryBuffer& operator=(const MemoryBuffer&) = delete;
+  virtual ~MemoryBuffer();
+
+  const uint8_t* begin() const { return m_bufferStart; }
+  const uint8_t* end() const { return m_bufferEnd; }
+  size_t size() const { return m_bufferEnd - m_bufferStart; }
+
+  std::span<const uint8_t> GetBuffer() const { return {begin(), end()}; }
+
+  /// Return an identifier for this buffer, typically the filename it was read
+  /// from.
+  virtual std::string_view GetBufferIdentifier() const {
+    return "Unknown buffer";
+  }
+
+  /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer
+  /// if successful, otherwise returning null. If FileSize is specified, this
+  /// means that the client knows that the file exists and that it has the
+  /// specified size.
+  static std::unique_ptr<MemoryBuffer> GetFile(std::string_view filename,
+                                               std::error_code& ec,
+                                               int64_t fileSize = -1);
+
+  /// Read all of the specified file into a MemoryBuffer as a stream
+  /// (i.e. until EOF reached). This is useful for special files that
+  /// look like a regular file but have 0 size (e.g. /proc/cpuinfo on Linux).
+  static std::unique_ptr<MemoryBuffer> GetFileAsStream(
+      std::string_view filename, std::error_code& ec);
+
+  /// Given an already-open file descriptor, map some slice of it into a
+  /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
+  static std::unique_ptr<MemoryBuffer> GetOpenFileSlice(
+      fs::file_t f, std::string_view filename, std::error_code& ec,
+      uint64_t mapSize, int64_t offset);
+
+  /// Given an already-open file descriptor, read the file and return a
+  /// MemoryBuffer.
+  static std::unique_ptr<MemoryBuffer> GetOpenFile(fs::file_t f,
+                                                   std::string_view filename,
+                                                   std::error_code& ec,
+                                                   uint64_t fileSize);
+
+  /// Open the specified memory range as a MemoryBuffer.
+  static std::unique_ptr<MemoryBuffer> GetMemBuffer(
+      std::span<const uint8_t> inputData, std::string_view bufferName = "");
+
+  static std::unique_ptr<MemoryBuffer> GetMemBuffer(MemoryBufferRef ref);
+
+  /// Open the specified memory range as a MemoryBuffer, copying the contents
+  /// and taking ownership of it.
+  static std::unique_ptr<MemoryBuffer> GetMemBufferCopy(
+      std::span<const uint8_t> inputData, std::string_view bufferName = "");
+
+  /// Map a subrange of the specified file as a MemoryBuffer.
+  static std::unique_ptr<MemoryBuffer> GetFileSlice(std::string_view filename,
+                                                    std::error_code& ec,
+                                                    uint64_t mapSize,
+                                                    uint64_t offset);
+
+  //===--------------------------------------------------------------------===//
+  // Provided for performance analysis.
+  //===--------------------------------------------------------------------===//
+
+  /// The kind of memory backing used to support the MemoryBuffer.
+  enum BufferKind { MemoryBuffer_Malloc, MemoryBuffer_MMap };
+
+  /// Return information on the memory mechanism used to support the
+  /// MemoryBuffer.
+  virtual BufferKind GetBufferKind() const = 0;
+
+  MemoryBufferRef GetMemBufferRef() const;
+};
+
+/// This class is an extension of MemoryBuffer, which allows copy-on-write
+/// access to the underlying contents.  It only supports creation methods that
+/// are guaranteed to produce a writable buffer.  For example, mapping a file
+/// read-only is not supported.
+class WritableMemoryBuffer : public MemoryBuffer {
+ protected:
+  WritableMemoryBuffer() = default;
+
+ public:
+  using MemoryBuffer::begin;
+  using MemoryBuffer::end;
+  using MemoryBuffer::GetBuffer;
+  using MemoryBuffer::size;
+
+  // const_cast is well-defined here, because the underlying buffer is
+  // guaranteed to have been initialized with a mutable buffer.
+  uint8_t* begin() { return const_cast<uint8_t*>(MemoryBuffer::begin()); }
+  uint8_t* end() { return const_cast<uint8_t*>(MemoryBuffer::end()); }
+  std::span<uint8_t> GetBuffer() { return {begin(), end()}; }
+
+  static std::unique_ptr<WritableMemoryBuffer> GetFile(
+      std::string_view filename, std::error_code& ec, int64_t fileSize = -1);
+
+  /// Map a subrange of the specified file as a WritableMemoryBuffer.
+  static std::unique_ptr<WritableMemoryBuffer> GetFileSlice(
+      std::string_view filename, std::error_code& ec, uint64_t mapSize,
+      uint64_t offset);
+
+  /// Allocate a new MemoryBuffer of the specified size that is not initialized.
+  /// Note that the caller should initialize the memory allocated by this
+  /// method. The memory is owned by the MemoryBuffer object.
+  static std::unique_ptr<WritableMemoryBuffer> GetNewUninitMemBuffer(
+      size_t size, std::string_view bufferName = "");
+
+  /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note
+  /// that the caller need not initialize the memory allocated by this method.
+  /// The memory is owned by the MemoryBuffer object.
+  static std::unique_ptr<WritableMemoryBuffer> GetNewMemBuffer(
+      size_t size, std::string_view bufferName = "");
+
+ private:
+  // Hide these base class factory function so one can't write
+  //   WritableMemoryBuffer::getXXX()
+  // and be surprised that they got a read-only Buffer.
+  using MemoryBuffer::GetFileAsStream;
+  using MemoryBuffer::GetMemBuffer;
+  using MemoryBuffer::GetMemBufferCopy;
+  using MemoryBuffer::GetOpenFile;
+  using MemoryBuffer::GetOpenFileSlice;
+};
+
+/// This class is an extension of MemoryBuffer, which allows write access to
+/// the underlying contents and committing those changes to the original source.
+/// It only supports creation methods that are guaranteed to produce a writable
+/// buffer.  For example, mapping a file read-only is not supported.
+class WriteThroughMemoryBuffer : public MemoryBuffer {
+ protected:
+  WriteThroughMemoryBuffer() = default;
+
+ public:
+  using MemoryBuffer::begin;
+  using MemoryBuffer::end;
+  using MemoryBuffer::GetBuffer;
+  using MemoryBuffer::size;
+
+  // const_cast is well-defined here, because the underlying buffer is
+  // guaranteed to have been initialized with a mutable buffer.
+  uint8_t* begin() { return const_cast<uint8_t*>(MemoryBuffer::begin()); }
+  uint8_t* end() { return const_cast<uint8_t*>(MemoryBuffer::end()); }
+  std::span<uint8_t> GetBuffer() { return {begin(), end()}; }
+
+  static std::unique_ptr<WriteThroughMemoryBuffer> GetFile(
+      std::string_view filename, std::error_code& ec, int64_t fileSize = -1);
+
+  /// Map a subrange of the specified file as a ReadWriteMemoryBuffer.
+  static std::unique_ptr<WriteThroughMemoryBuffer> GetFileSlice(
+      std::string_view filename, std::error_code& ec, uint64_t mapSize,
+      uint64_t offset);
+
+ private:
+  // Hide these base class factory function so one can't write
+  //   WritableMemoryBuffer::getXXX()
+  // and be surprised that they got a read-only Buffer.
+  using MemoryBuffer::GetFileAsStream;
+  using MemoryBuffer::GetMemBuffer;
+  using MemoryBuffer::GetMemBufferCopy;
+  using MemoryBuffer::GetOpenFile;
+  using MemoryBuffer::GetOpenFileSlice;
+};
+
+class MemoryBufferRef {
+  std::span<const uint8_t> m_buffer;
+  std::string_view m_id;
+
+ public:
+  MemoryBufferRef() = default;
+  MemoryBufferRef(MemoryBuffer& buffer)  // NOLINT
+      : m_buffer(buffer.GetBuffer()), m_id(buffer.GetBufferIdentifier()) {}
+  MemoryBufferRef(std::span<const uint8_t> buffer, std::string_view id)
+      : m_buffer(buffer), m_id(id) {}
+
+  std::span<const uint8_t> GetBuffer() const { return m_buffer; }
+
+  std::string_view GetBufferIdentifier() const { return m_id; }
+
+  const uint8_t* begin() const { return &*m_buffer.begin(); }
+  const uint8_t* end() const { return &*m_buffer.end(); }
+  size_t size() const { return m_buffer.size(); }
+};
+
+}  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/PointerIntPair.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerIntPair.h
similarity index 88%
rename from wpiutil/src/main/native/include/wpi/PointerIntPair.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerIntPair.h
index e6a1212..34ff4e1 100644
--- a/wpiutil/src/main/native/include/wpi/PointerIntPair.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerIntPair.h
@@ -1,27 +1,29 @@
 //===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// This file defines the PointerIntPair class.
-//
+///
+/// \file
+/// This file defines the PointerIntPair class.
+///
 //===----------------------------------------------------------------------===//
 
 #ifndef WPIUTIL_WPI_POINTERINTPAIR_H
 #define WPIUTIL_WPI_POINTERINTPAIR_H
 
+#include "wpi/Compiler.h"
 #include "wpi/PointerLikeTypeTraits.h"
+#include "wpi/type_traits.h"
 #include <cassert>
 #include <cstdint>
 #include <limits>
 
 namespace wpi {
 
-template <typename T> struct DenseMapInfo;
+template <typename T, typename Enable> struct DenseMapInfo;
 template <typename PointerT, unsigned IntBits, typename PtrTraits>
 struct PointerIntPairInfo;
 
@@ -59,19 +61,19 @@
 
   IntType getInt() const { return (IntType)Info::getInt(Value); }
 
-  void setPointer(PointerTy PtrVal) {
+  void setPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION {
     Value = Info::updatePointer(Value, PtrVal);
   }
 
-  void setInt(IntType IntVal) {
+  void setInt(IntType IntVal) LLVM_LVALUE_FUNCTION {
     Value = Info::updateInt(Value, static_cast<intptr_t>(IntVal));
   }
 
-  void initWithPointer(PointerTy PtrVal) {
+  void initWithPointer(PointerTy PtrVal) LLVM_LVALUE_FUNCTION {
     Value = Info::updatePointer(0, PtrVal);
   }
 
-  void setPointerAndInt(PointerTy PtrVal, IntType IntVal) {
+  void setPointerAndInt(PointerTy PtrVal, IntType IntVal) LLVM_LVALUE_FUNCTION {
     Value = Info::updateInt(Info::updatePointer(0, PtrVal),
                             static_cast<intptr_t>(IntVal));
   }
@@ -89,7 +91,7 @@
 
   void *getOpaqueValue() const { return reinterpret_cast<void *>(Value); }
 
-  void setFromOpaqueValue(void *Val) {
+  void setFromOpaqueValue(void *Val) LLVM_LVALUE_FUNCTION {
     Value = reinterpret_cast<intptr_t>(Val);
   }
 
@@ -126,6 +128,7 @@
   }
 };
 
+
 template <typename PointerT, unsigned IntBits, typename PtrTraits>
 struct PointerIntPairInfo {
   static_assert(PtrTraits::NumLowBitsAvailable <
@@ -133,7 +136,7 @@
                 "cannot use a pointer type that has all bits free");
   static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,
                 "PointerIntPair with integer size too large for pointer");
-  enum : uintptr_t {
+  enum MaskAndShiftConstants : uintptr_t {
     /// PointerBitMask - The bits that come from the pointer.
     PointerBitMask =
         ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable) - 1),
@@ -176,15 +179,9 @@
   }
 };
 
-template <typename T> struct isPodLike;
-template <typename PointerTy, unsigned IntBits, typename IntType>
-struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType>> {
-  static const bool value = true;
-};
-
 // Provide specialization of DenseMapInfo for PointerIntPair.
 template <typename PointerTy, unsigned IntBits, typename IntType>
-struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>> {
+struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>, void> {
   using Ty = PointerIntPair<PointerTy, IntBits, IntType>;
 
   static Ty getEmptyKey() {
@@ -227,7 +224,8 @@
     return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
   }
 
-  enum { NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits };
+  static constexpr int NumLowBitsAvailable =
+      PtrTraits::NumLowBitsAvailable - IntBits;
 };
 
 } // end namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/PointerLikeTypeTraits.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerLikeTypeTraits.h
similarity index 86%
rename from wpiutil/src/main/native/include/wpi/PointerLikeTypeTraits.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerLikeTypeTraits.h
index fa136e0..ffca61a 100644
--- a/wpiutil/src/main/native/include/wpi/PointerLikeTypeTraits.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerLikeTypeTraits.h
@@ -1,9 +1,8 @@
 //===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -15,8 +14,8 @@
 #ifndef WPIUTIL_WPI_POINTERLIKETYPETRAITS_H
 #define WPIUTIL_WPI_POINTERLIKETYPETRAITS_H
 
+#include <cassert>
 #include <cstdint>
-#include <cstdlib>
 #include <type_traits>
 
 namespace wpi {
@@ -38,8 +37,9 @@
 };
 
 // sizeof(T) is valid only for a complete T.
-template <typename T> struct HasPointerLikeTypeTraits<
-  T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
+template <typename T>
+struct HasPointerLikeTypeTraits<
+    T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
   static const bool value = true;
 };
 
@@ -57,7 +57,8 @@
   static inline void *getAsVoidPointer(T *P) { return P; }
   static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
 
-  enum { NumLowBitsAvailable = detail::ConstantLog2<alignof(T)>::value };
+  static constexpr int NumLowBitsAvailable =
+      detail::ConstantLog2<alignof(T)>::value;
 };
 
 template <> struct PointerLikeTypeTraits<void *> {
@@ -71,7 +72,7 @@
   ///
   /// All clients should use assertions to do a run-time check to ensure that
   /// this is actually true.
-  enum { NumLowBitsAvailable = 2 };
+  static constexpr int NumLowBitsAvailable = 2;
 };
 
 // Provide PointerLikeTypeTraits for const things.
@@ -84,7 +85,7 @@
   static inline const T getFromVoidPointer(const void *P) {
     return NonConst::getFromVoidPointer(const_cast<void *>(P));
   }
-  enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+  static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
 };
 
 // Provide PointerLikeTypeTraits for const pointers.
@@ -97,7 +98,7 @@
   static inline const T *getFromVoidPointer(const void *P) {
     return NonConst::getFromVoidPointer(const_cast<void *>(P));
   }
-  enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+  static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
 };
 
 // Provide PointerLikeTypeTraits for uintptr_t.
@@ -109,7 +110,7 @@
     return reinterpret_cast<uintptr_t>(P);
   }
   // No bits are available!
-  enum { NumLowBitsAvailable = 0 };
+  static constexpr int NumLowBitsAvailable = 0;
 };
 
 /// Provide suitable custom traits struct for function pointers.
@@ -122,7 +123,8 @@
 /// potentially use alignment attributes on functions to satisfy that.
 template <int Alignment, typename FunctionPointerT>
 struct FunctionPointerLikeTypeTraits {
-  enum { NumLowBitsAvailable = detail::ConstantLog2<Alignment>::value };
+  static constexpr int NumLowBitsAvailable =
+      detail::ConstantLog2<Alignment>::value;
   static inline void *getAsVoidPointer(FunctionPointerT P) {
     assert((reinterpret_cast<uintptr_t>(P) &
             ~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 &&
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerUnion.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerUnion.h
new file mode 100644
index 0000000..cc12bbc
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/PointerUnion.h
@@ -0,0 +1,295 @@
+//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines the PointerUnion class, which is a discriminated union of
+/// pointer types.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_POINTERUNION_H
+#define WPIUTIL_WPI_POINTERUNION_H
+
+#include "wpi/DenseMapInfo.h"
+#include "wpi/PointerIntPair.h"
+#include "wpi/PointerLikeTypeTraits.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+namespace wpi {
+
+namespace detail {
+template <typename T, typename... Us> struct TypesAreDistinct;
+template <typename T, typename... Us>
+struct TypesAreDistinct
+    : std::integral_constant<bool, !std::disjunction_v<std::is_same<T, Us>...> &&
+                                       TypesAreDistinct<Us...>::value> {};
+template <typename T> struct TypesAreDistinct<T> : std::true_type {};
+} // namespace detail
+
+/// Determine if all types in Ts are distinct.
+///
+/// Useful to statically assert when Ts is intended to describe a non-multi set
+/// of types.
+///
+/// Expensive (currently quadratic in sizeof(Ts...)), and so should only be
+/// asserted once per instantiation of a type which requires it.
+template <typename... Ts> struct TypesAreDistinct;
+template <> struct TypesAreDistinct<> : std::true_type {};
+template <typename... Ts>
+struct TypesAreDistinct
+    : std::integral_constant<bool, detail::TypesAreDistinct<Ts...>::value> {};
+
+/// Find the first index where a type appears in a list of types.
+///
+/// FirstIndexOfType<T, Us...>::value is the first index of T in Us.
+///
+/// Typically only meaningful when it is otherwise statically known that the
+/// type pack has no duplicate types. This should be guaranteed explicitly with
+/// static_assert(TypesAreDistinct<Us...>::value).
+///
+/// It is a compile-time error to instantiate when T is not present in Us, i.e.
+/// if is_one_of<T, Us...>::value is false.
+template <typename T, typename... Us> struct FirstIndexOfType;
+template <typename T, typename U, typename... Us>
+struct FirstIndexOfType<T, U, Us...>
+    : std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {};
+template <typename T, typename... Us>
+struct FirstIndexOfType<T, T, Us...> : std::integral_constant<size_t, 0> {};
+
+/// Find the type at a given index in a list of types.
+///
+/// TypeAtIndex<I, Ts...> is the type at index I in Ts.
+template <size_t I, typename... Ts>
+using TypeAtIndex = std::tuple_element_t<I, std::tuple<Ts...>>;
+
+namespace pointer_union_detail {
+  /// Determine the number of bits required to store integers with values < n.
+  /// This is ceil(log2(n)).
+  constexpr int bitsRequired(unsigned n) {
+    return n > 1 ? 1 + bitsRequired((n + 1) / 2) : 0;
+  }
+
+  template <typename... Ts> constexpr int lowBitsAvailable() {
+    return std::min<int>({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...});
+  }
+
+  /// Find the first type in a list of types.
+  template <typename T, typename...> struct GetFirstType {
+    using type = T;
+  };
+
+  /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
+  /// for the template arguments.
+  template <typename ...PTs> class PointerUnionUIntTraits {
+  public:
+    static inline void *getAsVoidPointer(void *P) { return P; }
+    static inline void *getFromVoidPointer(void *P) { return P; }
+    static constexpr int NumLowBitsAvailable = lowBitsAvailable<PTs...>();
+  };
+
+  template <typename Derived, typename ValTy, int I, typename ...Types>
+  class PointerUnionMembers;
+
+  template <typename Derived, typename ValTy, int I>
+  class PointerUnionMembers<Derived, ValTy, I> {
+  protected:
+    ValTy Val;
+    PointerUnionMembers() = default;
+    PointerUnionMembers(ValTy Val) : Val(Val) {}
+
+    friend struct PointerLikeTypeTraits<Derived>;
+  };
+
+  template <typename Derived, typename ValTy, int I, typename Type,
+            typename ...Types>
+  class PointerUnionMembers<Derived, ValTy, I, Type, Types...>
+      : public PointerUnionMembers<Derived, ValTy, I + 1, Types...> {
+    using Base = PointerUnionMembers<Derived, ValTy, I + 1, Types...>;
+  public:
+    using Base::Base;
+    PointerUnionMembers() = default;
+    PointerUnionMembers(Type V)
+        : Base(ValTy(const_cast<void *>(
+                         PointerLikeTypeTraits<Type>::getAsVoidPointer(V)),
+                     I)) {}
+
+    using Base::operator=;
+    Derived &operator=(Type V) {
+      this->Val = ValTy(
+          const_cast<void *>(PointerLikeTypeTraits<Type>::getAsVoidPointer(V)),
+          I);
+      return static_cast<Derived &>(*this);
+    };
+  };
+}
+
+/// A discriminated union of two or more pointer types, with the discriminator
+/// in the low bit of the pointer.
+///
+/// This implementation is extremely efficient in space due to leveraging the
+/// low bits of the pointer, while exposing a natural and type-safe API.
+///
+/// Common use patterns would be something like this:
+///    PointerUnion<int*, float*> P;
+///    P = (int*)0;
+///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
+///    X = P.get<int*>();     // ok.
+///    Y = P.get<float*>();   // runtime assertion failure.
+///    Z = P.get<double*>();  // compile time failure.
+///    P = (float*)0;
+///    Y = P.get<float*>();   // ok.
+///    X = P.get<int*>();     // runtime assertion failure.
+///    PointerUnion<int*, int*> Q; // compile time failure.
+template <typename... PTs>
+class PointerUnion
+    : public pointer_union_detail::PointerUnionMembers<
+          PointerUnion<PTs...>,
+          PointerIntPair<
+              void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int,
+              pointer_union_detail::PointerUnionUIntTraits<PTs...>>,
+          0, PTs...> {
+  static_assert(TypesAreDistinct<PTs...>::value,
+                "PointerUnion alternative types cannot be repeated");
+  // The first type is special because we want to directly cast a pointer to a
+  // default-initialized union to a pointer to the first type. But we don't
+  // want PointerUnion to be a 'template <typename First, typename ...Rest>'
+  // because it's much more convenient to have a name for the whole pack. So
+  // split off the first type here.
+  using First = TypeAtIndex<0, PTs...>;
+  using Base = typename PointerUnion::PointerUnionMembers;
+
+public:
+  PointerUnion() = default;
+
+  PointerUnion(std::nullptr_t) : PointerUnion() {}
+  using Base::Base;
+
+  /// Test if the pointer held in the union is null, regardless of
+  /// which type it is.
+  bool isNull() const { return !this->Val.getPointer(); }
+
+  explicit operator bool() const { return !isNull(); }
+
+  /// Test if the Union currently holds the type matching T.
+  template <typename T> bool is() const {
+    return this->Val.getInt() == FirstIndexOfType<T, PTs...>::value;
+  }
+
+  /// Returns the value of the specified pointer type.
+  ///
+  /// If the specified pointer type is incorrect, assert.
+  template <typename T> T get() const {
+    assert(is<T>() && "Invalid accessor called");
+    return PointerLikeTypeTraits<T>::getFromVoidPointer(this->Val.getPointer());
+  }
+
+  /// Returns the current pointer if it is of the specified pointer type,
+  /// otherwise returns null.
+  template <typename T> T dyn_cast() const {
+    if (is<T>())
+      return get<T>();
+    return T();
+  }
+
+  /// If the union is set to the first pointer type get an address pointing to
+  /// it.
+  First const *getAddrOfPtr1() const {
+    return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
+  }
+
+  /// If the union is set to the first pointer type get an address pointing to
+  /// it.
+  First *getAddrOfPtr1() {
+    assert(is<First>() && "Val is not the first pointer");
+    assert(
+        PointerLikeTypeTraits<First>::getAsVoidPointer(get<First>()) ==
+            this->Val.getPointer() &&
+        "Can't get the address because PointerLikeTypeTraits changes the ptr");
+    return const_cast<First *>(
+        reinterpret_cast<const First *>(this->Val.getAddrOfPointer()));
+  }
+
+  /// Assignment from nullptr which just clears the union.
+  const PointerUnion &operator=(std::nullptr_t) {
+    this->Val.initWithPointer(nullptr);
+    return *this;
+  }
+
+  /// Assignment from elements of the union.
+  using Base::operator=;
+
+  void *getOpaqueValue() const { return this->Val.getOpaqueValue(); }
+  static inline PointerUnion getFromOpaqueValue(void *VP) {
+    PointerUnion V;
+    V.Val = decltype(V.Val)::getFromOpaqueValue(VP);
+    return V;
+  }
+};
+
+template <typename ...PTs>
+bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
+  return lhs.getOpaqueValue() == rhs.getOpaqueValue();
+}
+
+template <typename ...PTs>
+bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
+  return lhs.getOpaqueValue() != rhs.getOpaqueValue();
+}
+
+template <typename ...PTs>
+bool operator<(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) {
+  return lhs.getOpaqueValue() < rhs.getOpaqueValue();
+}
+
+// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
+// # low bits available = min(PT1bits,PT2bits)-1.
+template <typename ...PTs>
+struct PointerLikeTypeTraits<PointerUnion<PTs...>> {
+  static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) {
+    return P.getOpaqueValue();
+  }
+
+  static inline PointerUnion<PTs...> getFromVoidPointer(void *P) {
+    return PointerUnion<PTs...>::getFromOpaqueValue(P);
+  }
+
+  // The number of bits available are the min of the pointer types minus the
+  // bits needed for the discriminator.
+  static constexpr int NumLowBitsAvailable = PointerLikeTypeTraits<decltype(
+      PointerUnion<PTs...>::Val)>::NumLowBitsAvailable;
+};
+
+// Teach DenseMap how to use PointerUnions as keys.
+template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> {
+  using Union = PointerUnion<PTs...>;
+  using FirstInfo =
+      DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>;
+
+  static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); }
+
+  static inline Union getTombstoneKey() {
+    return Union(FirstInfo::getTombstoneKey());
+  }
+
+  static unsigned getHashValue(const Union &UnionVal) {
+    intptr_t key = (intptr_t)UnionVal.getOpaqueValue();
+    return DenseMapInfo<intptr_t>::getHashValue(key);
+  }
+
+  static bool isEqual(const Union &LHS, const Union &RHS) {
+    return LHS == RHS;
+  }
+};
+
+} // end namespace wpi
+
+#endif // WPIUTIL_WPI_POINTERUNION_H
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/ReverseIteration.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/ReverseIteration.h
new file mode 100644
index 0000000..f46d38d
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/ReverseIteration.h
@@ -0,0 +1,18 @@
+#ifndef WPIUTIL_WPI_REVERSEITERATION_H
+#define WPIUTIL_WPI_REVERSEITERATION_H
+
+#include "wpi/PointerLikeTypeTraits.h"
+
+namespace wpi {
+
+template<class T = void *>
+bool shouldReverseIterate() {
+#if LLVM_ENABLE_REVERSE_ITERATION
+  return detail::IsPointerLike<T>::value;
+#else
+  return false;
+#endif
+}
+
+}
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/STLForwardCompat.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/STLForwardCompat.h
new file mode 100644
index 0000000..7f8f068
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/STLForwardCompat.h
@@ -0,0 +1,83 @@
+//===- STLForwardCompat.h - Library features from future STLs ------C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains library features backported from future STL versions.
+///
+/// These should be replaced with their STL counterparts as the C++ version LLVM
+/// is compiled with is updated.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_STLFORWARDCOMPAT_H
+#define WPIUTIL_WPI_STLFORWARDCOMPAT_H
+
+#include <type_traits>
+
+namespace wpi {
+
+//===----------------------------------------------------------------------===//
+//     Features from C++17
+//===----------------------------------------------------------------------===//
+
+template <typename T>
+struct negation // NOLINT(readability-identifier-naming)
+    : std::integral_constant<bool, !bool(T::value)> {};
+
+template <typename...>
+struct conjunction // NOLINT(readability-identifier-naming)
+    : std::true_type {};
+template <typename B1> struct conjunction<B1> : B1 {};
+template <typename B1, typename... Bn>
+struct conjunction<B1, Bn...>
+    : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+
+template <typename...>
+struct disjunction // NOLINT(readability-identifier-naming)
+    : std::false_type {};
+template <typename B1> struct disjunction<B1> : B1 {};
+template <typename B1, typename... Bn>
+struct disjunction<B1, Bn...>
+    : std::conditional<bool(B1::value), B1, disjunction<Bn...>>::type {};
+
+struct in_place_t // NOLINT(readability-identifier-naming)
+{
+  explicit in_place_t() = default;
+};
+/// \warning This must not be odr-used, as it cannot be made \c inline in C++14.
+constexpr in_place_t in_place; // NOLINT(readability-identifier-naming)
+
+template <typename T>
+struct in_place_type_t // NOLINT(readability-identifier-naming)
+{
+  explicit in_place_type_t() = default;
+};
+
+template <std::size_t I>
+struct in_place_index_t // NOLINT(readability-identifier-naming)
+{
+  explicit in_place_index_t() = default;
+};
+
+//===----------------------------------------------------------------------===//
+//     Features from C++20
+//===----------------------------------------------------------------------===//
+
+template <typename T>
+struct remove_cvref // NOLINT(readability-identifier-naming)
+{
+  using type = std::remove_cv_t<std::remove_reference_t<T>>;
+};
+
+template <typename T>
+using remove_cvref_t // NOLINT(readability-identifier-naming)
+    = typename wpi::remove_cvref<T>::type;
+
+} // namespace wpi
+
+#endif // WPIUTIL_WPI_STLFORWARDCOMPAT_H
diff --git a/wpiutil/src/main/native/include/wpi/SmallPtrSet.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallPtrSet.h
similarity index 83%
rename from wpiutil/src/main/native/include/wpi/SmallPtrSet.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallPtrSet.h
index 8669527..1ada1e0 100644
--- a/wpiutil/src/main/native/include/wpi/SmallPtrSet.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallPtrSet.h
@@ -1,26 +1,26 @@
 //===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// This file defines the SmallPtrSet class.  See the doxygen comment for
-// SmallPtrSetImplBase for more details on the algorithm used.
+///
+/// \file
+/// This file defines the SmallPtrSet class.  See the doxygen comment for
+/// SmallPtrSetImplBase for more details on the algorithm used.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef WPIUTIL_WPI_SMALLPTRSET_H
 #define WPIUTIL_WPI_SMALLPTRSET_H
 
+#include "wpi/EpochTracker.h"
 #include "wpi/Compiler.h"
-#include "wpi/PointerLikeTypeTraits.h"
+#include "wpi/ReverseIteration.h"
 #include "wpi/type_traits.h"
 #include <cassert>
 #include <cstddef>
-#include <cstdint>
 #include <cstdlib>
 #include <cstring>
 #include <initializer_list>
@@ -47,7 +47,7 @@
 /// (-2), to allow deletion.  The hash table is resized when the table is 3/4 or
 /// more.  When this happens, the table is doubled in size.
 ///
-class SmallPtrSetImplBase {
+class SmallPtrSetImplBase : public DebugEpochBase {
   friend class SmallPtrSetIteratorImpl;
 
 protected:
@@ -93,6 +93,7 @@
   size_type size() const { return NumNonEmpty - NumTombstones; }
 
   void clear() {
+    incrementEpoch();
     // If the capacity of the array is huge, and the # elements used is small,
     // shrink the array.
     if (!isSmall()) {
@@ -139,12 +140,14 @@
       if (LastTombstone != nullptr) {
         *LastTombstone = Ptr;
         --NumTombstones;
+        incrementEpoch();
         return std::make_pair(LastTombstone, true);
       }
 
       // Nope, there isn't.  If we stay small, just 'pushback' now.
       if (NumNonEmpty < CurArraySize) {
         SmallArray[NumNonEmpty++] = Ptr;
+        incrementEpoch();
         return std::make_pair(SmallArray + (NumNonEmpty - 1), true);
       }
       // Otherwise, hit the big set case, which will call grow.
@@ -224,6 +227,10 @@
 public:
   explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
     : Bucket(BP), End(E) {
+    if (shouldReverseIterate()) {
+      RetreatIfNotValid();
+      return;
+    }
     AdvanceIfNotValid();
   }
 
@@ -257,7 +264,8 @@
 
 /// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
 template <typename PtrTy>
-class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
+class SmallPtrSetIterator : public SmallPtrSetIteratorImpl,
+                            DebugEpochBase::HandleBase {
   using PtrTraits = PointerLikeTypeTraits<PtrTy>;
 
 public:
@@ -267,17 +275,29 @@
   using difference_type = std::ptrdiff_t;
   using iterator_category = std::forward_iterator_tag;
 
-  explicit SmallPtrSetIterator(const void *const *BP, const void *const *E)
-      : SmallPtrSetIteratorImpl(BP, E) {}
+  explicit SmallPtrSetIterator(const void *const *BP, const void *const *E,
+                               const DebugEpochBase &Epoch)
+      : SmallPtrSetIteratorImpl(BP, E), DebugEpochBase::HandleBase(&Epoch) {}
 
-  // Most methods provided by baseclass.
+  // Most methods are provided by the base class.
 
   const PtrTy operator*() const {
+    assert(isHandleInSync() && "invalid iterator access!");
+    if (shouldReverseIterate()) {
+      assert(Bucket > End);
+      return PtrTraits::getFromVoidPointer(const_cast<void *>(Bucket[-1]));
+    }
     assert(Bucket < End);
     return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
   }
 
   inline SmallPtrSetIterator& operator++() {          // Preincrement
+    assert(isHandleInSync() && "invalid iterator access!");
+    if (shouldReverseIterate()) {
+      --Bucket;
+      RetreatIfNotValid();
+      return *this;
+    }
     ++Bucket;
     AdvanceIfNotValid();
     return *this;
@@ -327,14 +347,8 @@
   using ConstPtrTraits = PointerLikeTypeTraits<ConstPtrType>;
 
 protected:
-  // Constructors that forward to the base.
-  SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that)
-      : SmallPtrSetImplBase(SmallStorage, that) {}
-  SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize,
-                  SmallPtrSetImpl &&that)
-      : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {}
-  explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize)
-      : SmallPtrSetImplBase(SmallStorage, SmallSize) {}
+  // Forward constructors to the base.
+  using SmallPtrSetImplBase::SmallPtrSetImplBase;
 
 public:
   using iterator = SmallPtrSetIterator<PtrType>;
@@ -353,17 +367,28 @@
     return std::make_pair(makeIterator(p.first), p.second);
   }
 
+  /// Insert the given pointer with an iterator hint that is ignored. This is
+  /// identical to calling insert(Ptr), but allows SmallPtrSet to be used by
+  /// std::insert_iterator and std::inserter().
+  iterator insert(iterator, PtrType Ptr) {
+    return insert(Ptr).first;
+  }
+
   /// erase - If the set contains the specified pointer, remove it and return
   /// true, otherwise return false.
   bool erase(PtrType Ptr) {
     return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
   }
-
   /// count - Return 1 if the specified pointer is in the set, 0 otherwise.
-  size_type count(ConstPtrType Ptr) const { return find(Ptr) != end() ? 1 : 0; }
+  size_type count(ConstPtrType Ptr) const {
+    return find_imp(ConstPtrTraits::getAsVoidPointer(Ptr)) != EndPointer();
+  }
   iterator find(ConstPtrType Ptr) const {
     return makeIterator(find_imp(ConstPtrTraits::getAsVoidPointer(Ptr)));
   }
+  bool contains(ConstPtrType Ptr) const {
+    return find_imp(ConstPtrTraits::getAsVoidPointer(Ptr)) != EndPointer();
+  }
 
   template <typename IterT>
   void insert(IterT I, IterT E) {
@@ -376,6 +401,8 @@
   }
 
   iterator begin() const {
+    if (shouldReverseIterate())
+      return makeIterator(EndPointer() - 1);
     return makeIterator(CurArray);
   }
   iterator end() const { return makeIterator(EndPointer()); }
@@ -383,10 +410,38 @@
 private:
   /// Create an iterator that dereferences to same place as the given pointer.
   iterator makeIterator(const void *const *P) const {
-    return iterator(P, EndPointer());
+    if (shouldReverseIterate())
+      return iterator(P == EndPointer() ? CurArray : P + 1, CurArray, *this);
+    return iterator(P, EndPointer(), *this);
   }
 };
 
+/// Equality comparison for SmallPtrSet.
+///
+/// Iterates over elements of LHS confirming that each value from LHS is also in
+/// RHS, and that no additional values are in RHS.
+template <typename PtrType>
+bool operator==(const SmallPtrSetImpl<PtrType> &LHS,
+                const SmallPtrSetImpl<PtrType> &RHS) {
+  if (LHS.size() != RHS.size())
+    return false;
+
+  for (const auto *KV : LHS)
+    if (!RHS.count(KV))
+      return false;
+
+  return true;
+}
+
+/// Inequality comparison for SmallPtrSet.
+///
+/// Equivalent to !(LHS == RHS).
+template <typename PtrType>
+bool operator!=(const SmallPtrSetImpl<PtrType> &LHS,
+                const SmallPtrSetImpl<PtrType> &RHS) {
+  return !(LHS == RHS);
+}
+
 /// SmallPtrSet - This class implements a set which is optimized for holding
 /// SmallSize or less elements.  This internally rounds up SmallSize to the next
 /// power of two if it is not already a power of two.  See the comments above
@@ -460,4 +515,4 @@
 
 } // end namespace std
 
-#endif // LLVM_ADT_SMALLPTRSET_H
+#endif // WPIUTIL_WPI_SMALLPTRSET_H
diff --git a/wpiutil/src/main/native/include/wpi/SmallSet.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallSet.h
similarity index 83%
rename from wpiutil/src/main/native/include/wpi/SmallSet.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallSet.h
index dca204e..7b1b283 100644
--- a/wpiutil/src/main/native/include/wpi/SmallSet.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallSet.h
@@ -1,14 +1,14 @@
 //===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// This file defines the SmallSet class.
-//
+///
+/// \file
+/// This file defines the SmallSet class.
+///
 //===----------------------------------------------------------------------===//
 
 #ifndef WPIUTIL_WPI_SMALLSET_H
@@ -16,8 +16,8 @@
 
 #include "wpi/SmallPtrSet.h"
 #include "wpi/SmallVector.h"
-#include "wpi/Compiler.h"
 #include "wpi/iterator.h"
+#include "wpi/Compiler.h"
 #include "wpi/type_traits.h"
 #include <cstddef>
 #include <functional>
@@ -233,6 +233,13 @@
     return {Set.end()};
   }
 
+  /// Check if the SmallSet contains the given element.
+  bool contains(const T &V) const {
+    if (isSmall())
+      return vfind(V) != Vector.end();
+    return Set.find(V) != Set.end();
+  }
+
 private:
   bool isSmall() const { return Set.empty(); }
 
@@ -249,6 +256,31 @@
 template <typename PointeeType, unsigned N>
 class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N> {};
 
+/// Equality comparison for SmallSet.
+///
+/// Iterates over elements of LHS confirming that each element is also a member
+/// of RHS, and that RHS contains no additional values.
+/// Equivalent to N calls to RHS.count.
+/// For small-set mode amortized complexity is O(N^2)
+/// For large-set mode amortized complexity is linear, worst case is O(N^2) (if
+/// every hash collides).
+template <typename T, unsigned LN, unsigned RN, typename C>
+bool operator==(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) {
+  if (LHS.size() != RHS.size())
+    return false;
+
+  // All elements in LHS must also be in RHS
+  return std::all_of(LHS.begin(), LHS.end(), [&RHS](const T &E) { return RHS.count(E); });
+}
+
+/// Inequality comparison for SmallSet.
+///
+/// Equivalent to !(LHS == RHS). See operator== for performance notes.
+template <typename T, unsigned LN, unsigned RN, typename C>
+bool operator!=(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) {
+  return !(LHS == RHS);
+}
+
 } // end namespace wpi
 
-#endif // LLVM_ADT_SMALLSET_H
+#endif // WPIUTIL_WPI_SMALLSET_H
diff --git a/wpiutil/src/main/native/include/wpi/SmallString.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallString.h
similarity index 71%
rename from wpiutil/src/main/native/include/wpi/SmallString.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallString.h
index da4b2e4..4a53fee 100644
--- a/wpiutil/src/main/native/include/wpi/SmallString.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallString.h
@@ -1,14 +1,14 @@
 //===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// This file defines the SmallString class.
-//
+///
+/// \file
+/// This file defines the SmallString class.
+///
 //===----------------------------------------------------------------------===//
 
 #ifndef WPIUTIL_WPI_SMALLSTRING_H
@@ -16,6 +16,7 @@
 
 #include "wpi/SmallVector.h"
 #include <cstddef>
+#include <string>
 #include <string_view>
 
 namespace wpi {
@@ -29,66 +30,58 @@
   SmallString() = default;
 
   /// Initialize from a std::string_view.
-  SmallString(std::string_view S)
-    : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
+  SmallString(std::string_view S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
+
+  /// Initialize by concatenating a list of std::string_views.
+  SmallString(std::initializer_list<std::string_view> Refs)
+      : SmallVector<char, InternalLen>() {
+    this->append(Refs);
+  }
 
   /// Initialize with a range.
   template<typename ItTy>
   SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
 
-  // Note that in order to add new overloads for append & assign, we have to
-  // duplicate the inherited versions so as not to inadvertently hide them.
-
   /// @}
   /// @name String Assignment
   /// @{
 
-  /// Assign from a repeated element.
-  void assign(size_t NumElts, char Elt) {
-    this->SmallVectorImpl<char>::assign(NumElts, Elt);
-  }
-
-  /// Assign from an iterator pair.
-  template<typename in_iter>
-  void assign(in_iter S, in_iter E) {
-    this->clear();
-    SmallVectorImpl<char>::append(S, E);
-  }
+  using SmallVector<char, InternalLen>::assign;
 
   /// Assign from a std::string_view.
   void assign(std::string_view RHS) {
-    this->clear();
-    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+    SmallVectorImpl<char>::assign(RHS.begin(), RHS.end());
   }
 
-  /// Assign from a SmallVector.
-  void assign(const SmallVectorImpl<char> &RHS) {
+  /// Assign from a list of std::string_views.
+  void assign(std::initializer_list<std::string_view> Refs) {
     this->clear();
-    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+    append(Refs);
   }
 
   /// @}
   /// @name String Concatenation
   /// @{
 
-  /// Append from an iterator pair.
-  template<typename in_iter>
-  void append(in_iter S, in_iter E) {
-    SmallVectorImpl<char>::append(S, E);
-  }
-
-  void append(size_t NumInputs, char Elt) {
-    SmallVectorImpl<char>::append(NumInputs, Elt);
-  }
+  using SmallVector<char, InternalLen>::append;
 
   /// Append from a std::string_view.
   void append(std::string_view RHS) {
     SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
   }
 
-  /// Append from a SmallVector.
-  void append(const SmallVectorImpl<char> &RHS) {
-    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
+  /// Append from a list of std::string_views.
+  void append(std::initializer_list<std::string_view> Refs) {
+    size_t CurrentSize = this->size();
+    size_t SizeNeeded = CurrentSize;
+    for (std::string_view Ref : Refs)
+      SizeNeeded += Ref.size();
+    this->resize_for_overwrite(SizeNeeded);
+    for (std::string_view Ref : Refs) {
+      std::copy(Ref.begin(), Ref.end(), this->begin() + CurrentSize);
+      CurrentSize += Ref.size();
+    }
+    assert(CurrentSize == this->size());
   }
 
   /// @}
@@ -185,10 +178,7 @@
   // Extra methods.
 
   /// Explicit conversion to std::string_view.
-  std::string_view str() const { return {this->begin(), this->size()}; }
-
-  /// Explicit conversion to std::string.
-  std::string string() const { return {this->begin(), this->size()}; }
+  std::string_view str() const { return std::string_view(this->begin(), this->size()); }
 
   // TODO: Make this const, if it's safe...
   const char* c_str() {
@@ -200,13 +190,14 @@
   /// Implicit conversion to std::string_view.
   operator std::string_view() const { return str(); }
 
-  /// Implicit conversion to std::string.
-  operator std::string() const { return string(); }
+  explicit operator std::string() const {
+    return std::string(this->data(), this->size());
+  }
 
   // Extra operators.
-  const SmallString &operator=(std::string_view RHS) {
-    this->clear();
-    return *this += RHS;
+  SmallString &operator=(std::string_view RHS) {
+    this->assign(RHS);
+    return *this;
   }
 
   SmallString &operator+=(std::string_view RHS) {
@@ -221,4 +212,4 @@
 
 } // end namespace wpi
 
-#endif // LLVM_ADT_SMALLSTRING_H
+#endif // WPIUTIL_WPI_SMALLSTRING_H
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallVector.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallVector.h
new file mode 100644
index 0000000..134ce67
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallVector.h
@@ -0,0 +1,1312 @@
+//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// /file
+/// This file defines the SmallVector class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_SMALLVECTOR_H
+#define WPIUTIL_WPI_SMALLVECTOR_H
+
+// This file uses std::memcpy() to copy std::pair<unsigned int, unsigned int>.
+// That type is POD, but the standard doesn't guarantee that. GCC doesn't treat
+// the type as POD so it throws a warning. We want to consider this a warning
+// instead of an error.
+#if __GNUC__ >= 8
+#pragma GCC diagnostic warning "-Wclass-memaccess"
+#endif
+
+#include "wpi/Compiler.h"
+#include "wpi/type_traits.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
+#include <initializer_list>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+namespace wpi {
+
+template <typename IteratorT> class iterator_range;
+
+/// This is all the stuff common to all SmallVectors.
+///
+/// The template parameter specifies the type which should be used to hold the
+/// Size and Capacity of the SmallVector, so it can be adjusted.
+/// Using 32 bit size is desirable to shrink the size of the SmallVector.
+/// Using 64 bit size is desirable for cases like SmallVector<char>, where a
+/// 32 bit size would limit the vector to ~4GB. SmallVectors are used for
+/// buffering bitcode output - which can exceed 4GB.
+class SmallVectorBase {
+protected:
+  void *BeginX;
+  unsigned Size = 0, Capacity;
+
+  /// The maximum value of the Size_T used.
+  static constexpr size_t SizeTypeMax() {
+    return (std::numeric_limits<unsigned>::max)();
+  }
+
+  SmallVectorBase() = delete;
+  SmallVectorBase(void *FirstEl, size_t TotalCapacity)
+      : BeginX(FirstEl), Capacity(static_cast<unsigned>(TotalCapacity)) {}
+
+  /// This is a helper for \a grow() that's out of line to reduce code
+  /// duplication.  This function will report a fatal error if it can't grow at
+  /// least to \p MinSize.
+  void *mallocForGrow(size_t MinSize, size_t TSize, size_t &NewCapacity);
+
+  /// This is an implementation of the grow() method which only works
+  /// on POD-like data types and is out of line to reduce code duplication.
+  /// This function will report a fatal error if it cannot increase capacity.
+  void grow_pod(void *FirstEl, size_t MinSize, size_t TSize);
+
+public:
+  size_t size() const { return Size; }
+  size_t capacity() const { return Capacity; }
+
+  LLVM_NODISCARD bool empty() const { return !Size; }
+
+protected:
+  /// Set the array size to \p N, which the current array must have enough
+  /// capacity for.
+  ///
+  /// This does not construct or destroy any elements in the vector.
+  void set_size(size_t N) {
+    assert(N <= capacity());
+    Size = static_cast<unsigned>(N);
+  }
+};
+
+/// Figure out the offset of the first element.
+template <class T, typename = void> struct SmallVectorAlignmentAndSize {
+  alignas(SmallVectorBase) char Base[sizeof(
+      SmallVectorBase)];
+  alignas(T) char FirstEl[sizeof(T)];
+};
+
+/// This is the part of SmallVectorTemplateBase which does not depend on whether
+/// the type T is a POD. The extra dummy template argument is used by ArrayRef
+/// to avoid unnecessarily requiring T to be complete.
+template <typename T, typename = void>
+class SmallVectorTemplateCommon
+    : public SmallVectorBase {
+  using Base = SmallVectorBase;
+
+  /// Find the address of the first element.  For this pointer math to be valid
+  /// with small-size of 0 for T with lots of alignment, it's important that
+  /// SmallVectorStorage is properly-aligned even for small-size of 0.
+  void *getFirstEl() const {
+    return const_cast<void *>(reinterpret_cast<const void *>(
+        reinterpret_cast<const char *>(this) +
+        offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)));
+  }
+  // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
+
+protected:
+  SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {}
+
+  void grow_pod(size_t MinSize, size_t TSize) {
+    Base::grow_pod(getFirstEl(), MinSize, TSize);
+  }
+
+  /// Return true if this is a smallvector which has not had dynamic
+  /// memory allocated for it.
+  bool isSmall() const { return this->BeginX == getFirstEl(); }
+
+  /// Put this vector in a state of being small.
+  void resetToSmall() {
+    this->BeginX = getFirstEl();
+    this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect.
+  }
+
+  /// Return true if V is an internal reference to the given range.
+  bool isReferenceToRange(const void *V, const void *First, const void *Last) const {
+    // Use std::less to avoid UB.
+    std::less<> LessThan;
+    return !LessThan(V, First) && LessThan(V, Last);
+  }
+
+  /// Return true if V is an internal reference to this vector.
+  bool isReferenceToStorage(const void *V) const {
+    return isReferenceToRange(V, this->begin(), this->end());
+  }
+
+  /// Return true if First and Last form a valid (possibly empty) range in this
+  /// vector's storage.
+  bool isRangeInStorage(const void *First, const void *Last) const {
+    // Use std::less to avoid UB.
+    std::less<> LessThan;
+    return !LessThan(First, this->begin()) && !LessThan(Last, First) &&
+           !LessThan(this->end(), Last);
+  }
+
+  /// Return true unless Elt will be invalidated by resizing the vector to
+  /// NewSize.
+  bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
+    // Past the end.
+    if (LLVM_LIKELY(!isReferenceToStorage(Elt)))
+      return true;
+
+    // Return false if Elt will be destroyed by shrinking.
+    if (NewSize <= this->size())
+      return Elt < this->begin() + NewSize;
+
+    // Return false if we need to grow.
+    return NewSize <= this->capacity();
+  }
+
+  /// Check whether Elt will be invalidated by resizing the vector to NewSize.
+  void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
+    assert(isSafeToReferenceAfterResize(Elt, NewSize) &&
+           "Attempting to reference an element of the vector in an operation "
+           "that invalidates it");
+  }
+
+  /// Check whether Elt will be invalidated by increasing the size of the
+  /// vector by N.
+  void assertSafeToAdd(const void *Elt, size_t N = 1) {
+    this->assertSafeToReferenceAfterResize(Elt, this->size() + N);
+  }
+
+  /// Check whether any part of the range will be invalidated by clearing.
+  void assertSafeToReferenceAfterClear(const T *From, const T *To) {
+    if (From == To)
+      return;
+    this->assertSafeToReferenceAfterResize(From, 0);
+    this->assertSafeToReferenceAfterResize(To - 1, 0);
+  }
+  template <
+      class ItTy,
+      std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value,
+                       bool> = false>
+  void assertSafeToReferenceAfterClear(ItTy, ItTy) {}
+
+  /// Check whether any part of the range will be invalidated by growing.
+  void assertSafeToAddRange(const T *From, const T *To) {
+    if (From == To)
+      return;
+    this->assertSafeToAdd(From, To - From);
+    this->assertSafeToAdd(To - 1, To - From);
+  }
+  template <
+      class ItTy,
+      std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value,
+                       bool> = false>
+  void assertSafeToAddRange(ItTy, ItTy) {}
+
+  /// Reserve enough space to add one element, and return the updated element
+  /// pointer in case it was a reference to the storage.
+  template <class U>
+  static const T *reserveForParamAndGetAddressImpl(U *This, const T &Elt,
+                                                   size_t N) {
+    size_t NewSize = This->size() + N;
+    if (LLVM_LIKELY(NewSize <= This->capacity()))
+      return &Elt;
+
+    bool ReferencesStorage = false;
+    int64_t Index = -1;
+    if (!U::TakesParamByValue) {
+      if (LLVM_UNLIKELY(This->isReferenceToStorage(&Elt))) {
+        ReferencesStorage = true;
+        Index = &Elt - This->begin();
+      }
+    }
+    This->grow(NewSize);
+    return ReferencesStorage ? This->begin() + Index : &Elt;
+  }
+
+public:
+  using size_type = size_t;
+  using difference_type = ptrdiff_t;
+  using value_type = T;
+  using iterator = T *;
+  using const_iterator = const T *;
+
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+  using reverse_iterator = std::reverse_iterator<iterator>;
+
+  using reference = T &;
+  using const_reference = const T &;
+  using pointer = T *;
+  using const_pointer = const T *;
+
+  using Base::capacity;
+  using Base::empty;
+  using Base::size;
+
+  // forward iterator creation methods.
+  iterator begin() { return (iterator)this->BeginX; }
+  const_iterator begin() const { return (const_iterator)this->BeginX; }
+  iterator end() { return begin() + size(); }
+  const_iterator end() const { return begin() + size(); }
+
+  // reverse iterator creation methods.
+  reverse_iterator rbegin()            { return reverse_iterator(end()); }
+  const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
+  reverse_iterator rend()              { return reverse_iterator(begin()); }
+  const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
+
+  size_type size_in_bytes() const { return size() * sizeof(T); }
+  size_type max_size() const {
+    return (std::min)(this->SizeTypeMax(), size_type(-1) / sizeof(T));
+  }
+
+  size_t capacity_in_bytes() const { return capacity() * sizeof(T); }
+
+  /// Return a pointer to the vector's buffer, even if empty().
+  pointer data() { return pointer(begin()); }
+  /// Return a pointer to the vector's buffer, even if empty().
+  const_pointer data() const { return const_pointer(begin()); }
+
+  reference operator[](size_type idx) {
+    assert(idx < size());
+    return begin()[idx];
+  }
+  const_reference operator[](size_type idx) const {
+    assert(idx < size());
+    return begin()[idx];
+  }
+
+  reference front() {
+    assert(!empty());
+    return begin()[0];
+  }
+  const_reference front() const {
+    assert(!empty());
+    return begin()[0];
+  }
+
+  reference back() {
+    assert(!empty());
+    return end()[-1];
+  }
+  const_reference back() const {
+    assert(!empty());
+    return end()[-1];
+  }
+};
+
+/// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put
+/// method implementations that are designed to work with non-trivial T's.
+///
+/// We approximate is_trivially_copyable with trivial move/copy construction and
+/// trivial destruction. While the standard doesn't specify that you're allowed
+/// copy these types with memcpy, there is no way for the type to observe this.
+/// This catches the important case of std::pair<POD, POD>, which is not
+/// trivially assignable.
+template <typename T, bool = (is_trivially_copy_constructible<T>::value) &&
+                             (is_trivially_move_constructible<T>::value) &&
+                             std::is_trivially_destructible<T>::value>
+class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
+  friend class SmallVectorTemplateCommon<T>;
+
+protected:
+  static constexpr bool TakesParamByValue = false;
+  using ValueParamT = const T &;
+
+  SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
+
+  static void destroy_range(T *S, T *E) {
+    while (S != E) {
+      --E;
+      E->~T();
+    }
+  }
+
+  /// Move the range [I, E) into the uninitialized memory starting with "Dest",
+  /// constructing elements as needed.
+  template<typename It1, typename It2>
+  static void uninitialized_move(It1 I, It1 E, It2 Dest) {
+    std::uninitialized_copy(std::make_move_iterator(I),
+                            std::make_move_iterator(E), Dest);
+  }
+
+  /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
+  /// constructing elements as needed.
+  template<typename It1, typename It2>
+  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
+    std::uninitialized_copy(I, E, Dest);
+  }
+
+  /// Grow the allocated memory (without initializing new elements), doubling
+  /// the size of the allocated memory. Guarantees space for at least one more
+  /// element, or MinSize more elements if specified.
+  void grow(size_t MinSize = 0);
+
+  /// Create a new allocation big enough for \p MinSize and pass back its size
+  /// in \p NewCapacity. This is the first section of \a grow().
+  T *mallocForGrow(size_t MinSize, size_t &NewCapacity) {
+    return static_cast<T *>(
+        SmallVectorBase::mallocForGrow(
+            MinSize, sizeof(T), NewCapacity));
+  }
+
+  /// Move existing elements over to the new allocation \p NewElts, the middle
+  /// section of \a grow().
+  void moveElementsForGrow(T *NewElts);
+
+  /// Transfer ownership of the allocation, finishing up \a grow().
+  void takeAllocationForGrow(T *NewElts, size_t NewCapacity);
+
+  /// Reserve enough space to add one element, and return the updated element
+  /// pointer in case it was a reference to the storage.
+  const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) {
+    return this->reserveForParamAndGetAddressImpl(this, Elt, N);
+  }
+
+  /// Reserve enough space to add one element, and return the updated element
+  /// pointer in case it was a reference to the storage.
+  T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) {
+    return const_cast<T *>(
+        this->reserveForParamAndGetAddressImpl(this, Elt, N));
+  }
+
+  static T &&forward_value_param(T &&V) { return std::move(V); }
+  static const T &forward_value_param(const T &V) { return V; }
+
+  void growAndAssign(size_t NumElts, const T &Elt) {
+    // Grow manually in case Elt is an internal reference.
+    size_t NewCapacity;
+    T *NewElts = mallocForGrow(NumElts, NewCapacity);
+    std::uninitialized_fill_n(NewElts, NumElts, Elt);
+    this->destroy_range(this->begin(), this->end());
+    takeAllocationForGrow(NewElts, NewCapacity);
+    this->set_size(NumElts);
+  }
+
+  template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) {
+    // Grow manually in case one of Args is an internal reference.
+    size_t NewCapacity;
+    T *NewElts = mallocForGrow(0, NewCapacity);
+    ::new ((void *)(NewElts + this->size())) T(std::forward<ArgTypes>(Args)...);
+    moveElementsForGrow(NewElts);
+    takeAllocationForGrow(NewElts, NewCapacity);
+    this->set_size(this->size() + 1);
+    return this->back();
+  }
+
+public:
+  void push_back(const T &Elt) {
+    const T *EltPtr = reserveForParamAndGetAddress(Elt);
+    ::new ((void *)this->end()) T(*EltPtr);
+    this->set_size(this->size() + 1);
+  }
+
+  void push_back(T &&Elt) {
+    T *EltPtr = reserveForParamAndGetAddress(Elt);
+    ::new ((void *)this->end()) T(::std::move(*EltPtr));
+    this->set_size(this->size() + 1);
+  }
+
+  void pop_back() {
+    this->set_size(this->size() - 1);
+    this->end()->~T();
+  }
+};
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T, bool TriviallyCopyable>
+void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) {
+  size_t NewCapacity;
+  T *NewElts = mallocForGrow(MinSize, NewCapacity);
+  moveElementsForGrow(NewElts);
+  takeAllocationForGrow(NewElts, NewCapacity);
+}
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T, bool TriviallyCopyable>
+void SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow(
+    T *NewElts) {
+  // Move the elements over.
+  this->uninitialized_move(this->begin(), this->end(), NewElts);
+
+  // Destroy the original elements.
+  destroy_range(this->begin(), this->end());
+}
+
+// Define this out-of-line to dissuade the C++ compiler from inlining it.
+template <typename T, bool TriviallyCopyable>
+void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow(
+    T *NewElts, size_t NewCapacity) {
+  // If this wasn't grown from the inline copy, deallocate the old space.
+  if (!this->isSmall())
+    free(this->begin());
+
+  this->BeginX = NewElts;
+  this->Capacity = static_cast<unsigned>(NewCapacity);
+}
+
+/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
+/// method implementations that are designed to work with trivially copyable
+/// T's. This allows using memcpy in place of copy/move construction and
+/// skipping destruction.
+template <typename T>
+class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
+  friend class SmallVectorTemplateCommon<T>;
+
+protected:
+  /// True if it's cheap enough to take parameters by value. Doing so avoids
+  /// overhead related to mitigations for reference invalidation.
+  static constexpr bool TakesParamByValue = sizeof(T) <= 2 * sizeof(void *);
+
+  /// Either const T& or T, depending on whether it's cheap enough to take
+  /// parameters by value.
+  using ValueParamT =
+      typename std::conditional<TakesParamByValue, T, const T &>::type;
+
+  SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
+
+  // No need to do a destroy loop for POD's.
+  static void destroy_range(T *, T *) {}
+
+  /// Move the range [I, E) onto the uninitialized memory
+  /// starting with "Dest", constructing elements into it as needed.
+  template<typename It1, typename It2>
+  static void uninitialized_move(It1 I, It1 E, It2 Dest) {
+    // Just do a copy.
+    uninitialized_copy(I, E, Dest);
+  }
+
+  /// Copy the range [I, E) onto the uninitialized memory
+  /// starting with "Dest", constructing elements into it as needed.
+  template<typename It1, typename It2>
+  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
+    // Arbitrary iterator types; just use the basic implementation.
+    std::uninitialized_copy(I, E, Dest);
+  }
+
+  /// Copy the range [I, E) onto the uninitialized memory
+  /// starting with "Dest", constructing elements into it as needed.
+  template <typename T1, typename T2>
+  static void uninitialized_copy(
+      T1 *I, T1 *E, T2 *Dest,
+      std::enable_if_t<std::is_same<typename std::remove_const<T1>::type,
+                                    T2>::value> * = nullptr) {
+    // Use memcpy for PODs iterated by pointers (which includes SmallVector
+    // iterators): std::uninitialized_copy optimizes to memmove, but we can
+    // use memcpy here. Note that I and E are iterators and thus might be
+    // invalid for memcpy if they are equal.
+    if (I != E)
+      memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T));
+  }
+
+  /// Double the size of the allocated memory, guaranteeing space for at
+  /// least one more element or MinSize if specified.
+  void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); }
+
+  /// Reserve enough space to add one element, and return the updated element
+  /// pointer in case it was a reference to the storage.
+  const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) {
+    return this->reserveForParamAndGetAddressImpl(this, Elt, N);
+  }
+
+  /// Reserve enough space to add one element, and return the updated element
+  /// pointer in case it was a reference to the storage.
+  T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) {
+    return const_cast<T *>(
+        this->reserveForParamAndGetAddressImpl(this, Elt, N));
+  }
+
+  /// Copy \p V or return a reference, depending on \a ValueParamT.
+  static ValueParamT forward_value_param(ValueParamT V) { return V; }
+
+  void growAndAssign(size_t NumElts, T Elt) {
+    // Elt has been copied in case it's an internal reference, side-stepping
+    // reference invalidation problems without losing the realloc optimization.
+    this->set_size(0);
+    this->grow(NumElts);
+    std::uninitialized_fill_n(this->begin(), NumElts, Elt);
+    this->set_size(NumElts);
+  }
+
+  template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) {
+    // Use push_back with a copy in case Args has an internal reference,
+    // side-stepping reference invalidation problems without losing the realloc
+    // optimization.
+    push_back(T(std::forward<ArgTypes>(Args)...));
+    return this->back();
+  }
+
+public:
+  void push_back(ValueParamT Elt) {
+    const T *EltPtr = reserveForParamAndGetAddress(Elt);
+    memcpy(reinterpret_cast<void *>(this->end()), EltPtr, sizeof(T));
+    this->set_size(this->size() + 1);
+  }
+
+  void pop_back() { this->set_size(this->size() - 1); }
+};
+
+/// This class consists of common code factored out of the SmallVector class to
+/// reduce code duplication based on the SmallVector 'N' template parameter.
+template <typename T>
+class SmallVectorImpl : public SmallVectorTemplateBase<T> {
+  using SuperClass = SmallVectorTemplateBase<T>;
+
+public:
+  using iterator = typename SuperClass::iterator;
+  using const_iterator = typename SuperClass::const_iterator;
+  using reference = typename SuperClass::reference;
+  using size_type = typename SuperClass::size_type;
+
+protected:
+  using SmallVectorTemplateBase<T>::TakesParamByValue;
+  using ValueParamT = typename SuperClass::ValueParamT;
+
+  // Default ctor - Initialize to empty.
+  explicit SmallVectorImpl(unsigned N)
+      : SmallVectorTemplateBase<T>(N) {}
+
+  void assignRemote(SmallVectorImpl &&RHS) {
+    this->destroy_range(this->begin(), this->end());
+    if (!this->isSmall())
+      free(this->begin());
+    this->BeginX = RHS.BeginX;
+    this->Size = RHS.Size;
+    this->Capacity = RHS.Capacity;
+    RHS.resetToSmall();
+  }
+
+public:
+  SmallVectorImpl(const SmallVectorImpl &) = delete;
+
+  ~SmallVectorImpl() {
+    // Subclass has already destructed this vector's elements.
+    // If this wasn't grown from the inline copy, deallocate the old space.
+    if (!this->isSmall())
+      free(this->begin());
+  }
+
+  void clear() {
+    this->destroy_range(this->begin(), this->end());
+    this->Size = 0;
+  }
+
+private:
+  // Make set_size() private to avoid misuse in subclasses.
+  using SuperClass::set_size;
+
+  template <bool ForOverwrite> void resizeImpl(size_type N) {
+    if (N == this->size())
+      return;
+
+    if (N < this->size()) {
+      this->truncate(N);
+      return;
+    }
+
+    this->reserve(N);
+    for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
+      if (ForOverwrite)
+        new (&*I) T;
+      else
+        new (&*I) T();
+    this->set_size(N);
+  }
+
+public:
+  void resize(size_type N) { resizeImpl<false>(N); }
+
+  /// Like resize, but \ref T is POD, the new values won't be initialized.
+  void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }
+
+  /// Like resize, but requires that \p N is less than \a size().
+  void truncate(size_type N) {
+    assert(this->size() >= N && "Cannot increase size with truncate");
+    this->destroy_range(this->begin() + N, this->end());
+    this->set_size(N);
+  }
+
+  void resize(size_type N, ValueParamT NV) {
+    if (N == this->size())
+      return;
+
+    if (N < this->size()) {
+      this->truncate(N);
+      return;
+    }
+
+    // N > this->size(). Defer to append.
+    this->append(N - this->size(), NV);
+  }
+
+  void reserve(size_type N) {
+    if (this->capacity() < N)
+      this->grow(N);
+  }
+
+  void pop_back_n(size_type NumItems) {
+    assert(this->size() >= NumItems);
+    truncate(this->size() - NumItems);
+  }
+
+  LLVM_NODISCARD T pop_back_val() {
+    T Result = ::std::move(this->back());
+    this->pop_back();
+    return Result;
+  }
+
+  void swap(SmallVectorImpl &RHS);
+
+  /// Add the specified range to the end of the SmallVector.
+  template <typename in_iter,
+            typename = std::enable_if_t<std::is_convertible<
+                typename std::iterator_traits<in_iter>::iterator_category,
+                std::input_iterator_tag>::value>>
+  void append(in_iter in_start, in_iter in_end) {
+    this->assertSafeToAddRange(in_start, in_end);
+    size_type NumInputs = std::distance(in_start, in_end);
+    this->reserve(this->size() + NumInputs);
+    this->uninitialized_copy(in_start, in_end, this->end());
+    this->set_size(this->size() + NumInputs);
+  }
+
+  /// Append \p NumInputs copies of \p Elt to the end.
+  void append(size_type NumInputs, ValueParamT Elt) {
+    const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumInputs);
+    std::uninitialized_fill_n(this->end(), NumInputs, *EltPtr);
+    this->set_size(this->size() + NumInputs);
+  }
+
+  void append(std::initializer_list<T> IL) {
+    append(IL.begin(), IL.end());
+  }
+
+  void append(const SmallVectorImpl &RHS) { append(RHS.begin(), RHS.end()); }
+
+  void assign(size_type NumElts, ValueParamT Elt) {
+    // Note that Elt could be an internal reference.
+    if (NumElts > this->capacity()) {
+      this->growAndAssign(NumElts, Elt);
+      return;
+    }
+
+    // Assign over existing elements.
+    std::fill_n(this->begin(), (std::min)(NumElts, this->size()), Elt);
+    if (NumElts > this->size())
+      std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt);
+    else if (NumElts < this->size())
+      this->destroy_range(this->begin() + NumElts, this->end());
+    this->set_size(NumElts);
+  }
+
+  // FIXME: Consider assigning over existing elements, rather than clearing &
+  // re-initializing them - for all assign(...) variants.
+
+  template <typename in_iter,
+            typename = std::enable_if_t<std::is_convertible<
+                typename std::iterator_traits<in_iter>::iterator_category,
+                std::input_iterator_tag>::value>>
+  void assign(in_iter in_start, in_iter in_end) {
+    this->assertSafeToReferenceAfterClear(in_start, in_end);
+    clear();
+    append(in_start, in_end);
+  }
+
+  void assign(std::initializer_list<T> IL) {
+    clear();
+    append(IL);
+  }
+
+  void assign(const SmallVectorImpl &RHS) { assign(RHS.begin(), RHS.end()); }
+
+  iterator erase(const_iterator CI) {
+    // Just cast away constness because this is a non-const member function.
+    iterator I = const_cast<iterator>(CI);
+
+    assert(this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds.");
+
+    iterator N = I;
+    // Shift all elts down one.
+    std::move(I+1, this->end(), I);
+    // Drop the last elt.
+    this->pop_back();
+    return(N);
+  }
+
+  iterator erase(const_iterator CS, const_iterator CE) {
+    // Just cast away constness because this is a non-const member function.
+    iterator S = const_cast<iterator>(CS);
+    iterator E = const_cast<iterator>(CE);
+
+    assert(this->isRangeInStorage(S, E) && "Range to erase is out of bounds.");
+
+    iterator N = S;
+    // Shift all elts down.
+    iterator I = std::move(E, this->end(), S);
+    // Drop the last elts.
+    this->destroy_range(I, this->end());
+    this->set_size(I - this->begin());
+    return(N);
+  }
+
+private:
+  template <class ArgType> iterator insert_one_impl(iterator I, ArgType &&Elt) {
+    // Callers ensure that ArgType is derived from T.
+    static_assert(
+        std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>,
+                     T>::value,
+        "ArgType must be derived from T!");
+
+    if (I == this->end()) {  // Important special case for empty vector.
+      this->push_back(::std::forward<ArgType>(Elt));
+      return this->end()-1;
+    }
+
+    assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
+
+    // Grow if necessary.
+    size_t Index = I - this->begin();
+    std::remove_reference_t<ArgType> *EltPtr =
+        this->reserveForParamAndGetAddress(Elt);
+    I = this->begin() + Index;
+
+    ::new ((void*) this->end()) T(::std::move(this->back()));
+    // Push everything else over.
+    std::move_backward(I, this->end()-1, this->end());
+    this->set_size(this->size() + 1);
+
+    // If we just moved the element we're inserting, be sure to update
+    // the reference (never happens if TakesParamByValue).
+    static_assert(!TakesParamByValue || std::is_same<ArgType, T>::value,
+                  "ArgType must be 'T' when taking by value!");
+    if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end()))
+      ++EltPtr;
+
+    *I = ::std::forward<ArgType>(*EltPtr);
+    return I;
+  }
+
+public:
+  iterator insert(iterator I, T &&Elt) {
+    return insert_one_impl(I, this->forward_value_param(std::move(Elt)));
+  }
+
+  iterator insert(iterator I, const T &Elt) {
+    return insert_one_impl(I, this->forward_value_param(Elt));
+  }
+
+  iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt) {
+    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+    size_t InsertElt = I - this->begin();
+
+    if (I == this->end()) {  // Important special case for empty vector.
+      append(NumToInsert, Elt);
+      return this->begin()+InsertElt;
+    }
+
+    assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
+
+    // Ensure there is enough space, and get the (maybe updated) address of
+    // Elt.
+    const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumToInsert);
+
+    // Uninvalidate the iterator.
+    I = this->begin()+InsertElt;
+
+    // If there are more elements between the insertion point and the end of the
+    // range than there are being inserted, we can use a simple approach to
+    // insertion.  Since we already reserved space, we know that this won't
+    // reallocate the vector.
+    if (size_t(this->end()-I) >= NumToInsert) {
+      T *OldEnd = this->end();
+      append(std::move_iterator<iterator>(this->end() - NumToInsert),
+             std::move_iterator<iterator>(this->end()));
+
+      // Copy the existing elements that get replaced.
+      std::move_backward(I, OldEnd-NumToInsert, OldEnd);
+
+      // If we just moved the element we're inserting, be sure to update
+      // the reference (never happens if TakesParamByValue).
+      if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
+        EltPtr += NumToInsert;
+
+      std::fill_n(I, NumToInsert, *EltPtr);
+      return I;
+    }
+
+    // Otherwise, we're inserting more elements than exist already, and we're
+    // not inserting at the end.
+
+    // Move over the elements that we're about to overwrite.
+    T *OldEnd = this->end();
+    this->set_size(this->size() + NumToInsert);
+    size_t NumOverwritten = OldEnd-I;
+    this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
+
+    // If we just moved the element we're inserting, be sure to update
+    // the reference (never happens if TakesParamByValue).
+    if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
+      EltPtr += NumToInsert;
+
+    // Replace the overwritten part.
+    std::fill_n(I, NumOverwritten, *EltPtr);
+
+    // Insert the non-overwritten middle part.
+    std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr);
+    return I;
+  }
+
+  template <typename ItTy,
+            typename = std::enable_if_t<std::is_convertible<
+                typename std::iterator_traits<ItTy>::iterator_category,
+                std::input_iterator_tag>::value>>
+  iterator insert(iterator I, ItTy From, ItTy To) {
+    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+    size_t InsertElt = I - this->begin();
+
+    if (I == this->end()) {  // Important special case for empty vector.
+      append(From, To);
+      return this->begin()+InsertElt;
+    }
+
+    assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
+
+    // Check that the reserve that follows doesn't invalidate the iterators.
+    this->assertSafeToAddRange(From, To);
+
+    size_t NumToInsert = std::distance(From, To);
+
+    // Ensure there is enough space.
+    reserve(this->size() + NumToInsert);
+
+    // Uninvalidate the iterator.
+    I = this->begin()+InsertElt;
+
+    // If there are more elements between the insertion point and the end of the
+    // range than there are being inserted, we can use a simple approach to
+    // insertion.  Since we already reserved space, we know that this won't
+    // reallocate the vector.
+    if (size_t(this->end()-I) >= NumToInsert) {
+      T *OldEnd = this->end();
+      append(std::move_iterator<iterator>(this->end() - NumToInsert),
+             std::move_iterator<iterator>(this->end()));
+
+      // Copy the existing elements that get replaced.
+      std::move_backward(I, OldEnd-NumToInsert, OldEnd);
+
+      std::copy(From, To, I);
+      return I;
+    }
+
+    // Otherwise, we're inserting more elements than exist already, and we're
+    // not inserting at the end.
+
+    // Move over the elements that we're about to overwrite.
+    T *OldEnd = this->end();
+    this->set_size(this->size() + NumToInsert);
+    size_t NumOverwritten = OldEnd-I;
+    this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
+
+    // Replace the overwritten part.
+    for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
+      *J = *From;
+      ++J; ++From;
+    }
+
+    // Insert the non-overwritten middle part.
+    this->uninitialized_copy(From, To, OldEnd);
+    return I;
+  }
+
+  void insert(iterator I, std::initializer_list<T> IL) {
+    insert(I, IL.begin(), IL.end());
+  }
+
+  template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) {
+    if (LLVM_UNLIKELY(this->size() >= this->capacity()))
+      return this->growAndEmplaceBack(std::forward<ArgTypes>(Args)...);
+
+    ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
+    this->set_size(this->size() + 1);
+    return this->back();
+  }
+
+  SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
+
+  SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
+
+  bool operator==(const SmallVectorImpl &RHS) const {
+    if (this->size() != RHS.size()) return false;
+    return std::equal(this->begin(), this->end(), RHS.begin());
+  }
+  bool operator!=(const SmallVectorImpl &RHS) const {
+    return !(*this == RHS);
+  }
+
+  bool operator<(const SmallVectorImpl &RHS) const {
+    return std::lexicographical_compare(this->begin(), this->end(),
+                                        RHS.begin(), RHS.end());
+  }
+};
+
+template <typename T>
+void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
+  if (this == &RHS) return;
+
+  // We can only avoid copying elements if neither vector is small.
+  if (!this->isSmall() && !RHS.isSmall()) {
+    std::swap(this->BeginX, RHS.BeginX);
+    std::swap(this->Size, RHS.Size);
+    std::swap(this->Capacity, RHS.Capacity);
+    return;
+  }
+  this->reserve(RHS.size());
+  RHS.reserve(this->size());
+
+  // Swap the shared elements.
+  size_t NumShared = this->size();
+  if (NumShared > RHS.size()) NumShared = RHS.size();
+  for (size_type i = 0; i != NumShared; ++i)
+    std::swap((*this)[i], RHS[i]);
+
+  // Copy over the extra elts.
+  if (this->size() > RHS.size()) {
+    size_t EltDiff = this->size() - RHS.size();
+    this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
+    RHS.set_size(RHS.size() + EltDiff);
+    this->destroy_range(this->begin()+NumShared, this->end());
+    this->set_size(NumShared);
+  } else if (RHS.size() > this->size()) {
+    size_t EltDiff = RHS.size() - this->size();
+    this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
+    this->set_size(this->size() + EltDiff);
+    this->destroy_range(RHS.begin()+NumShared, RHS.end());
+    RHS.set_size(NumShared);
+  }
+}
+
+template <typename T>
+SmallVectorImpl<T> &SmallVectorImpl<T>::
+  operator=(const SmallVectorImpl<T> &RHS) {
+  // Avoid self-assignment.
+  if (this == &RHS) return *this;
+
+  // If we already have sufficient space, assign the common elements, then
+  // destroy any excess.
+  size_t RHSSize = RHS.size();
+  size_t CurSize = this->size();
+  if (CurSize >= RHSSize) {
+    // Assign common elements.
+    iterator NewEnd;
+    if (RHSSize)
+      NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
+    else
+      NewEnd = this->begin();
+
+    // Destroy excess elements.
+    this->destroy_range(NewEnd, this->end());
+
+    // Trim.
+    this->set_size(RHSSize);
+    return *this;
+  }
+
+  // If we have to grow to have enough elements, destroy the current elements.
+  // This allows us to avoid copying them during the grow.
+  // FIXME: don't do this if they're efficiently moveable.
+  if (this->capacity() < RHSSize) {
+    // Destroy current elements.
+    this->clear();
+    CurSize = 0;
+    this->grow(RHSSize);
+  } else if (CurSize) {
+    // Otherwise, use assignment for the already-constructed elements.
+    std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
+  }
+
+  // Copy construct the new elements in place.
+  this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
+                           this->begin()+CurSize);
+
+  // Set end.
+  this->set_size(RHSSize);
+  return *this;
+}
+
+template <typename T>
+SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
+  // Avoid self-assignment.
+  if (this == &RHS) return *this;
+
+  // If the RHS isn't small, clear this vector and then steal its buffer.
+  if (!RHS.isSmall()) {
+    this->assignRemote(std::move(RHS));
+    return *this;
+  }
+
+  // If we already have sufficient space, assign the common elements, then
+  // destroy any excess.
+  size_t RHSSize = RHS.size();
+  size_t CurSize = this->size();
+  if (CurSize >= RHSSize) {
+    // Assign common elements.
+    iterator NewEnd = this->begin();
+    if (RHSSize)
+      NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
+
+    // Destroy excess elements and trim the bounds.
+    this->destroy_range(NewEnd, this->end());
+    this->set_size(RHSSize);
+
+    // Clear the RHS.
+    RHS.clear();
+
+    return *this;
+  }
+
+  // If we have to grow to have enough elements, destroy the current elements.
+  // This allows us to avoid copying them during the grow.
+  // FIXME: this may not actually make any sense if we can efficiently move
+  // elements.
+  if (this->capacity() < RHSSize) {
+    // Destroy current elements.
+    this->clear();
+    CurSize = 0;
+    this->grow(RHSSize);
+  } else if (CurSize) {
+    // Otherwise, use assignment for the already-constructed elements.
+    std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
+  }
+
+  // Move-construct the new elements in place.
+  this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
+                           this->begin()+CurSize);
+
+  // Set end.
+  this->set_size(RHSSize);
+
+  RHS.clear();
+  return *this;
+}
+
+/// Storage for the SmallVector elements.  This is specialized for the N=0 case
+/// to avoid allocating unnecessary storage.
+template <typename T, unsigned N>
+struct SmallVectorStorage {
+  alignas(T) char InlineElts[N * sizeof(T)];
+};
+
+/// We need the storage to be properly aligned even for small-size of 0 so that
+/// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is
+/// well-defined.
+template <typename T> struct alignas(T) SmallVectorStorage<T, 0> {};
+
+/// Forward declaration of SmallVector so that
+/// calculateSmallVectorDefaultInlinedElements can reference
+/// `sizeof(SmallVector<T, 0>)`.
+template <typename T, unsigned N> class LLVM_GSL_OWNER SmallVector;
+
+/// Helper class for calculating the default number of inline elements for
+/// `SmallVector<T>`.
+///
+/// This should be migrated to a constexpr function when our minimum
+/// compiler support is enough for multi-statement constexpr functions.
+template <typename T> struct CalculateSmallVectorDefaultInlinedElements {
+  // Parameter controlling the default number of inlined elements
+  // for `SmallVector<T>`.
+  //
+  // The default number of inlined elements ensures that
+  // 1. There is at least one inlined element.
+  // 2. `sizeof(SmallVector<T>) <= kPreferredSmallVectorSizeof` unless
+  // it contradicts 1.
+  static constexpr size_t kPreferredSmallVectorSizeof = 64;
+
+  // static_assert that sizeof(T) is not "too big".
+  //
+  // Because our policy guarantees at least one inlined element, it is possible
+  // for an arbitrarily large inlined element to allocate an arbitrarily large
+  // amount of inline storage. We generally consider it an antipattern for a
+  // SmallVector to allocate an excessive amount of inline storage, so we want
+  // to call attention to these cases and make sure that users are making an
+  // intentional decision if they request a lot of inline storage.
+  //
+  // We want this assertion to trigger in pathological cases, but otherwise
+  // not be too easy to hit. To accomplish that, the cutoff is actually somewhat
+  // larger than kPreferredSmallVectorSizeof (otherwise,
+  // `SmallVector<SmallVector<T>>` would be one easy way to trip it, and that
+  // pattern seems useful in practice).
+  //
+  // One wrinkle is that this assertion is in theory non-portable, since
+  // sizeof(T) is in general platform-dependent. However, we don't expect this
+  // to be much of an issue, because most LLVM development happens on 64-bit
+  // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for
+  // 32-bit hosts, dodging the issue. The reverse situation, where development
+  // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a
+  // 64-bit host, is expected to be very rare.
+  static_assert(
+      sizeof(T) <= 256,
+      "You are trying to use a default number of inlined elements for "
+      "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
+      "explicit number of inlined elements with `SmallVector<T, N>` to make "
+      "sure you really want that much inline storage.");
+
+  // Discount the size of the header itself when calculating the maximum inline
+  // bytes.
+  static constexpr size_t PreferredInlineBytes =
+      kPreferredSmallVectorSizeof - sizeof(SmallVector<T, 0>);
+  static constexpr size_t NumElementsThatFit = PreferredInlineBytes / sizeof(T);
+  static constexpr size_t value =
+      NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
+};
+
+/// This is a 'vector' (really, a variable-sized array), optimized
+/// for the case when the array is small.  It contains some number of elements
+/// in-place, which allows it to avoid heap allocation when the actual number of
+/// elements is below that threshold.  This allows normal "small" cases to be
+/// fast without losing generality for large inputs.
+///
+/// \note
+/// In the absence of a well-motivated choice for the number of inlined
+/// elements \p N, it is recommended to use \c SmallVector<T> (that is,
+/// omitting the \p N). This will choose a default number of inlined elements
+/// reasonable for allocation on the stack (for example, trying to keep \c
+/// sizeof(SmallVector<T>) around 64 bytes).
+///
+/// \warning This does not attempt to be exception safe.
+///
+/// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h
+template <typename T,
+          unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value>
+class LLVM_GSL_OWNER SmallVector : public SmallVectorImpl<T>,
+                                   SmallVectorStorage<T, N> {
+public:
+  SmallVector() : SmallVectorImpl<T>(N) {}
+
+  ~SmallVector() {
+    // Destroy the constructed elements in the vector.
+    this->destroy_range(this->begin(), this->end());
+  }
+
+  explicit SmallVector(size_t Size, const T &Value = T())
+    : SmallVectorImpl<T>(N) {
+    this->assign(Size, Value);
+  }
+
+  template <typename ItTy,
+            typename = std::enable_if_t<std::is_convertible<
+                typename std::iterator_traits<ItTy>::iterator_category,
+                std::input_iterator_tag>::value>>
+  SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
+    this->append(S, E);
+  }
+
+  template <typename RangeTy>
+  explicit SmallVector(const iterator_range<RangeTy> &R)
+      : SmallVectorImpl<T>(N) {
+    this->append(R.begin(), R.end());
+  }
+
+  SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
+    this->assign(IL);
+  }
+
+  SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
+    if (!RHS.empty())
+      SmallVectorImpl<T>::operator=(RHS);
+  }
+
+  SmallVector &operator=(const SmallVector &RHS) {
+    SmallVectorImpl<T>::operator=(RHS);
+    return *this;
+  }
+
+  SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) {
+    if (!RHS.empty())
+      SmallVectorImpl<T>::operator=(::std::move(RHS));
+  }
+
+  SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
+    if (!RHS.empty())
+      SmallVectorImpl<T>::operator=(::std::move(RHS));
+  }
+
+  SmallVector &operator=(SmallVector &&RHS) {
+    if (N) {
+      SmallVectorImpl<T>::operator=(::std::move(RHS));
+      return *this;
+    }
+    // SmallVectorImpl<T>::operator= does not leverage N==0. Optimize the
+    // case.
+    if (this == &RHS)
+      return *this;
+    if (RHS.empty()) {
+      this->destroy_range(this->begin(), this->end());
+      this->Size = 0;
+    } else {
+      this->assignRemote(std::move(RHS));
+    }
+    return *this;
+  }
+
+  SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
+    SmallVectorImpl<T>::operator=(::std::move(RHS));
+    return *this;
+  }
+
+  SmallVector &operator=(std::initializer_list<T> IL) {
+    this->assign(IL);
+    return *this;
+  }
+};
+
+template <typename T, unsigned N>
+inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
+  return X.capacity_in_bytes();
+}
+
+template <typename RangeType>
+using ValueTypeFromRangeType =
+    typename std::remove_const<typename std::remove_reference<
+        decltype(*std::begin(std::declval<RangeType &>()))>::type>::type;
+
+/// Given a range of type R, iterate the entire range and return a
+/// SmallVector with elements of the vector.  This is useful, for example,
+/// when you want to iterate a range and then sort the results.
+template <unsigned Size, typename R>
+SmallVector<ValueTypeFromRangeType<R>, Size> to_vector(R &&Range) {
+  return {std::begin(Range), std::end(Range)};
+}
+template <typename R>
+SmallVector<ValueTypeFromRangeType<R>,
+            CalculateSmallVectorDefaultInlinedElements<
+                ValueTypeFromRangeType<R>>::value>
+to_vector(R &&Range) {
+  return {std::begin(Range), std::end(Range)};
+}
+
+} // end namespace wpi
+
+namespace std {
+
+  /// Implement std::swap in terms of SmallVector swap.
+  template<typename T>
+  inline void
+  swap(wpi::SmallVectorImpl<T> &LHS, wpi::SmallVectorImpl<T> &RHS) {
+    LHS.swap(RHS);
+  }
+
+  /// Implement std::swap in terms of SmallVector swap.
+  template<typename T, unsigned N>
+  inline void
+  swap(wpi::SmallVector<T, N> &LHS, wpi::SmallVector<T, N> &RHS) {
+    LHS.swap(RHS);
+  }
+
+} // end namespace std
+
+#endif // WPIUTIL_WPI_SMALLVECTOR_H
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallVectorMemoryBuffer.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallVectorMemoryBuffer.h
new file mode 100644
index 0000000..6173714
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SmallVectorMemoryBuffer.h
@@ -0,0 +1,63 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+//===- SmallVectorMemoryBuffer.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a wrapper class to hold the memory into which an
+// object will be generated.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <string>
+#include <string_view>
+#include <utility>
+
+#include "wpi/MemoryBuffer.h"
+#include "wpi/SmallVector.h"
+#include "wpi/raw_ostream.h"
+
+namespace wpi {
+
+/// SmallVector-backed MemoryBuffer instance.
+///
+/// This class enables efficient construction of MemoryBuffers from SmallVector
+/// instances.
+class SmallVectorMemoryBuffer : public MemoryBuffer {
+ public:
+  /// Construct an SmallVectorMemoryBuffer from the given SmallVector
+  /// r-value.
+  SmallVectorMemoryBuffer(SmallVectorImpl<uint8_t>&& sv)  // NOLINT
+      : m_sv(std::move(sv)), m_bufferName("<in-memory object>") {
+    Init(this->m_sv.begin(), this->m_sv.end());
+  }
+
+  /// Construct a named SmallVectorMemoryBuffer from the given
+  /// SmallVector r-value and StringRef.
+  SmallVectorMemoryBuffer(SmallVectorImpl<uint8_t>&& sv, std::string_view name)
+      : m_sv(std::move(sv)), m_bufferName(name) {
+    Init(this->m_sv.begin(), this->m_sv.end());
+  }
+
+  // Key function.
+  ~SmallVectorMemoryBuffer() override;
+
+  std::string_view GetBufferIdentifier() const override { return m_bufferName; }
+
+  BufferKind GetBufferKind() const override { return MemoryBuffer_Malloc; }
+
+ private:
+  SmallVector<uint8_t, 0> m_sv;
+  std::string m_bufferName;
+};
+
+}  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/StringExtras.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringExtras.h
similarity index 97%
rename from wpiutil/src/main/native/include/wpi/StringExtras.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringExtras.h
index 9e70f52..75c637b 100644
--- a/wpiutil/src/main/native/include/wpi/StringExtras.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringExtras.h
@@ -709,4 +709,16 @@
 std::optional<long double> parse_float<long double>(
     std::string_view str) noexcept;
 
+/**
+ * Unescapes a C-style string (reverse operation to raw_ostream::write_escaped).
+ * Scans through @p str until either the end is reached or an unescaped double
+ * quote character is found.
+ *
+ * @param str input string
+ * @param buf buffer for unescaped characters
+ * @return pair of the unescaped string and any remaining input
+ */
+std::pair<std::string_view, std::string_view> UnescapeCString(
+    std::string_view str, SmallVectorImpl<char>& buf);
+
 }  // namespace wpi
diff --git a/wpiutil/src/main/native/include/wpi/StringMap.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMap.h
similarity index 73%
rename from wpiutil/src/main/native/include/wpi/StringMap.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMap.h
index dac2f20..c7da670 100644
--- a/wpiutil/src/main/native/include/wpi/StringMap.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMap.h
@@ -1,51 +1,35 @@
 //===- StringMap.h - String Hash table map interface ------------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-// This file defines the StringMap class.
-//
+///
+/// \file
+/// This file defines the StringMap class.
+///
 //===----------------------------------------------------------------------===//
 
 #ifndef WPIUTIL_WPI_STRINGMAP_H
 #define WPIUTIL_WPI_STRINGMAP_H
 
+#include "wpi/StringMapEntry.h"
+#include "wpi/iterator.h"
+#include "wpi/AllocatorBase.h"
+#include "wpi/MemAlloc.h"
 #include "wpi/SmallVector.h"
 #include "wpi/iterator.h"
 #include "wpi/iterator_range.h"
-#include "wpi/MemAlloc.h"
 #include "wpi/PointerLikeTypeTraits.h"
-#include "wpi/ErrorHandling.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <cstdlib>
-#include <cstring>
 #include <initializer_list>
 #include <iterator>
-#include <string_view>
-#include <utility>
 
 namespace wpi {
 
-template<typename ValueTy> class StringMapConstIterator;
-template<typename ValueTy> class StringMapIterator;
-template<typename ValueTy> class StringMapKeyIterator;
-template<typename ValueTy> class StringMapEntry;
-
-/// StringMapEntryBase - Shared base class of StringMapEntry instances.
-class StringMapEntryBase {
-  size_t StrLen;
-
-public:
-  explicit StringMapEntryBase(size_t Len) : StrLen(Len) {}
-
-  size_t getKeyLength() const { return StrLen; }
-};
+template <typename ValueTy> class StringMapConstIterator;
+template <typename ValueTy> class StringMapIterator;
+template <typename ValueTy> class StringMapKeyIterator;
 
 /// StringMapImpl - This is the base class of StringMap that is shared among
 /// all of its instantiations.
@@ -61,8 +45,7 @@
   unsigned ItemSize;
 
 protected:
-  explicit StringMapImpl(unsigned itemSize)
-      : ItemSize(itemSize) {}
+  explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) {}
   StringMapImpl(StringMapImpl &&RHS) noexcept
       : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets),
         NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones),
@@ -101,10 +84,12 @@
   void init(unsigned Size);
 
 public:
+  static constexpr uintptr_t TombstoneIntVal =
+      static_cast<uintptr_t>(-1)
+      << PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable;
+
   static StringMapEntryBase *getTombstoneVal() {
-    uintptr_t Val = static_cast<uintptr_t>(-1);
-    Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable;
-    return reinterpret_cast<StringMapEntryBase *>(Val);
+    return reinterpret_cast<StringMapEntryBase *>(TombstoneIntVal);
   }
 
   unsigned getNumBuckets() const { return NumBuckets; }
@@ -121,108 +106,41 @@
   }
 };
 
-/// StringMapEntry - This is used to represent one value that is inserted into
-/// a StringMap.  It contains the Value itself and the key: the string length
-/// and data.
-template<typename ValueTy>
-class StringMapEntry : public StringMapEntryBase {
-public:
-  ValueTy second;
-
-  explicit StringMapEntry(size_t strLen)
-    : StringMapEntryBase(strLen), second() {}
-  template <typename... InitTy>
-  StringMapEntry(size_t strLen, InitTy &&... InitVals)
-      : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {}
-  StringMapEntry(StringMapEntry &E) = delete;
-
-  std::string_view getKey() const {
-    return {getKeyData(), getKeyLength()};
-  }
-
-  const ValueTy &getValue() const { return second; }
-  ValueTy &getValue() { return second; }
-
-  void setValue(const ValueTy &V) { second = V; }
-
-  /// getKeyData - Return the start of the string data that is the key for this
-  /// value.  The string data is always stored immediately after the
-  /// StringMapEntry object.
-  const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);}
-
-  std::string_view first() const { return {getKeyData(), getKeyLength()}; }
-
-  /// Create a StringMapEntry for the specified key construct the value using
-  /// \p InitiVals.
-  template <typename... InitTy>
-  static StringMapEntry *Create(std::string_view Key, InitTy &&... InitVals) {
-    size_t KeyLength = Key.size();
-
-    // Allocate a new item with space for the string at the end and a null
-    // terminator.
-    size_t AllocSize = sizeof(StringMapEntry) + KeyLength + 1;
-
-    StringMapEntry *NewItem =
-      static_cast<StringMapEntry*>(safe_malloc(AllocSize));
-
-    // Construct the value.
-    new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...);
-
-    // Copy the string information.
-    char *StrBuffer = const_cast<char*>(NewItem->getKeyData());
-    if (KeyLength > 0)
-      memcpy(StrBuffer, Key.data(), KeyLength);
-    StrBuffer[KeyLength] = 0;  // Null terminate for convenience of clients.
-    return NewItem;
-  }
-
-  static StringMapEntry *Create(std::string_view Key) {
-    return Create(Key, ValueTy());
-  }
-
-  /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
-  /// into a StringMapEntry, return the StringMapEntry itself.
-  static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
-    char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
-    return *reinterpret_cast<StringMapEntry*>(Ptr);
-  }
-
-  /// Destroy - Destroy this StringMapEntry, releasing memory back to the
-  /// specified allocator.
-  void Destroy() {
-    // Free memory referenced by the item.
-    this->~StringMapEntry();
-    std::free(static_cast<void *>(this));
-  }
-};
-
-
 /// StringMap - This is an unconventional map that is specialized for handling
 /// keys that are "strings", which are basically ranges of bytes. This does some
 /// funky memory allocation and hashing things to make it extremely efficient,
 /// storing the string data *after* the value in the map.
-template<typename ValueTy>
+template <typename ValueTy, typename AllocatorTy = MallocAllocator>
 class StringMap : public StringMapImpl {
+  AllocatorTy Allocator;
+
 public:
   using MapEntryTy = StringMapEntry<ValueTy>;
 
   StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
 
   explicit StringMap(unsigned InitialSize)
-    : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
+      : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
+
+  explicit StringMap(AllocatorTy A)
+      : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {
+  }
+
+  StringMap(unsigned InitialSize, AllocatorTy A)
+      : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
+        Allocator(A) {}
 
   StringMap(std::initializer_list<std::pair<std::string_view, ValueTy>> List)
       : StringMapImpl(List.size(), static_cast<unsigned>(sizeof(MapEntryTy))) {
-    for (const auto &P : List) {
-      insert(P);
-    }
+    insert(List);
   }
 
   StringMap(StringMap &&RHS)
-      : StringMapImpl(std::move(RHS)) {}
+      : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {}
 
-  StringMap(const StringMap &RHS) :
-    StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {
+  StringMap(const StringMap &RHS)
+      : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))),
+        Allocator(RHS.Allocator) {
     if (RHS.empty())
       return;
 
@@ -242,7 +160,7 @@
       }
 
       TheTable[I] = MapEntryTy::Create(
-          static_cast<MapEntryTy *>(Bucket)->getKey(),
+          static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator,
           static_cast<MapEntryTy *>(Bucket)->getValue());
       HashTable[I] = RHSHashTable[I];
     }
@@ -257,6 +175,7 @@
 
   StringMap &operator=(StringMap RHS) {
     StringMapImpl::swap(RHS);
+    std::swap(Allocator, RHS.Allocator);
     return *this;
   }
 
@@ -268,14 +187,17 @@
       for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
         StringMapEntryBase *Bucket = TheTable[I];
         if (Bucket && Bucket != getTombstoneVal()) {
-          static_cast<MapEntryTy*>(Bucket)->Destroy();
+          static_cast<MapEntryTy *>(Bucket)->Destroy(Allocator);
         }
       }
     }
     free(TheTable);
   }
 
-  using key_type = const char*;
+  AllocatorTy &getAllocator() { return Allocator; }
+  const AllocatorTy &getAllocator() const { return Allocator; }
+
+  using key_type = const char *;
   using mapped_type = ValueTy;
   using value_type = StringMapEntry<ValueTy>;
   using size_type = size_t;
@@ -283,17 +205,13 @@
   using const_iterator = StringMapConstIterator<ValueTy>;
   using iterator = StringMapIterator<ValueTy>;
 
-  iterator begin() {
-    return iterator(TheTable, NumBuckets == 0);
-  }
-  iterator end() {
-    return iterator(TheTable+NumBuckets, true);
-  }
+  iterator begin() { return iterator(TheTable, NumBuckets == 0); }
+  iterator end() { return iterator(TheTable + NumBuckets, true); }
   const_iterator begin() const {
     return const_iterator(TheTable, NumBuckets == 0);
   }
   const_iterator end() const {
-    return const_iterator(TheTable+NumBuckets, true);
+    return const_iterator(TheTable + NumBuckets, true);
   }
 
   iterator_range<StringMapKeyIterator<ValueTy>> keys() const {
@@ -303,14 +221,16 @@
 
   iterator find(std::string_view Key) {
     int Bucket = FindKey(Key);
-    if (Bucket == -1) return end();
-    return iterator(TheTable+Bucket, true);
+    if (Bucket == -1)
+      return end();
+    return iterator(TheTable + Bucket, true);
   }
 
   const_iterator find(std::string_view Key) const {
     int Bucket = FindKey(Key);
-    if (Bucket == -1) return end();
-    return const_iterator(TheTable+Bucket, true);
+    if (Bucket == -1)
+      return end();
+    return const_iterator(TheTable + Bucket, true);
   }
 
   /// lookup - Return the entry for the specified key, or a default
@@ -327,10 +247,33 @@
   ValueTy &operator[](std::string_view Key) { return try_emplace(Key).first->second; }
 
   /// count - Return 1 if the element is in the map, 0 otherwise.
-  size_type count(std::string_view Key) const {
-    return find(Key) == end() ? 0 : 1;
+  size_type count(std::string_view Key) const { return find(Key) == end() ? 0 : 1; }
+
+  template <typename InputTy>
+  size_type count(const StringMapEntry<InputTy> &MapEntry) const {
+    return count(MapEntry.getKey());
   }
 
+  /// equal - check whether both of the containers are equal.
+  bool operator==(const StringMap &RHS) const {
+    if (size() != RHS.size())
+      return false;
+
+    for (const auto &KeyValue : *this) {
+      auto FindInRHS = RHS.find(KeyValue.getKey());
+
+      if (FindInRHS == RHS.end())
+        return false;
+
+      if (!(KeyValue.getValue() == FindInRHS->getValue()))
+        return false;
+    }
+
+    return true;
+  }
+
+  bool operator!=(const StringMap &RHS) const { return !(*this == RHS); }
+
   /// insert - Insert the specified key/value pair into the map.  If the key
   /// already exists in the map, return false and ignore the request, otherwise
   /// insert it and return true.
@@ -338,7 +281,7 @@
     unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
     StringMapEntryBase *&Bucket = TheTable[BucketNo];
     if (Bucket && Bucket != getTombstoneVal())
-      return false;  // Already exists in map.
+      return false; // Already exists in map.
 
     if (Bucket == getTombstoneVal())
       --NumTombstones;
@@ -358,6 +301,31 @@
     return try_emplace(KV.first, std::move(KV.second));
   }
 
+  /// Inserts elements from range [first, last). If multiple elements in the
+  /// range have keys that compare equivalent, it is unspecified which element
+  /// is inserted .
+  template <typename InputIt> void insert(InputIt First, InputIt Last) {
+    for (InputIt It = First; It != Last; ++It)
+      insert(*It);
+  }
+
+  ///  Inserts elements from initializer list ilist. If multiple elements in
+  /// the range have keys that compare equivalent, it is unspecified which
+  /// element is inserted
+  void insert(std::initializer_list<std::pair<std::string_view, ValueTy>> List) {
+    insert(List.begin(), List.end());
+  }
+
+  /// Inserts an element or assigns to the current element if the key already
+  /// exists. The return type is the same as try_emplace.
+  template <typename V>
+  std::pair<iterator, bool> insert_or_assign(std::string_view Key, V &&Val) {
+    auto Ret = try_emplace(Key, std::forward<V>(Val));
+    if (!Ret.second)
+      Ret.first->second = std::forward<V>(Val);
+    return Ret;
+  }
+
   /// Emplace a new element for the specified key into the map if the key isn't
   /// already in the map. The bool component of the returned pair is true
   /// if and only if the insertion takes place, and the iterator component of
@@ -372,7 +340,7 @@
 
     if (Bucket == getTombstoneVal())
       --NumTombstones;
-    Bucket = MapEntryTy::Create(Key, std::forward<ArgsTy>(Args)...);
+    Bucket = MapEntryTy::Create(Key, Allocator, std::forward<ArgsTy>(Args)...);
     ++NumItems;
     assert(NumItems + NumTombstones <= NumBuckets);
 
@@ -382,14 +350,15 @@
 
   // clear - Empties out the StringMap
   void clear() {
-    if (empty()) return;
+    if (empty())
+      return;
 
     // Zap all values, resetting the keys back to non-present (not tombstone),
     // which is safe because we're removing all elements.
     for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
       StringMapEntryBase *&Bucket = TheTable[I];
       if (Bucket && Bucket != getTombstoneVal()) {
-        static_cast<MapEntryTy*>(Bucket)->Destroy();
+        static_cast<MapEntryTy *>(Bucket)->Destroy(Allocator);
       }
       Bucket = nullptr;
     }
@@ -400,19 +369,18 @@
 
   /// remove - Remove the specified key/value pair from the map, but do not
   /// erase it.  This aborts if the key is not in the map.
-  void remove(MapEntryTy *KeyValue) {
-    RemoveKey(KeyValue);
-  }
+  void remove(MapEntryTy *KeyValue) { RemoveKey(KeyValue); }
 
   void erase(iterator I) {
     MapEntryTy &V = *I;
     remove(&V);
-    V.Destroy();
+    V.Destroy(Allocator);
   }
 
   bool erase(std::string_view Key) {
     iterator I = find(Key);
-    if (I == end()) return false;
+    if (I == end())
+      return false;
     erase(I);
     return true;
   }
@@ -431,7 +399,8 @@
   explicit StringMapIterBase(StringMapEntryBase **Bucket,
                              bool NoAdvance = false)
       : Ptr(Bucket) {
-    if (!NoAdvance) AdvancePastEmptyBuckets();
+    if (!NoAdvance)
+      AdvancePastEmptyBuckets();
   }
 
   DerivedTy &operator=(const DerivedTy &Other) {
@@ -439,13 +408,9 @@
     return static_cast<DerivedTy &>(*this);
   }
 
-#if __cplusplus < 202002L
-  bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
-#else
   friend bool operator==(const DerivedTy &LHS, const DerivedTy &RHS) {
     return LHS.Ptr == RHS.Ptr;
   }
-#endif
 
   DerivedTy &operator++() { // Preincrement
     ++Ptr;
@@ -490,15 +455,13 @@
                                  const StringMapEntry<ValueTy>>;
 
 public:
-  using value_type = const StringMapEntry<ValueTy>;
-
   StringMapConstIterator() = default;
   explicit StringMapConstIterator(StringMapEntryBase **Bucket,
                                   bool NoAdvance = false)
       : base(Bucket, NoAdvance) {}
 
-  value_type &operator*() const {
-    return *static_cast<value_type *>(*this->Ptr);
+  const StringMapEntry<ValueTy> &operator*() const {
+    return *static_cast<const StringMapEntry<ValueTy> *>(*this->Ptr);
   }
 };
 
@@ -509,15 +472,13 @@
       StringMapIterBase<StringMapIterator<ValueTy>, StringMapEntry<ValueTy>>;
 
 public:
-  using value_type = StringMapEntry<ValueTy>;
-
   StringMapIterator() = default;
   explicit StringMapIterator(StringMapEntryBase **Bucket,
                              bool NoAdvance = false)
       : base(Bucket, NoAdvance) {}
 
-  value_type &operator*() const {
-    return *static_cast<value_type *>(*this->Ptr);
+  StringMapEntry<ValueTy> &operator*() const {
+    return *static_cast<StringMapEntry<ValueTy> *>(*this->Ptr);
   }
 
   operator StringMapConstIterator<ValueTy>() const {
@@ -539,13 +500,7 @@
   explicit StringMapKeyIterator(StringMapConstIterator<ValueTy> Iter)
       : base(std::move(Iter)) {}
 
-  std::string_view &operator*() {
-    Key = this->wrapped()->getKey();
-    return Key;
-  }
-
-private:
-  std::string_view Key;
+  std::string_view operator*() const { return this->wrapped()->getKey(); }
 };
 
 template <typename ValueTy>
@@ -635,4 +590,4 @@
 
 } // end namespace wpi
 
-#endif // LLVM_ADT_STRINGMAP_H
+#endif // WPIUTIL_WPI_STRINGMAP_H
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMapEntry.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMapEntry.h
new file mode 100644
index 0000000..2b33aa6
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/StringMapEntry.h
@@ -0,0 +1,153 @@
+//===- StringMapEntry.h - String Hash table map interface -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines the StringMapEntry class - it is intended to be a low
+/// dependency implementation detail of StringMap that is more suitable for
+/// inclusion in public headers than StringMap.h itself is.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_STRINGMAPENTRY_H
+#define WPIUTIL_WPI_STRINGMAPENTRY_H
+
+#include "wpi/MemAlloc.h"
+
+#include <cassert>
+#include <cstring>
+#include <optional>
+#include <string_view>
+
+namespace wpi {
+
+/// StringMapEntryBase - Shared base class of StringMapEntry instances.
+class StringMapEntryBase {
+  size_t keyLength;
+
+public:
+  explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {}
+
+  size_t getKeyLength() const { return keyLength; }
+
+protected:
+  /// Helper to tail-allocate \p Key. It'd be nice to generalize this so it
+  /// could be reused elsewhere, maybe even taking an wpi::function_ref to
+  /// type-erase the allocator and put it in a source file.
+  template <typename AllocatorTy>
+  static void *allocateWithKey(size_t EntrySize, size_t EntryAlign,
+                               std::string_view Key, AllocatorTy &Allocator);
+};
+
+// Define out-of-line to dissuade inlining.
+template <typename AllocatorTy>
+void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign,
+                                          std::string_view Key,
+                                          AllocatorTy &Allocator) {
+  size_t KeyLength = Key.size();
+
+  // Allocate a new item with space for the string at the end and a null
+  // terminator.
+  size_t AllocSize = EntrySize + KeyLength + 1;
+  void *Allocation = Allocator.Allocate(AllocSize, EntryAlign);
+  assert(Allocation && "Unhandled out-of-memory");
+
+  // Copy the string information.
+  char *Buffer = reinterpret_cast<char *>(Allocation) + EntrySize;
+  if (KeyLength > 0)
+    ::memcpy(Buffer, Key.data(), KeyLength);
+  Buffer[KeyLength] = 0; // Null terminate for convenience of clients.
+  return Allocation;
+}
+
+/// StringMapEntryStorage - Holds the value in a StringMapEntry.
+///
+/// Factored out into a separate base class to make it easier to specialize.
+/// This is primarily intended to support StringSet, which doesn't need a value
+/// stored at all.
+template <typename ValueTy>
+class StringMapEntryStorage : public StringMapEntryBase {
+public:
+  ValueTy second;
+
+  explicit StringMapEntryStorage(size_t keyLength)
+      : StringMapEntryBase(keyLength), second() {}
+  template <typename... InitTy>
+  StringMapEntryStorage(size_t keyLength, InitTy &&... initVals)
+      : StringMapEntryBase(keyLength),
+        second(std::forward<InitTy>(initVals)...) {}
+  StringMapEntryStorage(StringMapEntryStorage &e) = delete;
+
+  const ValueTy &getValue() const { return second; }
+  ValueTy &getValue() { return second; }
+
+  void setValue(const ValueTy &V) { second = V; }
+};
+
+template <> class StringMapEntryStorage<std::nullopt_t> : public StringMapEntryBase {
+public:
+  explicit StringMapEntryStorage(size_t keyLength, std::nullopt_t = std::nullopt)
+      : StringMapEntryBase(keyLength) {}
+  StringMapEntryStorage(StringMapEntryStorage &entry) = delete;
+
+  std::nullopt_t getValue() const { return std::nullopt; }
+};
+
+/// StringMapEntry - This is used to represent one value that is inserted into
+/// a StringMap.  It contains the Value itself and the key: the string length
+/// and data.
+template <typename ValueTy>
+class StringMapEntry final : public StringMapEntryStorage<ValueTy> {
+public:
+  using StringMapEntryStorage<ValueTy>::StringMapEntryStorage;
+
+  std::string_view getKey() const {
+    return std::string_view(getKeyData(), this->getKeyLength());
+  }
+
+  /// getKeyData - Return the start of the string data that is the key for this
+  /// value.  The string data is always stored immediately after the
+  /// StringMapEntry object.
+  const char *getKeyData() const {
+    return reinterpret_cast<const char *>(this + 1);
+  }
+
+  std::string_view first() const {
+    return std::string_view(getKeyData(), this->getKeyLength());
+  }
+
+  /// Create a StringMapEntry for the specified key construct the value using
+  /// \p InitiVals.
+  template <typename AllocatorTy, typename... InitTy>
+  static StringMapEntry *Create(std::string_view key, AllocatorTy &allocator,
+                                InitTy &&... initVals) {
+    return new (StringMapEntryBase::allocateWithKey(
+        sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator))
+        StringMapEntry(key.size(), std::forward<InitTy>(initVals)...);
+  }
+
+  /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
+  /// into a StringMapEntry, return the StringMapEntry itself.
+  static StringMapEntry &GetStringMapEntryFromKeyData(const char *keyData) {
+    char *ptr = const_cast<char *>(keyData) - sizeof(StringMapEntry<ValueTy>);
+    return *reinterpret_cast<StringMapEntry *>(ptr);
+  }
+
+  /// Destroy - Destroy this StringMapEntry, releasing memory back to the
+  /// specified allocator.
+  template <typename AllocatorTy> void Destroy(AllocatorTy &allocator) {
+    // Free memory referenced by the item.
+    size_t AllocSize = sizeof(StringMapEntry) + this->getKeyLength() + 1;
+    this->~StringMapEntry();
+    allocator.Deallocate(static_cast<void *>(this), AllocSize,
+                         alignof(StringMapEntry));
+  }
+};
+
+} // end namespace wpi
+
+#endif // WPIUTIL_WPI_STRINGMAPENTRY_H
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SwapByteOrder.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SwapByteOrder.h
new file mode 100644
index 0000000..ab2791a
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/SwapByteOrder.h
@@ -0,0 +1,165 @@
+//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares generic and optimized functions to swap the byte order of
+// an integral type.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_SWAPBYTEORDER_H
+#define WPIUTIL_WPI_SWAPBYTEORDER_H
+
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+#if defined(_MSC_VER) && !defined(_DEBUG)
+#include <stdlib.h>
+#endif
+
+#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) ||            \
+    defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
+#include <endian.h>
+#elif defined(_AIX)
+#include <sys/machine.h>
+#elif defined(__sun)
+/* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
+#include <sys/types.h>
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+#if defined(_BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#elif defined(__MVS__)
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#if !defined(BYTE_ORDER) && !defined(_WIN32)
+#include <machine/endian.h>
+#endif
+#endif
+
+namespace wpi {
+
+/// ByteSwap_16 - This function returns a byte-swapped representation of
+/// the 16-bit argument.
+inline uint16_t ByteSwap_16(uint16_t value) {
+#if defined(_MSC_VER) && !defined(_DEBUG)
+  // The DLL version of the runtime lacks these functions (bug!?), but in a
+  // release build they're replaced with BSWAP instructions anyway.
+  return _byteswap_ushort(value);
+#else
+  uint16_t Hi = value << 8;
+  uint16_t Lo = value >> 8;
+  return Hi | Lo;
+#endif
+}
+
+/// This function returns a byte-swapped representation of the 32-bit argument.
+inline uint32_t ByteSwap_32(uint32_t value) {
+#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
+  return __builtin_bswap32(value);
+#elif defined(_MSC_VER) && !defined(_DEBUG)
+  return _byteswap_ulong(value);
+#else
+  uint32_t Byte0 = value & 0x000000FF;
+  uint32_t Byte1 = value & 0x0000FF00;
+  uint32_t Byte2 = value & 0x00FF0000;
+  uint32_t Byte3 = value & 0xFF000000;
+  return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
+#endif
+}
+
+/// This function returns a byte-swapped representation of the 64-bit argument.
+inline uint64_t ByteSwap_64(uint64_t value) {
+#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
+  return __builtin_bswap64(value);
+#elif defined(_MSC_VER) && !defined(_DEBUG)
+  return _byteswap_uint64(value);
+#else
+  uint64_t Hi = ByteSwap_32(uint32_t(value));
+  uint32_t Lo = ByteSwap_32(uint32_t(value >> 32));
+  return (Hi << 32) | Lo;
+#endif
+}
+
+namespace sys {
+
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+constexpr bool IsBigEndianHost = true;
+#else
+constexpr bool IsBigEndianHost = false;
+#endif
+
+static const bool IsLittleEndianHost = !IsBigEndianHost;
+
+inline unsigned char  getSwappedBytes(unsigned char C) { return C; }
+inline   signed char  getSwappedBytes(signed char C) { return C; }
+inline          char  getSwappedBytes(char C) { return C; }
+
+inline unsigned short getSwappedBytes(unsigned short C) { return ByteSwap_16(C); }
+inline   signed short getSwappedBytes(  signed short C) { return ByteSwap_16(C); }
+
+inline unsigned int   getSwappedBytes(unsigned int   C) { return ByteSwap_32(C); }
+inline   signed int   getSwappedBytes(  signed int   C) { return ByteSwap_32(C); }
+
+inline unsigned long getSwappedBytes(unsigned long C) {
+  // Handle LLP64 and LP64 platforms.
+  return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
+                                     : ByteSwap_64((uint64_t)C);
+}
+inline signed long getSwappedBytes(signed long C) {
+  // Handle LLP64 and LP64 platforms.
+  return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
+                                     : ByteSwap_64((uint64_t)C);
+}
+
+inline unsigned long long getSwappedBytes(unsigned long long C) {
+  return ByteSwap_64(C);
+}
+inline signed long long getSwappedBytes(signed long long C) {
+  return ByteSwap_64(C);
+}
+
+inline float getSwappedBytes(float C) {
+  union {
+    uint32_t i;
+    float f;
+  } in, out;
+  in.f = C;
+  out.i = ByteSwap_32(in.i);
+  return out.f;
+}
+
+inline double getSwappedBytes(double C) {
+  union {
+    uint64_t i;
+    double d;
+  } in, out;
+  in.d = C;
+  out.i = ByteSwap_64(in.i);
+  return out.d;
+}
+
+template <typename T>
+inline std::enable_if_t<std::is_enum<T>::value, T> getSwappedBytes(T C) {
+  return static_cast<T>(
+      getSwappedBytes(static_cast<std::underlying_type_t<T>>(C)));
+}
+
+template<typename T>
+inline void swapByteOrder(T &Value) {
+  Value = getSwappedBytes(Value);
+}
+
+} // end namespace sys
+} // end namespace wpi
+
+#endif
diff --git a/wpiutil/src/main/native/include/wpi/VersionTuple.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/VersionTuple.h
similarity index 82%
rename from wpiutil/src/main/native/include/wpi/VersionTuple.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/VersionTuple.h
index 59df41c..c08ff37 100644
--- a/wpiutil/src/main/native/include/wpi/VersionTuple.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/VersionTuple.h
@@ -1,9 +1,8 @@
 //===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 ///
@@ -15,10 +14,14 @@
 #ifndef WPIUTIL_WPI_VERSIONTUPLE_H
 #define WPIUTIL_WPI_VERSIONTUPLE_H
 
+#include "wpi/DenseMapInfo.h"
+#include "wpi/Hashing.h"
 #include <optional>
 #include <string>
+#include <tuple>
 
 namespace wpi {
+class raw_ostream;
 
 /// Represents a version number in the form major[.minor[.subminor[.build]]].
 class VersionTuple {
@@ -85,6 +88,27 @@
     return Build;
   }
 
+  /// Return a version tuple that contains only the first 3 version components.
+  VersionTuple withoutBuild() const {
+    if (HasBuild)
+      return VersionTuple(Major, Minor, Subminor);
+    return *this;
+  }
+
+  /// Return a version tuple that contains only components that are non-zero.
+  VersionTuple normalize() const {
+    VersionTuple Result = *this;
+    if (Result.Build == 0) {
+      Result.HasBuild = false;
+      if (Result.Subminor == 0) {
+        Result.HasSubminor = false;
+        if (Result.Minor == 0)
+          Result.HasMinor = false;
+      }
+    }
+    return Result;
+  }
+
   /// Determine if two version numbers are equivalent. If not
   /// provided, minor and subminor version numbers are considered to be zero.
   friend bool operator==(const VersionTuple &X, const VersionTuple &Y) {
diff --git a/wpiutil/src/main/native/include/wpi/WindowsError.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/WindowsError.h
similarity index 62%
rename from wpiutil/src/main/native/include/wpi/WindowsError.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/WindowsError.h
index 565e2b7..54a5236 100644
--- a/wpiutil/src/main/native/include/wpi/WindowsError.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/WindowsError.h
@@ -1,9 +1,8 @@
 //===-- WindowsError.h - Support for mapping windows errors to posix-------===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 
diff --git a/wpiutil/src/main/native/include/wpi/function_ref.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/function_ref.h
similarity index 100%
rename from wpiutil/src/main/native/include/wpi/function_ref.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/function_ref.h
diff --git a/wpiutil/src/main/native/include/wpi/iterator.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/iterator.h
similarity index 77%
rename from wpiutil/src/main/native/include/wpi/iterator.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/iterator.h
index 70bbdab..f959fac 100644
--- a/wpiutil/src/main/native/include/wpi/iterator.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/iterator.h
@@ -1,9 +1,8 @@
 //===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 
@@ -11,7 +10,6 @@
 #define WPIUTIL_WPI_ITERATOR_H
 
 #include "wpi/iterator_range.h"
-#include <algorithm>
 #include <cstddef>
 #include <iterator>
 #include <type_traits>
@@ -37,6 +35,21 @@
 /// terms of addition of one. These aren't equivalent for all iterator
 /// categories, and respecting that adds a lot of complexity for little gain.
 ///
+/// Iterators are expected to have const rules analogous to pointers, with a
+/// single, const-qualified operator*() that returns ReferenceT. This matches
+/// the second and third pointers in the following example:
+/// \code
+///   int Value;
+///   { int *I = &Value; }             // ReferenceT 'int&'
+///   { int *const I = &Value; }       // ReferenceT 'int&'; const
+///   { const int *I = &Value; }       // ReferenceT 'const int&'
+///   { const int *const I = &Value; } // ReferenceT 'const int&'; const
+/// \endcode
+/// If an iterator facade returns a handle to its own state, then T (and
+/// PointerT and ReferenceT) should usually be const-qualified. Otherwise, if
+/// clients are expected to modify the handle itself, the field can be declared
+/// mutable or use const_cast.
+///
 /// Classes wishing to use `iterator_facade_base` should implement the following
 /// methods:
 ///
@@ -44,8 +57,7 @@
 ///   (All of the following methods)
 ///   - DerivedT &operator=(const DerivedT &R);
 ///   - bool operator==(const DerivedT &R) const;
-///   - const T &operator*() const;
-///   - T &operator*();
+///   - T &operator*() const;
 ///   - DerivedT &operator++();
 ///
 /// Bidirectional Iterators:
@@ -65,9 +77,14 @@
 template <typename DerivedT, typename IteratorCategoryT, typename T,
           typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *,
           typename ReferenceT = T &>
-class iterator_facade_base
-    : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT,
-                           ReferenceT> {
+class iterator_facade_base {
+public:
+  using iterator_category = IteratorCategoryT;
+  using value_type = T;
+  using difference_type = DifferenceTypeT;
+  using pointer = PointerT;
+  using reference = ReferenceT;
+
 protected:
   enum {
     IsRandomAccess = std::is_base_of<std::random_access_iterator_tag,
@@ -92,6 +109,22 @@
     operator ReferenceT() const { return *I; }
   };
 
+  /// A proxy object for computing a pointer via indirecting a copy of a
+  /// reference. This is used in APIs which need to produce a pointer but for
+  /// which the reference might be a temporary. The proxy preserves the
+  /// reference internally and exposes the pointer via a arrow operator.
+  class PointerProxy {
+    friend iterator_facade_base;
+
+    ReferenceT R;
+
+    template <typename RefT>
+    PointerProxy(RefT &&R) : R(std::forward<RefT>(R)) {}
+
+  public:
+    PointerT operator->() const { return &R; }
+  };
+
 public:
   DerivedT operator+(DifferenceTypeT n) const {
     static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
@@ -143,43 +176,39 @@
     return tmp;
   }
 
+#ifndef __cpp_impl_three_way_comparison
   bool operator!=(const DerivedT &RHS) const {
-    return !static_cast<const DerivedT *>(this)->operator==(RHS);
+    return !(static_cast<const DerivedT &>(*this) == RHS);
   }
+#endif
 
   bool operator>(const DerivedT &RHS) const {
     static_assert(
         IsRandomAccess,
         "Relational operators are only defined for random access iterators.");
-    return !static_cast<const DerivedT *>(this)->operator<(RHS) &&
-           !static_cast<const DerivedT *>(this)->operator==(RHS);
+    return !(static_cast<const DerivedT &>(*this) < RHS) &&
+           !(static_cast<const DerivedT &>(*this) == RHS);
   }
   bool operator<=(const DerivedT &RHS) const {
     static_assert(
         IsRandomAccess,
         "Relational operators are only defined for random access iterators.");
-    return !static_cast<const DerivedT *>(this)->operator>(RHS);
+    return !(static_cast<const DerivedT &>(*this) > RHS);
   }
   bool operator>=(const DerivedT &RHS) const {
     static_assert(
         IsRandomAccess,
         "Relational operators are only defined for random access iterators.");
-    return !static_cast<const DerivedT *>(this)->operator<(RHS);
+    return !(static_cast<const DerivedT &>(*this) < RHS);
   }
 
-  PointerT operator->() { return &static_cast<DerivedT *>(this)->operator*(); }
-  PointerT operator->() const {
-    return &static_cast<const DerivedT *>(this)->operator*();
-  }
-  ReferenceProxy operator[](DifferenceTypeT n) {
-    static_assert(IsRandomAccess,
-                  "Subscripting is only defined for random access iterators.");
-    return ReferenceProxy(static_cast<DerivedT *>(this)->operator+(n));
+  PointerProxy operator->() const {
+    return static_cast<const DerivedT *>(this)->operator*();
   }
   ReferenceProxy operator[](DifferenceTypeT n) const {
     static_assert(IsRandomAccess,
                   "Subscripting is only defined for random access iterators.");
-    return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n));
+    return static_cast<const DerivedT *>(this)->operator+(n);
   }
 };
 
@@ -195,14 +224,14 @@
     typename T = typename std::iterator_traits<WrappedIteratorT>::value_type,
     typename DifferenceTypeT =
         typename std::iterator_traits<WrappedIteratorT>::difference_type,
-    typename PointerT = typename std::conditional<
+    typename PointerT = std::conditional_t<
         std::is_same<T, typename std::iterator_traits<
                             WrappedIteratorT>::value_type>::value,
-        typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type,
-    typename ReferenceT = typename std::conditional<
+        typename std::iterator_traits<WrappedIteratorT>::pointer, T *>,
+    typename ReferenceT = std::conditional_t<
         std::is_same<T, typename std::iterator_traits<
                             WrappedIteratorT>::value_type>::value,
-        typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type>
+        typename std::iterator_traits<WrappedIteratorT>::reference, T &>>
 class iterator_adaptor_base
     : public iterator_facade_base<DerivedT, IteratorCategoryT, T,
                                   DifferenceTypeT, PointerT, ReferenceT> {
@@ -261,12 +290,16 @@
     return *static_cast<DerivedT *>(this);
   }
 
-  bool operator==(const DerivedT &RHS) const { return I == RHS.I; }
-  bool operator<(const DerivedT &RHS) const {
+  friend bool operator==(const iterator_adaptor_base &LHS,
+                         const iterator_adaptor_base &RHS) {
+    return LHS.I == RHS.I;
+  }
+  friend bool operator<(const iterator_adaptor_base &LHS,
+                        const iterator_adaptor_base &RHS) {
     static_assert(
         BaseT::IsRandomAccess,
         "Relational operators are only defined for random access iterators.");
-    return I < RHS.I;
+    return LHS.I < RHS.I;
   }
 
   ReferenceT operator*() const { return *I; }
@@ -282,8 +315,8 @@
 ///   using iterator = pointee_iterator<SmallVectorImpl<T *>::iterator>;
 /// \endcode
 template <typename WrappedIteratorT,
-          typename T = typename std::remove_reference<
-              decltype(**std::declval<WrappedIteratorT>())>::type>
+          typename T = std::remove_reference_t<decltype(
+              **std::declval<WrappedIteratorT>())>>
 struct pointee_iterator
     : iterator_adaptor_base<
           pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT,
@@ -321,8 +354,7 @@
   explicit pointer_iterator(WrappedIteratorT u)
       : pointer_iterator::iterator_adaptor_base(std::move(u)) {}
 
-  T &operator*() { return Ptr = &*this->I; }
-  const T &operator*() const { return Ptr = &*this->I; }
+  T &operator*() const { return Ptr = &*this->I; }
 };
 
 template <typename RangeT, typename WrappedIteratorT =
@@ -334,6 +366,13 @@
                     PointerIteratorT(std::end(std::forward<RangeT>(Range))));
 }
 
+template <typename WrappedIteratorT,
+          typename T1 = std::remove_reference_t<decltype(
+              **std::declval<WrappedIteratorT>())>,
+          typename T2 = std::add_pointer_t<T1>>
+using raw_pointer_iterator =
+    pointer_iterator<pointee_iterator<WrappedIteratorT, T1>, T2>;
+
 } // end namespace wpi
 
-#endif // LLVM_ADT_ITERATOR_H
+#endif // WPIUTIL_WPI_ITERATOR_H
diff --git a/wpiutil/src/main/native/include/wpi/iterator_range.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/iterator_range.h
similarity index 82%
rename from wpiutil/src/main/native/include/wpi/iterator_range.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/iterator_range.h
index 78a60c2..ce0e4ee 100644
--- a/wpiutil/src/main/native/include/wpi/iterator_range.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/iterator_range.h
@@ -1,9 +1,8 @@
 //===- iterator_range.h - A range adaptor for iterators ---------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 /// \file
@@ -19,7 +18,6 @@
 #ifndef WPIUTIL_WPI_ITERATOR_RANGE_H
 #define WPIUTIL_WPI_ITERATOR_RANGE_H
 
-#include <iterator>
 #include <utility>
 
 namespace wpi {
@@ -45,6 +43,7 @@
 
   IteratorT begin() const { return begin_iterator; }
   IteratorT end() const { return end_iterator; }
+  bool empty() const { return begin_iterator == end_iterator; }
 };
 
 /// Convenience function for iterating over sub-ranges.
@@ -59,11 +58,6 @@
   return iterator_range<T>(std::move(p.first), std::move(p.second));
 }
 
-template <typename T>
-iterator_range<decltype(adl_begin(std::declval<T>()))> drop_begin(T &&t,
-                                                                  int n) {
-  return make_range(std::next(adl_begin(t), n), adl_end(t));
-}
 }
 
 #endif
diff --git a/wpiutil/src/main/native/include/wpi/raw_os_ostream.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/raw_os_ostream.h
similarity index 84%
rename from wpiutil/src/main/native/include/wpi/raw_os_ostream.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/raw_os_ostream.h
index 4335e02..87cd596 100644
--- a/wpiutil/src/main/native/include/wpi/raw_os_ostream.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/raw_os_ostream.h
@@ -1,9 +1,8 @@
 //===- raw_os_ostream.h - std::ostream adaptor for raw_ostream --*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
diff --git a/wpiutil/src/main/native/include/wpi/raw_ostream.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/raw_ostream.h
similarity index 74%
rename from wpiutil/src/main/native/include/wpi/raw_ostream.h
rename to wpiutil/src/main/native/thirdparty/llvm/include/wpi/raw_ostream.h
index 84ec925..350262b 100644
--- a/wpiutil/src/main/native/include/wpi/raw_ostream.h
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/raw_ostream.h
@@ -1,9 +1,8 @@
 //===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===//
 //
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
 //
@@ -15,20 +14,25 @@
 #define WPIUTIL_WPI_RAW_OSTREAM_H
 
 #include "wpi/SmallVector.h"
-#include "wpi/span.h"
+#include <span>
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
 #include <string>
+#if __cplusplus > 201402L
 #include <string_view>
-#include <vector>
+#endif
 #include <system_error>
+#include <type_traits>
+#include <vector>
+
 
 namespace fs {
 enum FileAccess : unsigned;
 enum OpenFlags : unsigned;
 enum CreationDisposition : unsigned;
+class FileLocker;
 } // end namespace fs
 
 namespace wpi {
@@ -38,7 +42,16 @@
 /// buffered disciplines etc. It is a simple buffer that outputs
 /// a chunk at a time.
 class raw_ostream {
+public:
+  // Class kinds to support LLVM-style RTTI.
+  enum class OStreamKind {
+    OK_OStream,
+    OK_FDStream,
+  };
+
 private:
+  OStreamKind Kind;
+
   /// The buffer is handled in such a way that the buffer is
   /// uninitialized, unbuffered, or out of space when OutBufCur >=
   /// OutBufEnd. Thus a single comparison suffices to determine if we
@@ -59,7 +72,11 @@
   /// this buffer.
   char *OutBufStart, *OutBufEnd, *OutBufCur;
 
-  enum BufferKind {
+  /// Optional stream this stream is tied to. If this stream is written to, the
+  /// tied-to stream will be flushed first.
+  raw_ostream *TiedStream = nullptr;
+
+  enum class BufferKind {
     Unbuffered = 0,
     InternalBuffer,
     ExternalBuffer
@@ -67,7 +84,7 @@
 
 public:
   // color order matches ANSI escape sequence, don't change
-  enum Colors {
+  enum class Colors {
     BLACK = 0,
     RED,
     GREEN,
@@ -76,11 +93,25 @@
     MAGENTA,
     CYAN,
     WHITE,
-    SAVEDCOLOR
+    SAVEDCOLOR,
+    RESET,
   };
 
-  explicit raw_ostream(bool unbuffered = false)
-      : BufferMode(unbuffered ? Unbuffered : InternalBuffer) {
+  static constexpr Colors BLACK = Colors::BLACK;
+  static constexpr Colors RED = Colors::RED;
+  static constexpr Colors GREEN = Colors::GREEN;
+  static constexpr Colors YELLOW = Colors::YELLOW;
+  static constexpr Colors BLUE = Colors::BLUE;
+  static constexpr Colors MAGENTA = Colors::MAGENTA;
+  static constexpr Colors CYAN = Colors::CYAN;
+  static constexpr Colors WHITE = Colors::WHITE;
+  static constexpr Colors SAVEDCOLOR = Colors::SAVEDCOLOR;
+  static constexpr Colors RESET = Colors::RESET;
+
+  explicit raw_ostream(bool unbuffered = false,
+                       OStreamKind K = OStreamKind::OK_OStream)
+      : Kind(K), BufferMode(unbuffered ? BufferKind::Unbuffered
+                                       : BufferKind::InternalBuffer) {
     // Start out ready to flush.
     OutBufStart = OutBufEnd = OutBufCur = nullptr;
   }
@@ -93,10 +124,19 @@
   /// tell - Return the current offset with the file.
   uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); }
 
+  OStreamKind get_kind() const { return Kind; }
+
   //===--------------------------------------------------------------------===//
   // Configuration Interface
   //===--------------------------------------------------------------------===//
 
+  /// If possible, pre-allocate \p ExtraSize bytes for stream data.
+  /// i.e. it extends internal buffers to keep additional ExtraSize bytes.
+  /// So that the stream could keep at least tell() + ExtraSize bytes
+  /// without re-allocations. reserveExtraSpace() does not change
+  /// the size/data of the stream.
+  virtual void reserveExtraSpace(uint64_t ExtraSize) {}
+
   /// Set the stream to be buffered, with an automatically determined buffer
   /// size.
   void SetBuffered();
@@ -104,13 +144,13 @@
   /// Set the stream to be buffered, using the specified buffer size.
   void SetBufferSize(size_t Size) {
     flush();
-    SetBufferAndMode(new char[Size], Size, InternalBuffer);
+    SetBufferAndMode(new char[Size], Size, BufferKind::InternalBuffer);
   }
 
   size_t GetBufferSize() const {
     // If we're supposed to be buffered but haven't actually gotten around
     // to allocating the buffer yet, return the value that would be used.
-    if (BufferMode != Unbuffered && OutBufStart == nullptr)
+    if (BufferMode != BufferKind::Unbuffered && OutBufStart == nullptr)
       return preferred_buffer_size();
 
     // Otherwise just return the size of the allocated buffer.
@@ -122,7 +162,7 @@
   /// when the stream is being set to unbuffered.
   void SetUnbuffered() {
     flush();
-    SetBufferAndMode(nullptr, 0, Unbuffered);
+    SetBufferAndMode(nullptr, 0, BufferKind::Unbuffered);
   }
 
   size_t GetNumBytesInBuffer() const {
@@ -159,7 +199,7 @@
     return *this;
   }
 
-  raw_ostream &operator<<(span<const uint8_t> Arr) {
+  raw_ostream &operator<<(std::span<const uint8_t> Arr) {
     // Inline fast path, particularly for arrays with a known length.
     size_t Size = Arr.size();
 
@@ -237,9 +277,8 @@
   /// @param Bold bold/brighter text, default false
   /// @param BG if true change the background, default: change foreground
   /// @returns itself so it can be used within << invocations
-  virtual raw_ostream &changeColor(enum Colors Color,
-                                   bool Bold = false,
-                                   bool BG = false) {
+  virtual raw_ostream &changeColor(enum Colors Color, bool Bold = false,
+                                   bool BG = false)  {
     (void)Color;
     (void)Bold;
     (void)BG;
@@ -259,8 +298,19 @@
   virtual bool is_displayed() const { return false; }
 
   /// This function determines if this stream is displayed and supports colors.
+  /// The result is unaffected by calls to enable_color().
   virtual bool has_colors() const { return is_displayed(); }
 
+  // Enable or disable colors. Once enable_colors(false) is called,
+  // changeColor() has no effect until enable_colors(true) is called.
+  virtual void enable_colors(bool /*enable*/) {}
+
+  bool colors_enabled() const { return false; }
+
+  /// Tie this stream to the specified stream. Replaces any existing tied-to
+  /// stream. Specifying a nullptr unties the stream.
+  void tie(raw_ostream *TieTo) { TiedStream = TieTo; }
+
   //===--------------------------------------------------------------------===//
   // Subclass Interface
   //===--------------------------------------------------------------------===//
@@ -281,9 +331,6 @@
   /// \invariant { Size > 0 }
   virtual void write_impl(const char *Ptr, size_t Size) = 0;
 
-  // An out of line virtual method to provide a home for the class vtable.
-  virtual void handle();
-
   /// Return the current position within the stream, not counting the bytes
   /// currently in the buffer.
   virtual uint64_t current_pos() const = 0;
@@ -293,7 +340,7 @@
   /// use only by subclasses which can arrange for the output to go directly
   /// into the desired output buffer, instead of being copied on each flush.
   void SetBuffer(char *BufferStart, size_t Size) {
-    SetBufferAndMode(BufferStart, Size, ExternalBuffer);
+    SetBufferAndMode(BufferStart, Size, BufferKind::ExternalBuffer);
   }
 
   /// Return an efficient buffer size for the underlying output mechanism.
@@ -318,9 +365,23 @@
   /// unused bytes in the buffer.
   void copy_to_buffer(const char *Ptr, size_t Size);
 
+  /// Flush the tied-to stream (if present) and then write the required data.
+  void flush_tied_then_write(const char *Ptr, size_t Size);
+
   virtual void anchor();
 };
 
+/// Call the appropriate insertion operator, given an rvalue reference to a
+/// raw_ostream object and return a stream of the same type as the argument.
+template <typename OStream, typename T>
+std::enable_if_t<!std::is_reference<OStream>::value &&
+                     std::is_base_of<raw_ostream, OStream>::value,
+                 OStream &&>
+operator<<(OStream &&OS, const T &Value) {
+  OS << Value;
+  return std::move(OS);
+}
+
 /// An abstract base class for streams implementations that also support a
 /// pwrite operation. This is useful for code that can mostly stream out data,
 /// but needs to patch in a header that needs to know the output size.
@@ -329,10 +390,11 @@
   void anchor() override;
 
 public:
-  explicit raw_pwrite_stream(bool Unbuffered = false)
-      : raw_ostream(Unbuffered) {}
+  explicit raw_pwrite_stream(bool Unbuffered = false,
+                             OStreamKind K = OStreamKind::OK_OStream)
+      : raw_ostream(Unbuffered, K) {}
   void pwrite(const char *Ptr, size_t Size, uint64_t Offset) {
-#ifndef NDBEBUG
+#ifndef NDEBUG
     uint64_t Pos = tell();
     // /dev/null always reports a pos of 0, so we cannot perform this check
     // in that case.
@@ -352,8 +414,8 @@
 class raw_fd_ostream : public raw_pwrite_stream {
   int FD;
   bool ShouldClose;
-
-  bool SupportsSeeking;
+  bool SupportsSeeking = false;
+  bool IsRegularFile = false;
 
 #ifdef _WIN32
   /// True if this fd refers to a Windows console device. Mintty and other
@@ -363,7 +425,7 @@
 
   std::error_code EC;
 
-  uint64_t pos;
+  uint64_t pos = 0;
 
   /// See raw_ostream::write_impl.
   void write_impl(const char *Ptr, size_t Size) override;
@@ -377,10 +439,17 @@
   /// Determine an efficient buffer size.
   size_t preferred_buffer_size() const override;
 
+  void anchor() override;
+
+protected:
   /// Set the flag indicating that an output error has been encountered.
   void error_detected(std::error_code EC) { this->EC = EC; }
 
-  void anchor() override;
+  /// Return the file descriptor.
+  int get_fd() const { return FD; }
+
+  // Update the file position by increasing \p Delta.
+  void inc_pos(uint64_t Delta) { pos += Delta; }
 
 public:
   /// Open the specified file for writing. If an error occurs, information
@@ -405,7 +474,8 @@
   /// FD is the file descriptor that this writes to.  If ShouldClose is true,
   /// this closes the file when the stream is destroyed. If FD is for stdout or
   /// stderr, it will not be closed.
-  raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false);
+  raw_fd_ostream(int fd, bool shouldClose, bool unbuffered = false,
+                 OStreamKind K = OStreamKind::OK_OStream);
 
   ~raw_fd_ostream() override;
 
@@ -413,7 +483,9 @@
   /// fsync.
   void close();
 
-  bool supportsSeeking() { return SupportsSeeking; }
+  bool supportsSeeking() const { return SupportsSeeking; }
+
+  bool isRegularFile() const { return IsRegularFile; }
 
   /// Flushes the stream and repositions the underlying file descriptor position
   /// to the offset specified from the beginning of the file.
@@ -439,23 +511,46 @@
   void clear_error() { EC = std::error_code(); }
 };
 
-/// This returns a reference to a raw_ostream for standard output. Use it like:
-/// outs() << "foo" << "bar";
-raw_ostream &outs();
+/// This returns a reference to a raw_fd_ostream for standard output. Use it
+/// like: outs() << "foo" << "bar";
+raw_fd_ostream &outs();
 
-/// This returns a reference to a raw_ostream for standard error. Use it like:
-/// errs() << "foo" << "bar";
-raw_ostream &errs();
+/// This returns a reference to a raw_ostream for standard error.
+/// Use it like: errs() << "foo" << "bar";
+/// By default, the stream is tied to stdout to ensure stdout is flushed before
+/// stderr is written, to ensure the error messages are written in their
+/// expected place.
+raw_fd_ostream &errs();
 
 /// This returns a reference to a raw_ostream which simply discards output.
 raw_ostream &nulls();
 
 //===----------------------------------------------------------------------===//
+// File Streams
+//===----------------------------------------------------------------------===//
+
+/// A raw_ostream of a file for reading/writing/seeking.
+///
+class raw_fd_stream : public raw_fd_ostream {
+public:
+  /// Open the specified file for reading/writing/seeking. If an error occurs,
+  /// information about the error is put into EC, and the stream should be
+  /// immediately destroyed.
+  raw_fd_stream(std::string_view Filename, std::error_code &EC);
+
+  /// Check if \p OS is a pointer of type raw_fd_stream*.
+  static bool classof(const raw_ostream *OS);
+};
+
+//===----------------------------------------------------------------------===//
 // Output Stream Adaptors
 //===----------------------------------------------------------------------===//
 
 /// A raw_ostream that writes to an std::string.  This is a simple adaptor
 /// class. This class does not encounter output errors.
+/// raw_string_ostream operates without a buffer, delegating all memory
+/// management to the std::string. Thus the std::string is always up-to-date,
+/// may be used directly and there is no need to call flush().
 class raw_string_ostream : public raw_ostream {
   std::string &OS;
 
@@ -467,14 +562,17 @@
   uint64_t current_pos() const override { return OS.size(); }
 
 public:
-  explicit raw_string_ostream(std::string &O) : OS(O) {}
-  ~raw_string_ostream() override;
+  explicit raw_string_ostream(std::string &O) : OS(O) {
+    SetUnbuffered();
+  }
 
-  /// Flushes the stream contents to the target string and returns  the string's
-  /// reference.
-  std::string& str() {
-    flush();
-    return OS;
+  /// Returns the string's reference. In most cases it is better to simply use
+  /// the underlying std::string directly.
+  /// TODO: Consider removing this API.
+  std::string &str() { return OS; }
+
+  void reserveExtraSpace(uint64_t ExtraSize) override {
+    OS.reserve(tell() + ExtraSize);
   }
 };
 
@@ -508,7 +606,11 @@
   void flush() = delete;
 
   /// Return a std::string_view for the vector contents.
-  std::string_view str() { return std::string_view(OS.data(), OS.size()); }
+  std::string_view str() const { return std::string_view(OS.data(), OS.size()); }
+
+  void reserveExtraSpace(uint64_t ExtraSize) override {
+    OS.reserve(tell() + ExtraSize);
+  }
 };
 
 /// A raw_ostream that writes to a vector.  This is a
@@ -573,9 +675,9 @@
 
   void flush() = delete;
 
-  /// Return an span for the vector contents.
-  span<uint8_t> array() { return {OS.data(), OS.size()}; }
-  span<const uint8_t> array() const { return {OS.data(), OS.size()}; }
+  /// Return an std::span for the vector contents.
+  std::span<uint8_t> array() { return {OS.data(), OS.size()}; }
+  std::span<const uint8_t> array() const { return {OS.data(), OS.size()}; }
 };
 
 /// A raw_ostream that writes to a vector.  This is a
@@ -607,9 +709,9 @@
 
   void flush() = delete;
 
-  /// Return a span for the vector contents.
-  span<uint8_t> array() { return {OS.data(), OS.size()}; }
-  span<const uint8_t> array() const { return {OS.data(), OS.size()}; }
+  /// Return a std::span for the vector contents.
+  std::span<uint8_t> array() { return {OS.data(), OS.size()}; }
+  std::span<const uint8_t> array() const { return {OS.data(), OS.size()}; }
 };
 
 
@@ -639,6 +741,22 @@
   ~buffer_ostream() override { OS << str(); }
 };
 
+class buffer_unique_ostream : public raw_svector_ostream {
+  std::unique_ptr<raw_ostream> OS;
+  SmallVector<char, 0> Buffer;
+
+  virtual void anchor() override;
+
+public:
+  buffer_unique_ostream(std::unique_ptr<raw_ostream> OS)
+      : raw_svector_ostream(Buffer), OS(std::move(OS)) {
+    // Turn off buffering on OS, which we now own, to avoid allocating a buffer
+    // when the destructor writes only to be immediately flushed again.
+    this->OS->SetUnbuffered();
+  }
+  ~buffer_unique_ostream() override { *OS << str(); }
+};
+
 } // end namespace wpi
 
-#endif // LLVM_SUPPORT_RAW_OSTREAM_H
+#endif // WPIUTIL_WPI_RAW_OSTREAM_H
diff --git a/wpiutil/src/main/native/thirdparty/llvm/include/wpi/type_traits.h b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/type_traits.h
new file mode 100644
index 0000000..53e18d3
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/llvm/include/wpi/type_traits.h
@@ -0,0 +1,104 @@
+//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides useful additions to the standard type_traits library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef WPIUTIL_WPI_TYPE_TRAITS_H
+#define WPIUTIL_WPI_TYPE_TRAITS_H
+
+#include "wpi/Compiler.h"
+#include <type_traits>
+#include <utility>
+
+namespace wpi {
+
+
+/// Metafunction that determines whether the given type is either an
+/// integral type or an enumeration type, including enum classes.
+///
+/// Note that this accepts potentially more integral types than is_integral
+/// because it is based on being implicitly convertible to an integral type.
+/// Also note that enum classes aren't implicitly convertible to integral types,
+/// the value may therefore need to be explicitly converted before being used.
+template <typename T> class is_integral_or_enum {
+  using UnderlyingT = std::remove_reference_t<T>;
+
+public:
+  static const bool value =
+      !std::is_class<UnderlyingT>::value && // Filter conversion operators.
+      !std::is_pointer<UnderlyingT>::value &&
+      !std::is_floating_point<UnderlyingT>::value &&
+      (std::is_enum<UnderlyingT>::value ||
+       std::is_convertible<UnderlyingT, unsigned long long>::value);
+};
+
+/// If T is a pointer, just return it. If it is not, return T&.
+template<typename T, typename Enable = void>
+struct add_lvalue_reference_if_not_pointer { using type = T &; };
+
+template <typename T>
+struct add_lvalue_reference_if_not_pointer<
+    T, std::enable_if_t<std::is_pointer<T>::value>> {
+  using type = T;
+};
+
+/// If T is a pointer to X, return a pointer to const X. If it is not,
+/// return const T.
+template<typename T, typename Enable = void>
+struct add_const_past_pointer { using type = const T; };
+
+template <typename T>
+struct add_const_past_pointer<T, std::enable_if_t<std::is_pointer<T>::value>> {
+  using type = const std::remove_pointer_t<T> *;
+};
+
+template <typename T, typename Enable = void>
+struct const_pointer_or_const_ref {
+  using type = const T &;
+};
+template <typename T>
+struct const_pointer_or_const_ref<T,
+                                  std::enable_if_t<std::is_pointer<T>::value>> {
+  using type = typename add_const_past_pointer<T>::type;
+};
+
+namespace detail {
+/// Internal utility to detect trivial copy construction.
+template<typename T> union copy_construction_triviality_helper {
+    T t;
+    copy_construction_triviality_helper() = default;
+    copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default;
+    ~copy_construction_triviality_helper() = default;
+};
+/// Internal utility to detect trivial move construction.
+template<typename T> union move_construction_triviality_helper {
+    T t;
+    move_construction_triviality_helper() = default;
+    move_construction_triviality_helper(move_construction_triviality_helper&&) = default;
+    ~move_construction_triviality_helper() = default;
+};
+
+template<class T>
+union trivial_helper {
+    T t;
+};
+
+} // end namespace detail
+
+template <typename T>
+using is_trivially_move_constructible = std::is_trivially_move_constructible<T>;
+
+template <typename T>
+using is_trivially_copy_constructible = std::is_trivially_copy_constructible<T>;
+
+
+} // end namespace wpi
+
+#endif // WPIUTIL_WPI_TYPE_TRAITS_H
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/aligned_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/aligned_allocator.hpp
new file mode 100644
index 0000000..8118ec4
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/aligned_allocator.hpp
@@ -0,0 +1,197 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_ALIGNED_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_ALIGNED_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::aligned_allocator and related functions.
+
+#include <type_traits>
+
+#include "detail/assert.hpp"
+#include "detail/utility.hpp"
+#include "allocator_traits.hpp"
+#include "config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// A \concept{concept_rawallocator,RawAllocator} adapter that ensures a minimum alignment.
+        /// It adjusts the alignment value so that it is always larger than the minimum and forwards to the specified allocator.
+        /// \ingroup adapter
+        template <class RawAllocator>
+        class aligned_allocator : WPI_EBO(allocator_traits<RawAllocator>::allocator_type)
+        {
+            using traits            = allocator_traits<RawAllocator>;
+            using composable_traits = composable_allocator_traits<RawAllocator>;
+            using composable        = is_composable_allocator<typename traits::allocator_type>;
+
+        public:
+            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;
+            using is_stateful    = std::true_type;
+
+            /// \effects Creates it passing it the minimum alignment value and the allocator object.
+            /// \requires \c min_alignment must be less than \c this->max_alignment().
+            explicit aligned_allocator(std::size_t min_alignment, allocator_type&& alloc = {})
+            : allocator_type(detail::move(alloc)), min_alignment_(min_alignment)
+            {
+                WPI_MEMORY_ASSERT(min_alignment_ <= max_alignment());
+            }
+
+            /// @{
+            /// \effects Moves the \c aligned_allocator object.
+            /// It simply moves the underlying allocator.
+            aligned_allocator(aligned_allocator&& other) noexcept
+            : allocator_type(detail::move(other)), min_alignment_(other.min_alignment_)
+            {
+            }
+
+            aligned_allocator& operator=(aligned_allocator&& other) noexcept
+            {
+                allocator_type::operator=(detail::move(other));
+                min_alignment_          = other.min_alignment_;
+                return *this;
+            }
+            /// @}
+
+            /// @{
+            /// \effects Forwards to the underlying allocator through the \ref allocator_traits.
+            /// If the \c alignment is less than the \c min_alignment(), it is set to the minimum alignment.
+            void* allocate_node(std::size_t size, std::size_t alignment)
+            {
+                if (min_alignment_ > alignment)
+                    alignment = min_alignment_;
+                return traits::allocate_node(get_allocator(), size, alignment);
+            }
+
+            void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)
+            {
+                if (min_alignment_ > alignment)
+                    alignment = min_alignment_;
+                return traits::allocate_array(get_allocator(), count, size, alignment);
+            }
+
+            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                if (min_alignment_ > alignment)
+                    alignment = min_alignment_;
+                traits::deallocate_node(get_allocator(), ptr, size, alignment);
+            }
+
+            void deallocate_array(void* ptr, std::size_t count, std::size_t size,
+                                  std::size_t alignment) noexcept
+            {
+                if (min_alignment_ > alignment)
+                    alignment = min_alignment_;
+                traits::deallocate_array(get_allocator(), ptr, count, size, alignment);
+            }
+            /// @}
+
+            /// @{
+            /// \effects Forwards to the underlying allocator through the \ref composable_allocator_traits.
+            /// If the \c alignment is less than the \c min_alignment(), it is set to the minimum alignment.
+            /// \requires The underyling allocator must be composable.
+            WPI_ENABLE_IF(composable::value)
+            void* try_allocate_node(std::size_t size, std::size_t alignment) noexcept
+            {
+                if (min_alignment_ > alignment)
+                    alignment = min_alignment_;
+                return composable_traits::try_allocate_node(get_allocator(), size, alignment);
+            }
+
+            WPI_ENABLE_IF(composable::value)
+            void* try_allocate_array(std::size_t count, std::size_t size,
+                                     std::size_t alignment) noexcept
+            {
+                if (min_alignment_ > alignment)
+                    alignment = min_alignment_;
+                return composable_traits::try_allocate_array(get_allocator(), count, size,
+                                                             alignment);
+            }
+
+            WPI_ENABLE_IF(composable::value)
+            bool try_deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                if (min_alignment_ > alignment)
+                    alignment = min_alignment_;
+                return composable_traits::try_deallocate_node(get_allocator(), ptr, size,
+                                                              alignment);
+            }
+
+            WPI_ENABLE_IF(composable::value)
+            bool try_deallocate_array(void* ptr, std::size_t count, std::size_t size,
+                                      std::size_t alignment) noexcept
+            {
+                if (min_alignment_ > alignment)
+                    alignment = min_alignment_;
+                return composable_traits::try_deallocate_array(get_allocator(), ptr, count, size,
+                                                               alignment);
+            }
+            /// @}
+
+            /// @{
+            /// \returns The value returned by the \ref allocator_traits for the underlying allocator.
+            std::size_t max_node_size() const
+            {
+                return traits::max_node_size(get_allocator());
+            }
+
+            std::size_t max_array_size() const
+            {
+                return traits::max_array_size(get_allocator());
+            }
+
+            std::size_t max_alignment() const
+            {
+                return traits::max_alignment(get_allocator());
+            }
+            /// @}
+
+            /// @{
+            /// \returns A reference to the underlying allocator.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+            const allocator_type& get_allocator() const noexcept
+            {
+                return *this;
+            }
+            /// @}
+
+            /// \returns The minimum alignment.
+            std::size_t min_alignment() const noexcept
+            {
+                return min_alignment_;
+            }
+
+            /// \effects Sets the minimum alignment to a new value.
+            /// \requires \c min_alignment must be less than \c this->max_alignment().
+            void set_min_alignment(std::size_t min_alignment)
+            {
+                WPI_MEMORY_ASSERT(min_alignment <= max_alignment());
+                min_alignment_ = min_alignment;
+            }
+
+        private:
+            std::size_t min_alignment_;
+        };
+
+        /// \returns A new \ref aligned_allocator created by forwarding the parameters to the constructor.
+        /// \relates aligned_allocator
+        template <class RawAllocator>
+        auto make_aligned_allocator(std::size_t min_alignment, RawAllocator&& allocator) noexcept
+            -> aligned_allocator<typename std::decay<RawAllocator>::type>
+        {
+            return aligned_allocator<
+                typename std::decay<RawAllocator>::type>{min_alignment,
+                                                         detail::forward<RawAllocator>(allocator)};
+        }
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_ALIGNED_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/allocator_storage.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/allocator_storage.hpp
new file mode 100644
index 0000000..8dab2e0
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/allocator_storage.hpp
@@ -0,0 +1,932 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_ALLOCATOR_STORAGE_HPP_INCLUDED
+#define WPI_MEMORY_ALLOCATOR_STORAGE_HPP_INCLUDED
+
+/// \file
+/// Class template \ref wpi::memory::allocator_storage, some policies and resulting typedefs.
+
+#include <new>
+#include <type_traits>
+
+#include "detail/utility.hpp"
+#include "config.hpp"
+#include "allocator_traits.hpp"
+#include "threading.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            template <class Alloc>
+            void* try_allocate_node(std::true_type, Alloc& alloc, std::size_t size,
+                                    std::size_t alignment) noexcept
+            {
+                return composable_allocator_traits<Alloc>::try_allocate_node(alloc, size,
+                                                                             alignment);
+            }
+
+            template <class Alloc>
+            void* try_allocate_array(std::true_type, Alloc& alloc, std::size_t count,
+                                     std::size_t size, std::size_t alignment) noexcept
+            {
+                return composable_allocator_traits<Alloc>::try_allocate_array(alloc, count, size,
+                                                                              alignment);
+            }
+
+            template <class Alloc>
+            bool try_deallocate_node(std::true_type, Alloc& alloc, void* ptr, std::size_t size,
+                                     std::size_t alignment) noexcept
+            {
+                return composable_allocator_traits<Alloc>::try_deallocate_node(alloc, ptr, size,
+                                                                               alignment);
+            }
+
+            template <class Alloc>
+            bool try_deallocate_array(std::true_type, Alloc& alloc, void* ptr, std::size_t count,
+                                      std::size_t size, std::size_t alignment) noexcept
+            {
+                return composable_allocator_traits<Alloc>::try_deallocate_array(alloc, ptr, count,
+                                                                                size, alignment);
+            }
+
+            template <class Alloc>
+            void* try_allocate_node(std::false_type, Alloc&, std::size_t, std::size_t) noexcept
+            {
+                WPI_MEMORY_UNREACHABLE("Allocator is not compositioning");
+                return nullptr;
+            }
+
+            template <class Alloc>
+            void* try_allocate_array(std::false_type, Alloc&, std::size_t, std::size_t,
+                                     std::size_t) noexcept
+            {
+                WPI_MEMORY_UNREACHABLE("Allocator is not compositioning");
+                return nullptr;
+            }
+
+            template <class Alloc>
+            bool try_deallocate_node(std::false_type, Alloc&, void*, std::size_t,
+                                     std::size_t) noexcept
+            {
+                WPI_MEMORY_UNREACHABLE("Allocator is not compositioning");
+                return false;
+            }
+
+            template <class Alloc>
+            bool try_deallocate_array(std::false_type, Alloc&, void*, std::size_t, std::size_t,
+                                      std::size_t) noexcept
+            {
+                WPI_MEMORY_UNREACHABLE("Allocator is not compositioning");
+                return false;
+            }
+        } // namespace detail
+
+        /// A \concept{concept_rawallocator,RawAllocator} that stores another allocator.
+        /// The \concept{concept_storagepolicy,StoragePolicy} defines the allocator type being stored and how it is stored.
+        /// The \c Mutex controls synchronization of the access.
+        /// \ingroup storage
+        template <class StoragePolicy, class Mutex>
+        class allocator_storage
+        : WPI_EBO(StoragePolicy,
+                        detail::mutex_storage<
+                            detail::mutex_for<typename StoragePolicy::allocator_type, Mutex>>)
+        {
+            using traits = allocator_traits<typename StoragePolicy::allocator_type>;
+            using composable_traits =
+                composable_allocator_traits<typename StoragePolicy::allocator_type>;
+            using composable   = is_composable_allocator<typename StoragePolicy::allocator_type>;
+            using actual_mutex = const detail::mutex_storage<
+                detail::mutex_for<typename StoragePolicy::allocator_type, Mutex>>;
+
+        public:
+            using allocator_type = typename StoragePolicy::allocator_type;
+            using storage_policy = StoragePolicy;
+            using mutex          = Mutex;
+            using is_stateful    = typename traits::is_stateful;
+
+            /// \effects Creates it by default-constructing the \c StoragePolicy.
+            /// \requires The \c StoragePolicy must be default-constructible.
+            /// \notes The default constructor may create an invalid allocator storage not associated with any allocator.
+            /// If that is the case, it must not be used.
+            allocator_storage() = default;
+
+            /// \effects Creates it by passing it an allocator.
+            /// The allocator will be forwarded to the \c StoragePolicy, it decides whether it will be moved, its address stored or something else.
+            /// \requires The expression <tt>new storage_policy(std::forward<Alloc>(alloc))</tt> must be well-formed,
+            /// otherwise this constructor does not participate in overload resolution.
+            template <
+                class Alloc,
+                // MSVC seems to ignore access rights in SFINAE below
+                // use this to prevent this constructor being chosen instead of move for types inheriting from it
+                WPI_REQUIRES(
+                    (!std::is_base_of<allocator_storage, typename std::decay<Alloc>::type>::value))>
+            allocator_storage(Alloc&& alloc,
+                              WPI_SFINAE(new storage_policy(detail::forward<Alloc>(alloc))))
+            : storage_policy(detail::forward<Alloc>(alloc))
+            {
+            }
+
+            /// \effects Creates it by passing it another \c allocator_storage with a different \c StoragePolicy but the same \c Mutex type.
+            /// Initializes it with the result of \c other.get_allocator().
+            /// \requires The expression <tt>new storage_policy(other.get_allocator())</tt> must be well-formed,
+            /// otherwise this constructor does not participate in overload resolution.
+            template <class OtherPolicy>
+            allocator_storage(const allocator_storage<OtherPolicy, Mutex>& other,
+                              WPI_SFINAE(new storage_policy(other.get_allocator())))
+            : storage_policy(other.get_allocator())
+            {
+            }
+
+            /// @{
+            /// \effects Moves the \c allocator_storage object.
+            /// A moved-out \c allocator_storage object must still store a valid allocator object.
+            allocator_storage(allocator_storage&& other) noexcept
+            : storage_policy(detail::move(other)),
+              detail::mutex_storage<
+                  detail::mutex_for<typename StoragePolicy::allocator_type, Mutex>>(
+                  detail::move(other))
+            {
+            }
+
+            allocator_storage& operator=(allocator_storage&& other) noexcept
+            {
+                storage_policy::                                 operator=(detail::move(other));
+                detail::mutex_storage<detail::mutex_for<typename StoragePolicy::allocator_type,
+                                                        Mutex>>::operator=(detail::move(other));
+                return *this;
+            }
+            /// @}
+
+            /// @{
+            /// \effects Copies the \c allocator_storage object.
+            /// \requires The \c StoragePolicy must be copyable.
+            allocator_storage(const allocator_storage&) = default;
+            allocator_storage& operator=(const allocator_storage&) = default;
+            /// @}
+
+            /// @{
+            /// \effects Calls the function on the stored allocator.
+            /// The \c Mutex will be locked during the operation.
+            void* allocate_node(std::size_t size, std::size_t alignment)
+            {
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return traits::allocate_node(alloc, size, alignment);
+            }
+
+            void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)
+            {
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return traits::allocate_array(alloc, count, size, alignment);
+            }
+
+            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                traits::deallocate_node(alloc, ptr, size, alignment);
+            }
+
+            void deallocate_array(void* ptr, std::size_t count, std::size_t size,
+                                  std::size_t alignment) noexcept
+            {
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                traits::deallocate_array(alloc, ptr, count, size, alignment);
+            }
+
+            std::size_t max_node_size() const
+            {
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return traits::max_node_size(alloc);
+            }
+
+            std::size_t max_array_size() const
+            {
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return traits::max_array_size(alloc);
+            }
+
+            std::size_t max_alignment() const
+            {
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return traits::max_alignment(alloc);
+            }
+            /// @}
+
+            /// @{
+            /// \effects Calls the function on the stored composable allocator.
+            /// The \c Mutex will be locked during the operation.
+            /// \requires The allocator must be composable,
+            /// i.e. \ref is_composable() must return `true`.
+            /// \note This check is done at compile-time where possible,
+            /// and at runtime in the case of type-erased storage.
+            WPI_ENABLE_IF(composable::value)
+            void* try_allocate_node(std::size_t size, std::size_t alignment) noexcept
+            {
+                WPI_MEMORY_ASSERT(is_composable());
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return composable_traits::try_allocate_node(alloc, size, alignment);
+            }
+
+            WPI_ENABLE_IF(composable::value)
+            void* try_allocate_array(std::size_t count, std::size_t size,
+                                     std::size_t alignment) noexcept
+            {
+                WPI_MEMORY_ASSERT(is_composable());
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return composable_traits::try_allocate_array(alloc, count, size, alignment);
+            }
+
+            WPI_ENABLE_IF(composable::value)
+            bool try_deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                WPI_MEMORY_ASSERT(is_composable());
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return composable_traits::try_deallocate_node(alloc, ptr, size, alignment);
+            }
+
+            WPI_ENABLE_IF(composable::value)
+            bool try_deallocate_array(void* ptr, std::size_t count, std::size_t size,
+                                      std::size_t alignment) noexcept
+            {
+                WPI_MEMORY_ASSERT(is_composable());
+                std::lock_guard<actual_mutex> lock(*this);
+                auto&&                        alloc = get_allocator();
+                return composable_traits::try_deallocate_array(alloc, ptr, count, size, alignment);
+            }
+            /// @}
+
+            /// @{
+            /// \effects Forwards to the \c StoragePolicy.
+            /// \returns Returns a reference to the stored allocator.
+            /// \note This does not lock the \c Mutex.
+            auto get_allocator() noexcept
+                -> decltype(std::declval<storage_policy>().get_allocator())
+            {
+                return storage_policy::get_allocator();
+            }
+
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<const storage_policy>().get_allocator())
+            {
+                return storage_policy::get_allocator();
+            }
+            /// @}
+
+            /// @{
+            /// \returns A proxy object that acts like a pointer to the stored allocator.
+            /// It cannot be reassigned to point to another allocator object and only moving is supported, which is destructive.
+            /// As long as the proxy object lives and is not moved from, the \c Mutex will be kept locked.
+            auto lock() noexcept -> WPI_IMPL_DEFINED(decltype(detail::lock_allocator(
+                std::declval<storage_policy>().get_allocator(), std::declval<actual_mutex&>())))
+            {
+                return detail::lock_allocator(get_allocator(), static_cast<actual_mutex&>(*this));
+            }
+
+            auto lock() const noexcept -> WPI_IMPL_DEFINED(decltype(
+                detail::lock_allocator(std::declval<const storage_policy>().get_allocator(),
+                                       std::declval<actual_mutex&>())))
+            {
+                return detail::lock_allocator(get_allocator(), static_cast<actual_mutex&>(*this));
+            }
+            /// @}.
+
+            /// \returns Whether or not the stored allocator is composable,
+            /// that is you can use the compositioning functions.
+            /// \note Due to type-erased allocators,
+            /// this function can not be `constexpr`.
+            bool is_composable() const noexcept
+            {
+                return StoragePolicy::is_composable();
+            }
+        };
+
+        /// Tag type that enables type-erasure in \ref reference_storage.
+        /// It can be used everywhere a \ref allocator_reference is used internally.
+        /// \ingroup storage
+        struct any_allocator
+        {
+        };
+
+        /// A \concept{concept_storagepolicy,StoragePolicy} that stores the allocator directly.
+        /// It embeds the allocator inside it, i.e. moving the storage policy will move the allocator.
+        /// \ingroup storage
+        template <class RawAllocator>
+        class direct_storage : WPI_EBO(allocator_traits<RawAllocator>::allocator_type)
+        {
+            static_assert(!std::is_same<RawAllocator, any_allocator>::value,
+                          "cannot type-erase in direct_storage");
+
+        public:
+            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;
+
+            /// \effects Creates it by default-constructing the allocator.
+            /// \requires The \c RawAllcoator must be default constructible.
+            direct_storage() = default;
+
+            /// \effects Creates it by moving in an allocator object.
+            direct_storage(allocator_type&& allocator) noexcept
+            : allocator_type(detail::move(allocator))
+            {
+            }
+
+            /// @{
+            /// \effects Moves the \c direct_storage object.
+            /// This will move the stored allocator.
+            direct_storage(direct_storage&& other) noexcept : allocator_type(detail::move(other)) {}
+
+            direct_storage& operator=(direct_storage&& other) noexcept
+            {
+                allocator_type::operator=(detail::move(other));
+                return *this;
+            }
+            /// @}
+
+            /// @{
+            /// \returns A (\c const) reference to the stored allocator.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+            const allocator_type& get_allocator() const noexcept
+            {
+                return *this;
+            }
+            /// @}
+
+        protected:
+            ~direct_storage() noexcept = default;
+
+            bool is_composable() const noexcept
+            {
+                return is_composable_allocator<allocator_type>::value;
+            }
+        };
+
+        /// An alias template for \ref allocator_storage using the \ref direct_storage policy without a mutex.
+        /// It has the effect of giving any \concept{concept_rawallocator,RawAllocator} the interface with all member functions,
+        /// avoiding the need to wrap it inside the \ref allocator_traits.
+        /// \ingroup storage
+        template <class RawAllocator>
+        WPI_ALIAS_TEMPLATE(allocator_adapter,
+                                 allocator_storage<direct_storage<RawAllocator>, no_mutex>);
+
+        /// \returns A new \ref allocator_adapter object created by forwarding to the constructor.
+        /// \relates allocator_adapter
+        template <class RawAllocator>
+        auto make_allocator_adapter(RawAllocator&& allocator) noexcept
+            -> allocator_adapter<typename std::decay<RawAllocator>::type>
+        {
+            return {detail::forward<RawAllocator>(allocator)};
+        }
+
+/// An alias template for \ref allocator_storage using the \ref direct_storage policy with a mutex.
+/// It has a similar effect as \ref allocator_adapter but performs synchronization.
+/// The \c Mutex will default to \c std::mutex if threading is supported,
+/// otherwise there is no default.
+/// \ingroup storage
+#if WPI_HOSTED_IMPLEMENTATION
+        template <class RawAllocator, class Mutex = std::mutex>
+        WPI_ALIAS_TEMPLATE(thread_safe_allocator,
+                                 allocator_storage<direct_storage<RawAllocator>, Mutex>);
+#else
+        template <class RawAllocator, class Mutex>
+        WPI_ALIAS_TEMPLATE(thread_safe_allocator,
+                                 allocator_storage<direct_storage<RawAllocator>, Mutex>);
+#endif
+
+#if WPI_HOSTED_IMPLEMENTATION
+        /// \returns A new \ref thread_safe_allocator object created by forwarding to the constructor/
+        /// \relates thread_safe_allocator
+        template <class RawAllocator>
+        auto make_thread_safe_allocator(RawAllocator&& allocator)
+            -> thread_safe_allocator<typename std::decay<RawAllocator>::type>
+        {
+            return detail::forward<RawAllocator>(allocator);
+        }
+#endif
+
+        /// \returns A new \ref thread_safe_allocator object created by forwarding to the constructor,
+        /// specifying a certain mutex type.
+        /// \requires It requires threading support from the implementation.
+        /// \relates thread_safe_allocator
+        template <class Mutex, class RawAllocator>
+        auto make_thread_safe_allocator(RawAllocator&& allocator)
+            -> thread_safe_allocator<typename std::decay<RawAllocator>::type, Mutex>
+        {
+            return detail::forward<RawAllocator>(allocator);
+        }
+
+        namespace detail
+        {
+            struct reference_stateful
+            {
+            };
+            struct reference_stateless
+            {
+            };
+            struct reference_shared
+            {
+            };
+
+            reference_stateful  reference_type(std::true_type stateful, std::false_type shared);
+            reference_stateless reference_type(std::false_type stateful, std::true_type shared);
+            reference_stateless reference_type(std::false_type stateful, std::false_type shared);
+            reference_shared    reference_type(std::true_type stateful, std::true_type shared);
+
+            template <class RawAllocator, class Tag>
+            class reference_storage_impl;
+
+            // reference to stateful: stores a pointer to an allocator
+            template <class RawAllocator>
+            class reference_storage_impl<RawAllocator, reference_stateful>
+            {
+            protected:
+                reference_storage_impl() noexcept : alloc_(nullptr) {}
+
+                reference_storage_impl(RawAllocator& allocator) noexcept : alloc_(&allocator) {}
+
+                bool is_valid() const noexcept
+                {
+                    return alloc_ != nullptr;
+                }
+
+                RawAllocator& get_allocator() const noexcept
+                {
+                    WPI_MEMORY_ASSERT(alloc_ != nullptr);
+                    return *alloc_;
+                }
+
+            private:
+                RawAllocator* alloc_;
+            };
+
+            // reference to stateless: store in static storage
+            template <class RawAllocator>
+            class reference_storage_impl<RawAllocator, reference_stateless>
+            {
+            protected:
+                reference_storage_impl() noexcept = default;
+
+                reference_storage_impl(const RawAllocator&) noexcept {}
+
+                bool is_valid() const noexcept
+                {
+                    return true;
+                }
+
+                RawAllocator& get_allocator() const noexcept
+                {
+                    static RawAllocator alloc;
+                    return alloc;
+                }
+            };
+
+            // reference to shared: stores RawAllocator directly
+            template <class RawAllocator>
+            class reference_storage_impl<RawAllocator, reference_shared>
+            {
+            protected:
+                reference_storage_impl() noexcept = default;
+
+                reference_storage_impl(const RawAllocator& alloc) noexcept : alloc_(alloc) {}
+
+                bool is_valid() const noexcept
+                {
+                    return true;
+                }
+
+                RawAllocator& get_allocator() const noexcept
+                {
+                    return alloc_;
+                }
+
+            private:
+                mutable RawAllocator alloc_;
+            };
+        } // namespace detail
+
+        /// Specifies whether or not a \concept{concept_rawallocator,RawAllocator} has shared semantics.
+        /// It is shared, if - like \ref allocator_reference - if multiple objects refer to the same internal allocator and if it can be copied.
+        /// This sharing is stateful, however, stateless allocators are not considered shared in the meaning of this traits. <br>
+        /// If a \c RawAllocator is shared, it will be directly embedded inside \ref reference_storage since it already provides \ref allocator_reference like semantics, so there is no need to add them manually,<br>
+        /// Specialize it for your own types, if they provide sharing semantics and can be copied.
+        /// They also must provide an `operator==` to check whether two allocators refer to the same shared one.
+        /// \note This makes no guarantees about the lifetime of the shared object, the sharing allocators can either own or refer to a shared object.
+        /// \ingroup storage
+        template <class RawAllocator>
+        struct is_shared_allocator : std::false_type
+        {
+        };
+
+        /// A \concept{concept_storagepolicy,StoragePolicy} that stores a reference to an allocator.
+        /// For stateful allocators it only stores a pointer to an allocator object and copying/moving only copies the pointer.
+        /// For stateless allocators it does not store anything, an allocator will be constructed as needed.
+        /// For allocators that are already shared (determined through \ref is_shared_allocator) it will store the allocator type directly.
+        /// \note It does not take ownership over the allocator in the stateful case, the user has to ensure that the allocator object stays valid.
+        /// In the other cases the lifetime does not matter.
+        /// \ingroup storage
+        template <class RawAllocator>
+        class reference_storage
+#ifndef DOXYGEN
+        : WPI_EBO(detail::reference_storage_impl<
+                        typename allocator_traits<RawAllocator>::allocator_type,
+                        decltype(detail::reference_type(
+                            typename allocator_traits<RawAllocator>::is_stateful{},
+                            is_shared_allocator<RawAllocator>{}))>)
+#endif
+        {
+            using storage = detail::reference_storage_impl<
+                typename allocator_traits<RawAllocator>::allocator_type,
+                decltype(
+                    detail::reference_type(typename allocator_traits<RawAllocator>::is_stateful{},
+                                           is_shared_allocator<RawAllocator>{}))>;
+
+        public:
+            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;
+
+            /// Default constructor.
+            /// \effects If the allocator is stateless, this has no effect and the object is usable as an allocator.
+            /// If the allocator is stateful, creates an invalid reference without any associated allocator.
+            /// Then it must not be used.
+            /// If the allocator is shared, default constructs the shared allocator.
+            /// If the shared allocator does not have a default constructor, this constructor is ill-formed.
+            reference_storage() noexcept = default;
+
+            /// \effects Creates it from a stateless or shared allocator.
+            /// It will not store anything, only creates the allocator as needed.
+            /// \requires The \c RawAllocator is stateless or shared.
+            reference_storage(const allocator_type& alloc) noexcept : storage(alloc) {}
+
+            /// \effects Creates it from a reference to a stateful allocator.
+            /// It will store a pointer to this allocator object.
+            /// \note The user has to take care that the lifetime of the reference does not exceed the allocator lifetime.
+            reference_storage(allocator_type& alloc) noexcept : storage(alloc) {}
+
+            /// @{
+            /// \effects Copies the \c allocator_reference object.
+            /// Only copies the pointer to it in the stateful case.
+            reference_storage(const reference_storage&) noexcept = default;
+            reference_storage& operator=(const reference_storage&) noexcept = default;
+            /// @}
+
+            /// \returns Whether or not the reference is valid.
+            /// It is only invalid, if it was created by the default constructor and the allocator is stateful.
+            explicit operator bool() const noexcept
+            {
+                return storage::is_valid();
+            }
+
+            /// \returns Returns a reference to the allocator.
+            /// \requires The reference must be valid.
+            allocator_type& get_allocator() const noexcept
+            {
+                return storage::get_allocator();
+            }
+
+        protected:
+            ~reference_storage() noexcept = default;
+
+            bool is_composable() const noexcept
+            {
+                return is_composable_allocator<allocator_type>::value;
+            }
+        };
+
+        /// Specialization of the class template \ref reference_storage that is type-erased.
+        /// It is triggered by the tag type \ref any_allocator.
+        /// The specialization can store a reference to any allocator type.
+        /// \ingroup storage
+        template <>
+        class reference_storage<any_allocator>
+        {
+            class base_allocator
+            {
+            public:
+                using is_stateful = std::true_type;
+
+                virtual ~base_allocator() = default;
+
+                virtual void clone(void* storage) const noexcept = 0;
+
+                void* allocate_node(std::size_t size, std::size_t alignment)
+                {
+                    return allocate_impl(1, size, alignment);
+                }
+
+                void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)
+                {
+                    return allocate_impl(count, size, alignment);
+                }
+
+                void deallocate_node(void* node, std::size_t size, std::size_t alignment) noexcept
+                {
+                    deallocate_impl(node, 1, size, alignment);
+                }
+
+                void deallocate_array(void* array, std::size_t count, std::size_t size,
+                                      std::size_t alignment) noexcept
+                {
+                    deallocate_impl(array, count, size, alignment);
+                }
+
+                void* try_allocate_node(std::size_t size, std::size_t alignment) noexcept
+                {
+                    return try_allocate_impl(1, size, alignment);
+                }
+
+                void* try_allocate_array(std::size_t count, std::size_t size,
+                                         std::size_t alignment) noexcept
+                {
+                    return try_allocate_impl(count, size, alignment);
+                }
+
+                bool try_deallocate_node(void* node, std::size_t size,
+                                         std::size_t alignment) noexcept
+                {
+                    return try_deallocate_impl(node, 1, size, alignment);
+                }
+
+                bool try_deallocate_array(void* array, std::size_t count, std::size_t size,
+                                          std::size_t alignment) noexcept
+                {
+                    return try_deallocate_impl(array, count, size, alignment);
+                }
+
+                // count 1 means node
+                virtual void* allocate_impl(std::size_t count, std::size_t size,
+                                            std::size_t alignment)            = 0;
+                virtual void  deallocate_impl(void* ptr, std::size_t count, std::size_t size,
+                                              std::size_t alignment) noexcept = 0;
+
+                virtual void* try_allocate_impl(std::size_t count, std::size_t size,
+                                                std::size_t alignment) noexcept = 0;
+
+                virtual bool try_deallocate_impl(void* ptr, std::size_t count, std::size_t size,
+                                                 std::size_t alignment) noexcept = 0;
+
+                std::size_t max_node_size() const
+                {
+                    return max(query::node_size);
+                }
+
+                std::size_t max_array_size() const
+                {
+                    return max(query::array_size);
+                }
+
+                std::size_t max_alignment() const
+                {
+                    return max(query::alignment);
+                }
+
+                virtual bool is_composable() const noexcept = 0;
+
+            protected:
+                enum class query
+                {
+                    node_size,
+                    array_size,
+                    alignment
+                };
+
+                virtual std::size_t max(query q) const = 0;
+            };
+
+        public:
+            using allocator_type = WPI_IMPL_DEFINED(base_allocator);
+
+            /// \effects Creates it from a reference to any stateful \concept{concept_rawallocator,RawAllocator}.
+            /// It will store a pointer to this allocator object.
+            /// \note The user has to take care that the lifetime of the reference does not exceed the allocator lifetime.
+            template <class RawAllocator>
+            reference_storage(RawAllocator& alloc) noexcept
+            {
+                static_assert(sizeof(basic_allocator<RawAllocator>)
+                                  <= sizeof(basic_allocator<default_instantiation>),
+                              "requires all instantiations to have certain maximum size");
+                ::new (static_cast<void*>(&storage_)) basic_allocator<RawAllocator>(alloc);
+            }
+
+            // \effects Creates it from any stateless \concept{concept_rawallocator,RawAllocator}.
+            /// It will not store anything, only creates the allocator as needed.
+            /// \requires The \c RawAllocator is stateless.
+            template <class RawAllocator>
+            reference_storage(
+                const RawAllocator& alloc,
+                WPI_REQUIRES(!allocator_traits<RawAllocator>::is_stateful::value)) noexcept
+            {
+                static_assert(sizeof(basic_allocator<RawAllocator>)
+                                  <= sizeof(basic_allocator<default_instantiation>),
+                              "requires all instantiations to have certain maximum size");
+                ::new (static_cast<void*>(&storage_)) basic_allocator<RawAllocator>(alloc);
+            }
+
+            /// \effects Creates it from the internal base class for the type-erasure.
+            /// Has the same effect as if the actual stored allocator were passed to the other constructor overloads.
+            /// \note This constructor is used internally to avoid double-nesting.
+            reference_storage(const WPI_IMPL_DEFINED(base_allocator) & alloc) noexcept
+            {
+                alloc.clone(&storage_);
+            }
+
+            /// \effects Creates it from the internal base class for the type-erasure.
+            /// Has the same effect as if the actual stored allocator were passed to the other constructor overloads.
+            /// \note This constructor is used internally to avoid double-nesting.
+            reference_storage(WPI_IMPL_DEFINED(base_allocator) & alloc) noexcept
+            : reference_storage(static_cast<const base_allocator&>(alloc))
+            {
+            }
+
+            /// @{
+            /// \effects Copies the \c reference_storage object.
+            /// It only copies the pointer to the allocator.
+            reference_storage(const reference_storage& other) noexcept
+            {
+                other.get_allocator().clone(&storage_);
+            }
+
+            reference_storage& operator=(const reference_storage& other) noexcept
+            {
+                get_allocator().~allocator_type();
+                other.get_allocator().clone(&storage_);
+                return *this;
+            }
+            /// @}
+
+            /// \returns A reference to the allocator.
+            /// The actual type is implementation-defined since it is the base class used in the type-erasure,
+            /// but it provides the full \concept{concept_rawallocator,RawAllocator} member functions.
+            /// \note There is no way to access any custom member functions of the allocator type.
+            allocator_type& get_allocator() const noexcept
+            {
+                auto mem = static_cast<void*>(&storage_);
+                return *static_cast<base_allocator*>(mem);
+            }
+
+        protected:
+            ~reference_storage() noexcept
+            {
+                get_allocator().~allocator_type();
+            }
+
+            bool is_composable() const noexcept
+            {
+                return get_allocator().is_composable();
+            }
+
+        private:
+            template <class RawAllocator>
+            class basic_allocator
+            : public base_allocator,
+              private detail::reference_storage_impl<
+                  typename allocator_traits<RawAllocator>::allocator_type,
+                  decltype(
+                      detail::reference_type(typename allocator_traits<RawAllocator>::is_stateful{},
+                                             is_shared_allocator<RawAllocator>{}))>
+            {
+                using traits     = allocator_traits<RawAllocator>;
+                using composable = is_composable_allocator<typename traits::allocator_type>;
+                using storage    = detail::reference_storage_impl<
+                    typename allocator_traits<RawAllocator>::allocator_type,
+                    decltype(detail::reference_type(typename allocator_traits<
+                                                        RawAllocator>::is_stateful{},
+                                                    is_shared_allocator<RawAllocator>{}))>;
+
+            public:
+                // non stateful
+                basic_allocator(const RawAllocator& alloc) noexcept : storage(alloc) {}
+
+                // stateful
+                basic_allocator(RawAllocator& alloc) noexcept : storage(alloc) {}
+
+            private:
+                typename traits::allocator_type& get() const noexcept
+                {
+                    return storage::get_allocator();
+                }
+
+                void clone(void* storage) const noexcept override
+                {
+                    ::new (storage) basic_allocator(get());
+                }
+
+                void* allocate_impl(std::size_t count, std::size_t size,
+                                    std::size_t alignment) override
+                {
+                    auto&& alloc = get();
+                    if (count == 1u)
+                        return traits::allocate_node(alloc, size, alignment);
+                    else
+                        return traits::allocate_array(alloc, count, size, alignment);
+                }
+
+                void deallocate_impl(void* ptr, std::size_t count, std::size_t size,
+                                     std::size_t alignment) noexcept override
+                {
+                    auto&& alloc = get();
+                    if (count == 1u)
+                        traits::deallocate_node(alloc, ptr, size, alignment);
+                    else
+                        traits::deallocate_array(alloc, ptr, count, size, alignment);
+                }
+
+                void* try_allocate_impl(std::size_t count, std::size_t size,
+                                        std::size_t alignment) noexcept override
+                {
+                    auto&& alloc = get();
+                    if (count == 1u)
+                        return detail::try_allocate_node(composable{}, alloc, size, alignment);
+                    else
+                        return detail::try_allocate_array(composable{}, alloc, count, size,
+                                                          alignment);
+                }
+
+                bool try_deallocate_impl(void* ptr, std::size_t count, std::size_t size,
+                                         std::size_t alignment) noexcept override
+                {
+                    auto&& alloc = get();
+                    if (count == 1u)
+                        return detail::try_deallocate_node(composable{}, alloc, ptr, size,
+                                                           alignment);
+                    else
+                        return detail::try_deallocate_array(composable{}, alloc, ptr, count, size,
+                                                            alignment);
+                }
+
+                bool is_composable() const noexcept override
+                {
+                    return composable::value;
+                }
+
+                std::size_t max(query q) const override
+                {
+                    auto&& alloc = get();
+                    if (q == query::node_size)
+                        return traits::max_node_size(alloc);
+                    else if (q == query::array_size)
+                        return traits::max_array_size(alloc);
+                    return traits::max_alignment(alloc);
+                }
+            };
+
+            // use a stateful instantiation to determine size and alignment
+            // base_allocator is stateful
+            using default_instantiation = basic_allocator<base_allocator>;
+            alignas(default_instantiation) mutable char storage_[sizeof(default_instantiation)];
+        };
+
+        /// An alias template for \ref allocator_storage using the \ref reference_storage policy.
+        /// It will store a reference to the given allocator type. The tag type \ref any_allocator enables type-erasure.
+        /// Wrap the allocator in a \ref thread_safe_allocator if you want thread safety.
+        /// \ingroup storage
+        template <class RawAllocator>
+        WPI_ALIAS_TEMPLATE(allocator_reference,
+                                 allocator_storage<reference_storage<RawAllocator>, no_mutex>);
+
+        /// \returns A new \ref allocator_reference object by forwarding the allocator to the constructor.
+        /// \relates allocator_reference
+        template <class RawAllocator>
+        auto make_allocator_reference(RawAllocator&& allocator) noexcept
+            -> allocator_reference<typename std::decay<RawAllocator>::type>
+        {
+            return {detail::forward<RawAllocator>(allocator)};
+        }
+
+        /// An alias for the \ref reference_storage specialization using type-erasure.
+        /// \ingroup storage
+        using any_reference_storage = reference_storage<any_allocator>;
+
+        /// An alias for \ref allocator_storage using the \ref any_reference_storage.
+        /// It will store a reference to any \concept{concept_rawallocator,RawAllocator}.
+        /// This is the same as passing the tag type \ref any_allocator to the alias \ref allocator_reference.
+        /// Wrap the allocator in a \ref thread_safe_allocator if you want thread safety.
+        /// \ingroup storage
+        using any_allocator_reference = allocator_storage<any_reference_storage, no_mutex>;
+
+        /// \returns A new \ref any_allocator_reference object by forwarding the allocator to the constructor.
+        /// \relates any_allocator_reference
+        template <class RawAllocator>
+        auto make_any_allocator_reference(RawAllocator&& allocator) noexcept
+            -> any_allocator_reference
+        {
+            return {detail::forward<RawAllocator>(allocator)};
+        }
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_ALLOCATOR_STORAGE_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/allocator_traits.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/allocator_traits.hpp
new file mode 100644
index 0000000..47b6ffb
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/allocator_traits.hpp
@@ -0,0 +1,603 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_ALLOCATOR_TRAITS_HPP_INCLUDED
+#define WPI_MEMORY_ALLOCATOR_TRAITS_HPP_INCLUDED
+
+/// \file
+/// The default specialization of the \ref wpi::memory::allocator_traits.
+
+#include <cstddef>
+#include <type_traits>
+
+#include "detail/align.hpp"
+#include "detail/utility.hpp"
+#include "config.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <memory>
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            template <class Allocator>
+            std::true_type has_construct(int, WPI_SFINAE(std::declval<Allocator>().construct(
+                                                  std::declval<typename Allocator::pointer>(),
+                                                  std::declval<typename Allocator::value_type>())));
+
+            template <class Allocator>
+            std::false_type has_construct(short);
+
+            template <class Allocator>
+            std::true_type has_destroy(int, WPI_SFINAE(std::declval<Allocator>().destroy(
+                                                std::declval<typename Allocator::pointer>())));
+
+            template <class Allocator>
+            std::false_type has_destroy(short);
+
+            template <class Allocator>
+            struct check_standard_allocator
+            {
+                using custom_construct = decltype(has_construct<Allocator>(0));
+                using custom_destroy   = decltype(has_destroy<Allocator>(0));
+
+                using valid = std::integral_constant<bool, !custom_construct::value
+                                                               && !custom_destroy::value>;
+            };
+        } // namespace detail
+
+        /// Traits class that checks whether or not a standard \c Allocator can be used as \concept{concept_rawallocator,RawAllocator}.
+        /// It checks the existence of a custom \c construct(), \c destroy() function, if provided,
+        /// it cannot be used since it would not be called.<br>
+        /// Specialize it for custom \c Allocator types to override this check.
+        /// \ingroup core
+        template <class Allocator>
+        struct allocator_is_raw_allocator
+        : WPI_EBO(detail::check_standard_allocator<Allocator>::valid)
+        {
+        };
+
+        /// Specialization of \ref allocator_is_raw_allocator that allows \c std::allocator again.
+        /// \ingroup core
+        template <typename T>
+        struct allocator_is_raw_allocator<std::allocator<T>> : std::true_type
+        {
+        };
+
+        namespace traits_detail // use seperate namespace to avoid name clashes
+        {
+            // full_concept has the best conversion rank, error the lowest
+            // used to give priority to the functions
+            struct error
+            {
+                operator void*() const noexcept
+                {
+                    WPI_MEMORY_UNREACHABLE(
+                        "this is just to hide an error and move static_assert to the front");
+                    return nullptr;
+                }
+            };
+            struct std_concept : error
+            {
+            };
+            struct min_concept : std_concept
+            {
+            };
+            struct full_concept : min_concept
+            {
+            };
+
+            // used to delay assert in handle_error() until instantiation
+            template <typename T>
+            struct invalid_allocator_concept
+            {
+                static const bool error = false;
+            };
+
+            //=== allocator_type ===//
+            // if Allocator has a member template `rebind`, use that to rebind to `char`
+            // else if Allocator has a member `value_type`, rebind by changing argument
+            // else does nothing
+            template <class Allocator>
+            auto rebind_impl(int) -> typename Allocator::template rebind<char>::other&;
+
+            template <class Allocator, typename T>
+            struct allocator_rebinder
+            {
+                using type = Allocator&;
+            };
+
+            template <template <typename, typename...> class Alloc, typename U, typename... Args,
+                      typename T>
+            struct allocator_rebinder<Alloc<U, Args...>, T>
+            {
+                using type = Alloc<T, Args...>&;
+            };
+
+            template <class Allocator, typename = typename Allocator::value_type>
+            auto rebind_impl(char) -> typename allocator_rebinder<Allocator, char>::type;
+
+            template <class Allocator>
+            auto rebind_impl(...) -> Allocator&;
+
+            template <class Allocator>
+            struct allocator_type_impl // required for MSVC
+            {
+                using type = decltype(rebind_impl<Allocator>(0));
+            };
+
+            template <class Allocator>
+            using allocator_type =
+                typename std::decay<typename allocator_type_impl<Allocator>::type>::type;
+
+            //=== is_stateful ===//
+            // first try to access Allocator::is_stateful,
+            // then use whether or not the type is empty
+            template <class Allocator>
+            auto is_stateful(full_concept) -> decltype(typename Allocator::is_stateful{});
+
+            template <class Allocator, bool IsEmpty>
+            struct is_stateful_impl;
+
+            template <class Allocator>
+            struct is_stateful_impl<Allocator, true>
+            {
+                static_assert(std::is_default_constructible<Allocator>::value,
+                              "RawAllocator is empty but not default constructible ."
+                              "This means it is not a stateless allocator. "
+                              "If this is actually intended provide the appropriate is_stateful "
+                              "typedef in your class.");
+                using type = std::false_type;
+            };
+
+            template <class Allocator>
+            struct is_stateful_impl<Allocator, false>
+            {
+                using type = std::true_type;
+            };
+
+            template <class Allocator>
+            auto is_stateful(min_concept) ->
+                typename is_stateful_impl<Allocator, std::is_empty<Allocator>::value>::type;
+
+            //=== allocate_node() ===//
+            // first try Allocator::allocate_node
+            // then assume std_allocator and call Allocator::allocate
+            // then error
+            template <class Allocator>
+            auto allocate_node(full_concept, Allocator& alloc, std::size_t size,
+                               std::size_t alignment)
+                -> WPI_AUTO_RETURN_TYPE(alloc.allocate_node(size, alignment), void*)
+
+                    template <class Allocator>
+                    auto allocate_node(std_concept, Allocator& alloc, std::size_t size, std::size_t)
+                        -> WPI_AUTO_RETURN(static_cast<void*>(alloc.allocate(size)))
+
+                            template <class Allocator>
+                            error allocate_node(error, Allocator&, std::size_t, std::size_t)
+            {
+                static_assert(invalid_allocator_concept<Allocator>::error,
+                              "type is not a RawAllocator as it does not provide: void* "
+                              "allocate_node(std::size_t, "
+                              "std::size_t)");
+                return {};
+            }
+
+            //=== deallocate_node() ===//
+            // first try Allocator::deallocate_node
+            // then assume std_allocator and call Allocator::deallocate
+            // then error
+            template <class Allocator>
+            auto deallocate_node(full_concept, Allocator& alloc, void* ptr, std::size_t size,
+                                 std::size_t alignment) noexcept
+                -> WPI_AUTO_RETURN_TYPE(alloc.deallocate_node(ptr, size, alignment), void)
+
+                    template <class Allocator>
+                    auto deallocate_node(std_concept, Allocator& alloc, void* ptr, std::size_t size,
+                                         std::size_t) noexcept
+                -> WPI_AUTO_RETURN_TYPE(alloc.deallocate(static_cast<char*>(ptr), size), void)
+
+                    template <class Allocator>
+                    error deallocate_node(error, Allocator&, void*, std::size_t, std::size_t)
+            {
+                static_assert(invalid_allocator_concept<Allocator>::error,
+                              "type is not a RawAllocator as it does not provide: void "
+                              "deallocate_node(void*, std::size_t, "
+                              "std::size_t)");
+                return error{};
+            }
+
+            //=== allocate_array() ===//
+            // first try Allocator::allocate_array
+            // then forward to allocate_node()
+            template <class Allocator>
+            auto allocate_array(full_concept, Allocator& alloc, std::size_t count, std::size_t size,
+                                std::size_t alignment)
+                -> WPI_AUTO_RETURN_TYPE(alloc.allocate_array(count, size, alignment), void*)
+
+                    template <class Allocator>
+                    void* allocate_array(min_concept, Allocator& alloc, std::size_t count,
+                                         std::size_t size, std::size_t alignment)
+            {
+                return allocate_node(full_concept{}, alloc, count * size, alignment);
+            }
+
+            //=== deallocate_array() ===//
+            // first try Allocator::deallocate_array
+            // then forward to deallocate_node()
+            template <class Allocator>
+            auto deallocate_array(full_concept, Allocator& alloc, void* ptr, std::size_t count,
+                                  std::size_t size, std::size_t alignment) noexcept
+                -> WPI_AUTO_RETURN_TYPE(alloc.deallocate_array(ptr, count, size, alignment),
+                                              void)
+
+                    template <class Allocator>
+                    void deallocate_array(min_concept, Allocator& alloc, void* ptr,
+                                          std::size_t count, std::size_t size,
+                                          std::size_t alignment) noexcept
+            {
+                deallocate_node(full_concept{}, alloc, ptr, count * size, alignment);
+            }
+
+            //=== max_node_size() ===//
+            // first try Allocator::max_node_size()
+            // then return maximum value
+            template <class Allocator>
+            auto max_node_size(full_concept, const Allocator& alloc)
+                -> WPI_AUTO_RETURN_TYPE(alloc.max_node_size(), std::size_t)
+
+                    template <class Allocator>
+                    std::size_t max_node_size(min_concept, const Allocator&) noexcept
+            {
+                return std::size_t(-1);
+            }
+
+            //=== max_node_size() ===//
+            // first try Allocator::max_array_size()
+            // then forward to max_node_size()
+            template <class Allocator>
+            auto max_array_size(full_concept, const Allocator& alloc)
+                -> WPI_AUTO_RETURN_TYPE(alloc.max_array_size(), std::size_t)
+
+                    template <class Allocator>
+                    std::size_t max_array_size(min_concept, const Allocator& alloc)
+            {
+                return max_node_size(full_concept{}, alloc);
+            }
+
+            //=== max_alignment() ===//
+            // first try Allocator::max_alignment()
+            // then return detail::max_alignment
+            template <class Allocator>
+            auto max_alignment(full_concept, const Allocator& alloc)
+                -> WPI_AUTO_RETURN_TYPE(alloc.max_alignment(), std::size_t)
+
+                    template <class Allocator>
+                    std::size_t max_alignment(min_concept, const Allocator&)
+            {
+                return detail::max_alignment;
+            }
+        } // namespace traits_detail
+
+        /// The default specialization of the allocator_traits for a \concept{concept_rawallocator,RawAllocator}.
+        /// See the last link for the requirements on types that do not specialize this class and the interface documentation.
+        /// Any specialization must provide the same interface.
+        /// \ingroup core
+        template <class Allocator>
+        class allocator_traits
+        {
+        public:
+            using allocator_type = traits_detail::allocator_type<Allocator>;
+            using is_stateful =
+                decltype(traits_detail::is_stateful<Allocator>(traits_detail::full_concept{}));
+
+            static void* allocate_node(allocator_type& state, std::size_t size,
+                                       std::size_t alignment)
+            {
+                static_assert(allocator_is_raw_allocator<Allocator>::value,
+                              "Allocator cannot be used as RawAllocator because it provides custom "
+                              "construct()/destroy()");
+                return traits_detail::allocate_node(traits_detail::full_concept{}, state, size,
+                                                    alignment);
+            }
+
+            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size,
+                                        std::size_t alignment)
+            {
+                static_assert(allocator_is_raw_allocator<Allocator>::value,
+                              "Allocator cannot be used as RawAllocator because it provides custom "
+                              "construct()/destroy()");
+                return traits_detail::allocate_array(traits_detail::full_concept{}, state, count,
+                                                     size, alignment);
+            }
+
+            static void deallocate_node(allocator_type& state, void* node, std::size_t size,
+                                        std::size_t alignment) noexcept
+            {
+                static_assert(allocator_is_raw_allocator<Allocator>::value,
+                              "Allocator cannot be used as RawAllocator because it provides custom "
+                              "construct()/destroy()");
+                traits_detail::deallocate_node(traits_detail::full_concept{}, state, node, size,
+                                               alignment);
+            }
+
+            static void deallocate_array(allocator_type& state, void* array, std::size_t count,
+                                         std::size_t size, std::size_t alignment) noexcept
+            {
+                static_assert(allocator_is_raw_allocator<Allocator>::value,
+                              "Allocator cannot be used as RawAllocator because it provides custom "
+                              "construct()/destroy()");
+                traits_detail::deallocate_array(traits_detail::full_concept{}, state, array, count,
+                                                size, alignment);
+            }
+
+            static std::size_t max_node_size(const allocator_type& state)
+            {
+                static_assert(allocator_is_raw_allocator<Allocator>::value,
+                              "Allocator cannot be used as RawAllocator because it provides custom "
+                              "construct()/destroy()");
+                return traits_detail::max_node_size(traits_detail::full_concept{}, state);
+            }
+
+            static std::size_t max_array_size(const allocator_type& state)
+            {
+                static_assert(allocator_is_raw_allocator<Allocator>::value,
+                              "Allocator cannot be used as RawAllocator because it provides custom "
+                              "construct()/destroy()");
+                return traits_detail::max_array_size(traits_detail::full_concept{}, state);
+            }
+
+            static std::size_t max_alignment(const allocator_type& state)
+            {
+                static_assert(allocator_is_raw_allocator<Allocator>::value,
+                              "Allocator cannot be used as RawAllocator because it provides custom "
+                              "construct()/destroy()");
+                return traits_detail::max_alignment(traits_detail::full_concept{}, state);
+            }
+
+#if !defined(DOXYGEN)
+            using foonathan_memory_default_traits = std::true_type;
+#endif
+        };
+
+        namespace detail
+        {
+            template <class RawAllocator>
+            typename allocator_traits<RawAllocator>::foonathan_memory_default_traits
+                alloc_uses_default_traits(RawAllocator&);
+
+            std::false_type alloc_uses_default_traits(...);
+
+            template <typename T>
+            struct has_invalid_alloc_function
+            : std::is_same<decltype(
+                               traits_detail::allocate_node(traits_detail::full_concept{},
+                                                            std::declval<typename allocator_traits<
+                                                                T>::allocator_type&>(),
+                                                            0, 0)),
+                           traits_detail::error>
+            {
+            };
+
+            template <typename T>
+            struct has_invalid_dealloc_function
+            : std::is_same<
+                  decltype(traits_detail::deallocate_node(traits_detail::full_concept{},
+                                                          std::declval<typename allocator_traits<
+                                                              T>::allocator_type&>(),
+                                                          nullptr, 0, 0)),
+                  traits_detail::error>
+            {
+            };
+
+            template <typename T, class DefaultTraits>
+            struct is_raw_allocator : std::true_type
+            {
+            };
+
+            template <typename T>
+            struct is_raw_allocator<T, std::integral_constant<bool, true>>
+            : std::integral_constant<bool, allocator_is_raw_allocator<T>::value
+                                               && !(has_invalid_alloc_function<T>::value
+                                                    || has_invalid_dealloc_function<T>::value)>
+            {
+            };
+        } // namespace detail
+
+        /// Traits that check whether a type models concept \concept{concept_rawallocator,RawAllocator}.<br>
+        /// It must either provide the necessary functions for the default traits specialization or has specialized it.
+        /// \ingroup core
+        template <typename T>
+        struct is_raw_allocator
+        : detail::is_raw_allocator<T,
+                                   decltype(detail::alloc_uses_default_traits(std::declval<T&>()))>
+        {
+        };
+
+        namespace traits_detail
+        {
+            //=== try_allocate_node() ===//
+            // try Allocator::try_allocate_node
+            // otherwise error
+            template <class Allocator>
+            auto try_allocate_node(full_concept, Allocator& alloc, std::size_t size,
+                                   std::size_t alignment) noexcept
+                -> WPI_AUTO_RETURN_TYPE(alloc.try_allocate_node(size, alignment), void*)
+
+                    template <class Allocator>
+                    error try_allocate_node(error, Allocator&, std::size_t, std::size_t)
+            {
+                static_assert(invalid_allocator_concept<Allocator>::error,
+                              "type is not a composable RawAllocator as it does not provide: void* "
+                              "try_allocate_node(std::size_t, "
+                              "std::size_t)");
+                return {};
+            }
+
+            //=== try_deallocate_node() ===//
+            // try Allocator::try_deallocate_node
+            // otherwise error
+            template <class Allocator>
+            auto try_deallocate_node(full_concept, Allocator& alloc, void* ptr, std::size_t size,
+                                     std::size_t alignment) noexcept
+                -> WPI_AUTO_RETURN_TYPE(alloc.try_deallocate_node(ptr, size, alignment), bool)
+
+                    template <class Allocator>
+                    error try_deallocate_node(error, Allocator&, void*, std::size_t, std::size_t)
+            {
+                static_assert(invalid_allocator_concept<Allocator>::error,
+                              "type is not a composable RawAllocator as it does not provide: bool "
+                              "try_deallocate_node(void*, std::size_t, "
+                              "std::size_t)");
+                return error{};
+            }
+
+            //=== try_allocate_array() ===//
+            // first try Allocator::try_allocate_array
+            // then forward to try_allocate_node()
+            template <class Allocator>
+            auto try_allocate_array(full_concept, Allocator& alloc, std::size_t count,
+                                    std::size_t size, std::size_t alignment) noexcept
+                -> WPI_AUTO_RETURN_TYPE(alloc.try_allocate_array(count, size, alignment),
+                                              void*)
+
+                    template <class Allocator>
+                    void* try_allocate_array(min_concept, Allocator& alloc, std::size_t count,
+                                             std::size_t size, std::size_t alignment)
+            {
+                return try_allocate_node(full_concept{}, alloc, count * size, alignment);
+            }
+
+            //=== try_deallocate_array() ===//
+            // first try Allocator::try_deallocate_array
+            // then forward to try_deallocate_node()
+            template <class Allocator>
+            auto try_deallocate_array(full_concept, Allocator& alloc, void* ptr, std::size_t count,
+                                      std::size_t size, std::size_t alignment) noexcept
+                -> WPI_AUTO_RETURN_TYPE(alloc.try_deallocate_array(ptr, count, size,
+                                                                         alignment),
+                                              bool)
+
+                    template <class Allocator>
+                    bool try_deallocate_array(min_concept, Allocator& alloc, void* ptr,
+                                              std::size_t count, std::size_t size,
+                                              std::size_t alignment) noexcept
+            {
+                return try_deallocate_node(full_concept{}, alloc, ptr, count * size, alignment);
+            }
+        } // namespace traits_detail
+
+        /// The default specialization of the composable_allocator_traits for a \concept{concept_composableallocator,ComposableAllocator}.
+        /// See the last link for the requirements on types that do not specialize this class and the interface documentation.
+        /// Any specialization must provide the same interface.
+        /// \ingroup core
+        template <class Allocator>
+        class composable_allocator_traits
+        {
+        public:
+            using allocator_type = typename allocator_traits<Allocator>::allocator_type;
+
+            static void* try_allocate_node(allocator_type& state, std::size_t size,
+                                           std::size_t alignment) noexcept
+            {
+                static_assert(is_raw_allocator<Allocator>::value,
+                              "ComposableAllocator must be RawAllocator");
+                return traits_detail::try_allocate_node(traits_detail::full_concept{}, state, size,
+                                                        alignment);
+            }
+
+            static void* try_allocate_array(allocator_type& state, std::size_t count,
+                                            std::size_t size, std::size_t alignment) noexcept
+            {
+                static_assert(is_raw_allocator<Allocator>::value,
+                              "ComposableAllocator must be RawAllocator");
+                return traits_detail::try_allocate_array(traits_detail::full_concept{}, state,
+                                                         count, size, alignment);
+            }
+
+            static bool try_deallocate_node(allocator_type& state, void* node, std::size_t size,
+                                            std::size_t alignment) noexcept
+            {
+                static_assert(is_raw_allocator<Allocator>::value,
+                              "ComposableAllocator must be RawAllocator");
+                return traits_detail::try_deallocate_node(traits_detail::full_concept{}, state,
+                                                          node, size, alignment);
+            }
+
+            static bool try_deallocate_array(allocator_type& state, void* array, std::size_t count,
+                                             std::size_t size, std::size_t alignment) noexcept
+            {
+                static_assert(is_raw_allocator<Allocator>::value,
+                              "ComposableAllocator must be RawAllocator");
+                return traits_detail::try_deallocate_array(traits_detail::full_concept{}, state,
+                                                           array, count, size, alignment);
+            }
+
+#if !defined(DOXYGEN)
+            using foonathan_memory_default_traits = std::true_type;
+#endif
+        };
+
+        namespace detail
+        {
+            template <class RawAllocator>
+            typename composable_allocator_traits<RawAllocator>::foonathan_memory_default_traits
+                composable_alloc_uses_default_traits(RawAllocator&);
+
+            std::false_type composable_alloc_uses_default_traits(...);
+
+            template <typename T>
+            struct has_invalid_try_alloc_function
+            : std::is_same<
+                  decltype(traits_detail::try_allocate_node(traits_detail::full_concept{},
+                                                            std::declval<typename allocator_traits<
+                                                                T>::allocator_type&>(),
+                                                            0, 0)),
+                  traits_detail::error>
+            {
+            };
+
+            template <typename T>
+            struct has_invalid_try_dealloc_function
+            : std::is_same<
+                  decltype(
+                      traits_detail::try_deallocate_node(traits_detail::full_concept{},
+                                                         std::declval<typename allocator_traits<
+                                                             T>::allocator_type&>(),
+                                                         nullptr, 0, 0)),
+                  traits_detail::error>
+            {
+            };
+
+            template <typename T, class DefaultTraits>
+            struct is_composable_allocator : memory::is_raw_allocator<T>
+            {
+            };
+
+            template <typename T>
+            struct is_composable_allocator<T, std::integral_constant<bool, true>>
+            : std::integral_constant<bool, memory::is_raw_allocator<T>::value
+                                               && !(has_invalid_try_alloc_function<T>::value
+                                                    || has_invalid_try_dealloc_function<T>::value)>
+            {
+            };
+        } // namespace detail
+
+        /// Traits that check whether a type models concept \concept{concept_rawallocator,ComposableAllocator}.<br>
+        /// It must be a \concept{concept_rawallocator,RawAllocator} and either provide the necessary functions for the default traits specialization or has specialized it.
+        /// \ingroup core
+        template <typename T>
+        struct is_composable_allocator
+        : detail::is_composable_allocator<T, decltype(detail::composable_alloc_uses_default_traits(
+                                                 std::declval<T&>()))>
+        {
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_ALLOCATOR_TRAITS_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/config.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/config.hpp
new file mode 100644
index 0000000..067ecd2
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/config.hpp
@@ -0,0 +1,148 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+/// \file
+/// Configuration macros.
+
+#ifndef WPI_MEMORY_CONFIG_HPP_INCLUDED
+#define WPI_MEMORY_CONFIG_HPP_INCLUDED
+
+#include <cstddef>
+
+#if !defined(DOXYGEN)
+#define WPI_MEMORY_IMPL_IN_CONFIG_HPP
+#include "config_impl.hpp"
+#undef WPI_MEMORY_IMPL_IN_CONFIG_HPP
+#endif
+
+// exception support
+#ifndef WPI_HAS_EXCEPTION_SUPPORT
+#if defined(__GNUC__) && !defined(__EXCEPTIONS)
+#define WPI_HAS_EXCEPTION_SUPPORT 0
+#elif defined(_MSC_VER) && !_HAS_EXCEPTIONS
+#define WPI_HAS_EXCEPTION_SUPPORT 0
+#else
+#define WPI_HAS_EXCEPTION_SUPPORT 1
+#endif
+#endif
+
+#if WPI_HAS_EXCEPTION_SUPPORT
+#define WPI_THROW(Ex) throw(Ex)
+#else
+#include <cstdlib>
+#define WPI_THROW(Ex) ((Ex), std::abort())
+#endif
+
+// hosted implementation
+#ifndef WPI_HOSTED_IMPLEMENTATION
+#if !_MSC_VER && !__STDC_HOSTED__
+#define WPI_HOSTED_IMPLEMENTATION 0
+#else
+#define WPI_HOSTED_IMPLEMENTATION 1
+#endif
+#endif
+
+// log prefix
+#define WPI_MEMORY_LOG_PREFIX "wpi::memory"
+
+// version
+#define WPI_MEMORY_VERSION                                                                   \
+    (WPI_MEMORY_VERSION_MAJOR * 100 + WPI_MEMORY_VERSION_MINOR)
+
+// use this macro to mark implementation-defined types
+// gives it more semantics and useful with doxygen
+// add PREDEFINED: WPI_IMPL_DEFINED():=implementation_defined
+#ifndef WPI_IMPL_DEFINED
+#define WPI_IMPL_DEFINED(...) __VA_ARGS__
+#endif
+
+// use this macro to mark base class which only purpose is EBO
+// gives it more semantics and useful with doxygen
+// add PREDEFINED: WPI_EBO():=
+#ifndef WPI_EBO
+#define WPI_EBO(...) __VA_ARGS__
+#endif
+
+#ifndef WPI_ALIAS_TEMPLATE
+// defines a template alias
+// usage:
+// template <typename T>
+// WPI_ALIAS_TEMPLATE(bar, foo<T, int>);
+// useful for doxygen
+#ifdef DOXYGEN
+#define WPI_ALIAS_TEMPLATE(Name, ...)                                                        \
+    class Name : public __VA_ARGS__                                                                \
+    {                                                                                              \
+    }
+#else
+#define WPI_ALIAS_TEMPLATE(Name, ...) using Name = __VA_ARGS__
+#endif
+#endif
+
+#ifdef DOXYGEN
+// dummy definitions of config macros for doxygen
+
+/// The major version number.
+/// \ingroup core
+#define WPI_MEMORY_VERSION_MAJOR 1
+
+/// The minor version number.
+/// \ingroup core
+#define WPI_MEMORY_VERSION_MINOR 1
+
+/// The total version number of the form \c Mmm.
+/// \ingroup core
+#define WPI_MEMORY_VERSION                                                                   \
+    (WPI_MEMORY_VERSION_MAJOR * 100 + WPI_MEMORY_VERSION_MINOR)
+
+/// Whether or not the allocation size will be checked,
+/// i.e. the \ref wpi::memory::bad_allocation_size thrown.
+/// \ingroup core
+#define WPI_MEMORY_CHECK_ALLOCATION_SIZE 1
+
+/// Whether or not internal assertions in the library are enabled.
+/// \ingroup core
+#define WPI_MEMORY_DEBUG_ASSERT 1
+
+/// Whether or not allocated memory will be filled with special values.
+/// \ingroup core
+#define WPI_MEMORY_DEBUG_FILL 1
+
+/// The size of the fence memory, it has no effect if \ref WPI_MEMORY_DEBUG_FILL is \c false.
+/// \note For most allocators, the actual value doesn't matter and they use appropriate defaults to ensure alignment etc.
+/// \ingroup core
+#define WPI_MEMORY_DEBUG_FENCE 1
+
+/// Whether or not leak checking is enabled.
+/// \ingroup core
+#define WPI_MEMORY_DEBUG_LEAK_CHECK 1
+
+/// Whether or not the deallocation functions will check for pointers that were never allocated by an allocator.
+/// \ingroup core
+#define WPI_MEMORY_DEBUG_POINTER_CHECK 1
+
+/// Whether or not the deallocation functions will check for double free errors.
+/// This option makes no sense if \ref WPI_MEMORY_DEBUG_POINTER_CHECK is \c false.
+/// \ingroup core
+#define WPI_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK 1
+
+/// Whether or not everything is in namespace <tt>wpi::memory</tt>.
+/// If \c false, a namespace alias <tt>namespace memory = wpi::memory</tt> is automatically inserted into each header,
+/// allowing to qualify everything with <tt>wpi::</tt>.
+/// \note This option breaks in combination with using <tt>using namespace wpi;</tt>.
+/// \ingroup core
+#define WPI_MEMORY_NAMESPACE_PREFIX 1
+
+/// The mode of the automatic \ref wpi::memory::temporary_stack creation.
+/// Set to `2` to enable automatic lifetime management of the per-thread stack through nifty counter.
+/// Then all memory will be freed upon program termination automatically.
+/// Set to `1` to disable automatic lifetime managment of the per-thread stack,
+/// requires managing it through the \ref wpi::memory::temporary_stack_initializer.
+/// Set to `0` to disable the per-thread stack completely.
+/// \ref get_temporary_stack() will abort the program upon call.
+/// \ingroup allocator
+#define WPI_MEMORY_TEMPORARY_STACK_MODE 2
+#endif
+
+#endif // WPI_MEMORY_CONFIG_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/config_impl.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/config_impl.hpp
new file mode 100644
index 0000000..1f72375
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/config_impl.hpp
@@ -0,0 +1,34 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+// Copyright (C) 2015-2020 Jonathan Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#pragma once
+
+#include <cstddef>
+
+//=== options ===//
+#define WPI_MEMORY_CHECK_ALLOCATION_SIZE 1
+#define WPI_MEMORY_IMPL_DEFAULT_ALLOCATOR heap_allocator
+#ifdef NDEBUG
+#define WPI_MEMORY_DEBUG_ASSERT 0
+#define WPI_MEMORY_DEBUG_FILL 0
+#define WPI_MEMORY_DEBUG_FENCE 0
+#define WPI_MEMORY_DEBUG_LEAK_CHECK 0
+#define WPI_MEMORY_DEBUG_POINTER_CHECK 0
+#define WPI_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK 0
+#else
+#define WPI_MEMORY_DEBUG_ASSERT 1
+#define WPI_MEMORY_DEBUG_FILL 1
+#define WPI_MEMORY_DEBUG_FENCE 8
+#define WPI_MEMORY_DEBUG_LEAK_CHECK 1
+#define WPI_MEMORY_DEBUG_POINTER_CHECK 1
+#define WPI_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK 1
+#endif
+#define WPI_MEMORY_EXTERN_TEMPLATE 1
+#define WPI_MEMORY_TEMPORARY_STACK_MODE 2
+
+#define WPI_MEMORY_NO_NODE_SIZE 1
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/container.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/container.hpp
new file mode 100644
index 0000000..fd1547f
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/container.hpp
@@ -0,0 +1,362 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_CONTAINER_HPP_INCLUDED
+#define WPI_MEMORY_CONTAINER_HPP_INCLUDED
+
+/// \file
+/// Aliasas for STL containers using a certain \concept{concept_rawallocator,RawAllocator}.
+/// \note Only available on a hosted implementation.
+
+#include "config.hpp"
+#if !WPI_HOSTED_IMPLEMENTATION
+#error "This header is only available for a hosted implementation."
+#endif
+
+#include <functional>
+#include <utility>
+
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <map>
+#include <queue>
+#include <scoped_allocator>
+#include <set>
+#include <stack>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "std_allocator.hpp"
+#include "threading.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// \ingroup adapter
+        /// @{
+
+        /// Alias template for an STL container that uses a certain
+        /// \concept{concept_rawallocator,RawAllocator}. It is just a shorthand for a passing in the \c
+        /// RawAllocator wrapped in a \ref wpi::memory::std_allocator.
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(vector, std::vector<T, std_allocator<T, RawAllocator>>);
+
+        /// Same as above but uses \c std::scoped_allocator_adaptor so the allocator is inherited by all
+        /// nested containers.
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            vector_scoped_alloc,
+            std::vector<T, std::scoped_allocator_adaptor<std_allocator<T, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(deque, std::deque<T, std_allocator<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            deque_scoped_alloc,
+            std::deque<T, std::scoped_allocator_adaptor<std_allocator<T, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(list, std::list<T, std_allocator<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            list_scoped_alloc,
+            std::list<T, std::scoped_allocator_adaptor<std_allocator<T, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(forward_list,
+                                 std::forward_list<T, std_allocator<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            forward_list_scoped_alloc,
+            std::forward_list<T, std::scoped_allocator_adaptor<std_allocator<T, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(set, std::set<T, std::less<T>, std_allocator<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            set_scoped_alloc,
+            std::set<T, std::less<T>,
+                     std::scoped_allocator_adaptor<std_allocator<T, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(multiset,
+                                 std::multiset<T, std::less<T>, std_allocator<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            multiset_scoped_alloc,
+            std::multiset<T, std::less<T>,
+                          std::scoped_allocator_adaptor<std_allocator<T, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename Key, typename Value, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            map, std::map<Key, Value, std::less<Key>,
+                          std_allocator<std::pair<const Key, Value>, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename Key, typename Value, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            map_scoped_alloc,
+            std::map<Key, Value, std::less<Key>,
+                     std::scoped_allocator_adaptor<
+                         std_allocator<std::pair<const Key, Value>, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename Key, typename Value, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            multimap, std::multimap<Key, Value, std::less<Key>,
+                                    std_allocator<std::pair<const Key, Value>, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename Key, typename Value, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            multimap_scoped_alloc,
+            std::multimap<Key, Value, std::less<Key>,
+                          std::scoped_allocator_adaptor<
+                              std_allocator<std::pair<const Key, Value>, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            unordered_set,
+            std::unordered_set<T, std::hash<T>, std::equal_to<T>, std_allocator<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            unordered_set_scoped_alloc,
+            std::unordered_set<T, std::hash<T>, std::equal_to<T>,
+                               std::scoped_allocator_adaptor<std_allocator<T, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(unordered_multiset,
+                                 std::unordered_multiset<T, std::hash<T>, std::equal_to<T>,
+                                                         std_allocator<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            unordered_multiset_scoped_alloc,
+            std::unordered_multiset<T, std::hash<T>, std::equal_to<T>,
+                                    std::scoped_allocator_adaptor<std_allocator<T, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename Key, typename Value, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            unordered_map,
+            std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>,
+                               std_allocator<std::pair<const Key, Value>, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename Key, typename Value, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            unordered_map_scoped_alloc,
+            std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>,
+                               std::scoped_allocator_adaptor<
+                                   std_allocator<std::pair<const Key, Value>, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename Key, typename Value, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            unordered_multimap,
+            std::unordered_multimap<Key, Value, std::hash<Key>, std::equal_to<Key>,
+                                    std_allocator<std::pair<const Key, Value>, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename Key, typename Value, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            unordered_multimap_scoped_alloc,
+            std::unordered_multimap<Key, Value, std::hash<Key>, std::equal_to<Key>,
+                                    std::scoped_allocator_adaptor<
+                                        std_allocator<std::pair<const Key, Value>, RawAllocator>>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(stack, std::stack<T, deque<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(stack_scoped_alloc,
+                                 std::stack<T, deque_scoped_alloc<T, RawAllocator>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(queue, std::queue<T, deque<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(queue_scoped_alloc,
+                                 std::queue<T, deque_scoped_alloc<T, RawAllocator>>);
+
+        /// \copydoc vector
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(priority_queue, std::priority_queue<T, deque<T, RawAllocator>>);
+        /// \copydoc vector_scoped_alloc
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(priority_queue_scoped_alloc,
+                                 std::priority_queue<T, deque_scoped_alloc<T, RawAllocator>>);
+
+        /// \copydoc vector
+        template <class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            string,
+            std::basic_string<char, std::char_traits<char>, std_allocator<char, RawAllocator>>);
+        /// @}
+
+        /// @{
+        /// Convenience function to create a container adapter using a certain
+        /// \concept{concept_rawallocator,RawAllocator}. \returns An empty adapter with an
+        /// implementation container using a reference to a given allocator. \ingroup adapter
+        template <typename T, class RawAllocator, class Container = deque<T, RawAllocator>>
+        std::stack<T, Container> make_stack(RawAllocator& allocator)
+        {
+            return std::stack<T, Container>{Container(allocator)};
+        }
+
+        /// \copydoc make_stack
+        template <typename T, class RawAllocator, class Container = deque<T, RawAllocator>>
+        std::queue<T, Container> make_queue(RawAllocator& allocator)
+        {
+            return std::queue<T, Container>{Container(allocator)};
+        }
+
+        /// \copydoc make_stack
+        template <typename T, class RawAllocator, class Container = deque<T, RawAllocator>,
+                  class Compare = std::less<T>>
+        std::priority_queue<T, Container, Compare> make_priority_queue(RawAllocator& allocator,
+                                                                       Compare       comp = {})
+        {
+            return std::priority_queue<T, Container, Compare>{detail::move(comp),
+                                                              Container(allocator)};
+        }
+        /// @}
+
+#if !defined(DOXYGEN)
+
+#include "detail/container_node_sizes.hpp"
+
+#if !defined(WPI_MEMORY_NO_NODE_SIZE)
+        /// \exclude
+        namespace detail
+        {
+            template <typename T, class StdAllocator>
+            struct shared_ptr_node_size
+            {
+                static_assert(sizeof(T) != sizeof(T), "unsupported allocator type");
+            };
+
+            template <typename T, class RawAllocator>
+            struct shared_ptr_node_size<T, std_allocator<T, RawAllocator>>
+            : std::conditional<allocator_traits<RawAllocator>::is_stateful::value,
+                               memory::shared_ptr_stateful_node_size<T>,
+                               memory::shared_ptr_stateless_node_size<T>>::type
+            {
+                static_assert(sizeof(std_allocator<T, RawAllocator>) <= sizeof(void*),
+                              "fix node size debugger");
+            };
+
+        } // namespace detail
+
+        template <typename T, class StdAllocator>
+        struct shared_ptr_node_size : detail::shared_ptr_node_size<T, StdAllocator>
+        {
+        };
+#endif
+
+#else
+        /// \ingroup adapter
+        /// @{
+
+        /// Contains the node size of a node based STL container with a specific type.
+        /// These classes are auto-generated and only available if the tools are build and without
+        /// cross-compiling.
+        template <typename T>
+        struct forward_list_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct list_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct set_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct multiset_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct unordered_set_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct unordered_multiset_node_size
+        : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct map_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct multimap_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct unordered_map_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T>
+        struct unordered_multimap_node_size
+        : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+
+        /// \copydoc forward_list_node_size
+        template <typename T, class StdAllocator>
+        struct shared_ptr_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+/// @}
+#endif
+
+#if !defined(WPI_MEMORY_NO_NODE_SIZE)
+        /// The node size required by \ref allocate_shared.
+        /// \note This is similar to \ref shared_ptr_node_size but takes a
+        /// \concept{concept_rawallocator,RawAllocator} instead.
+        template <typename T, class RawAllocator>
+        struct allocate_shared_node_size : shared_ptr_node_size<T, std_allocator<T, RawAllocator>>
+        {
+        };
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_CONTAINER_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/debugging.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/debugging.hpp
new file mode 100644
index 0000000..b04050f
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/debugging.hpp
@@ -0,0 +1,114 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DEBUGGING_HPP_INCLUDED
+#define WPI_MEMORY_DEBUGGING_HPP_INCLUDED
+
+/// \file
+/// Debugging facilities.
+
+#include "config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        struct allocator_info;
+
+        /// The magic values that are used for debug filling.
+        /// If \ref WPI_MEMORY_DEBUG_FILL is \c true, memory will be filled to help detect use-after-free or missing initialization errors.
+        /// These are the constants for the different types.
+        /// \ingroup core
+        enum class debug_magic : unsigned char
+        {
+            /// Marks internal memory used by the allocator - "allocated block".
+            internal_memory = 0xAB,
+            /// Marks internal memory currently not used by the allocator - "freed block".
+            internal_freed_memory = 0xFB,
+            /// Marks allocated, but not yet used memory - "clean memory".
+            new_memory = 0xCD,
+            /// Marks freed memory - "dead memory".
+            freed_memory = 0xDD,
+            /// Marks buffer memory used to ensure proper alignment.
+            /// This memory can also serve as \ref debug_magic::fence_memory.
+            alignment_memory = 0xED,
+            /// Marks buffer memory used to protect against overflow - "fence memory".
+            /// The option \ref WPI_MEMORY_DEBUG_FENCE controls the size of a memory fence that will be placed before or after a memory block.
+            /// It helps catching buffer overflows.
+            fence_memory = 0xFD
+        };
+
+        /// The type of the handler called when a memory leak is detected.
+        /// Leak checking can be controlled via the option \ref WPI_MEMORY_DEBUG_LEAK_CHECK
+        /// and only affects calls through the \ref allocator_traits, not direct calls.
+        /// The handler gets the \ref allocator_info and the amount of memory leaked.
+        /// This can also be negative, meaning that more memory has been freed than allocated.
+        /// \requiredbe A leak handler shall log the leak, abort the program, do nothing or anything else that seems appropriate.
+        /// It must not throw any exceptions since it is called in the cleanup process.
+        /// \defaultbe On a hosted implementation it logs the leak to \c stderr and returns, continuing execution.
+        /// On a freestanding implementation it does nothing.
+        /// \ingroup core
+        using leak_handler = void (*)(const allocator_info& info, std::ptrdiff_t amount);
+
+        /// Exchanges the \ref leak_handler.
+        /// \effects Sets \c h as the new \ref leak_handler in an atomic operation.
+        /// A \c nullptr sets the default \ref leak_handler.
+        /// \returns The previous \ref leak_handler. This is never \c nullptr.
+        /// \ingroup core
+        leak_handler set_leak_handler(leak_handler h);
+
+        /// Returns the \ref leak_handler.
+        /// \returns The current \ref leak_handler. This is never \c nullptr.
+        /// \ingroup core
+        leak_handler get_leak_handler();
+
+        /// The type of the handler called when an invalid pointer is passed to a deallocation function.
+        /// Pointer checking can be controlled via the options \ref WPI_MEMORY_DEBUG_POINTER_CHECK and \ref WPI_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK.
+        /// The handler gets the \ref allocator_info and the invalid pointer.
+        /// \requiredbe An invalid pointer handler shall terminate the program.
+        /// It must not throw any exceptions since it might be called in the cleanup process.
+        /// \defaultbe On a hosted implementation it logs the information to \c stderr and calls \c std::abort().
+        /// On a freestanding implementation it only calls \c std::abort().
+        /// \ingroup core
+        using invalid_pointer_handler = void (*)(const allocator_info& info, const void* ptr);
+
+        /// Exchanges the \ref invalid_pointer_handler.
+        /// \effects Sets \c h as the new \ref invalid_pointer_handler in an atomic operation.
+        /// A \c nullptr sets the default \ref invalid_pointer_handler.
+        /// \returns The previous \ref invalid_pointer_handler. This is never \c nullptr.
+        /// \ingroup core
+        invalid_pointer_handler set_invalid_pointer_handler(invalid_pointer_handler h);
+
+        /// Returns the \ref invalid_pointer_handler.
+        /// \returns The current \ref invalid_pointer_handler. This is never \c nullptr.
+        /// \ingroup core
+        invalid_pointer_handler get_invalid_pointer_handler();
+
+        /// The type of the handler called when a buffer under/overflow is detected.
+        /// If \ref WPI_MEMORY_DEBUG_FILL is \c true and \ref WPI_MEMORY_DEBUG_FENCE has a non-zero value
+        /// the allocator classes check if a write into the fence has occured upon deallocation.
+        /// The handler gets the memory block belonging to the corrupted fence, its size and the exact address.
+        /// \requiredbe A buffer overflow handler shall terminate the program.
+        /// It must not throw any exceptions since it me be called in the cleanup process.
+        /// \defaultbe On a hosted implementation it logs the information to \c stderr and calls \c std::abort().
+        /// On a freestanding implementation it only calls \c std::abort().
+        /// \ingroup core
+        using buffer_overflow_handler = void (*)(const void* memory, std::size_t size,
+                                                 const void* write_ptr);
+
+        /// Exchanges the \ref buffer_overflow_handler.
+        /// \effects Sets \c h as the new \ref buffer_overflow_handler in an atomic operation.
+        /// A \c nullptr sets the default \ref buffer_overflow_handler.
+        /// \returns The previous \ref buffer_overflow_handler. This is never \c nullptr.
+        /// \ingroup core
+        buffer_overflow_handler set_buffer_overflow_handler(buffer_overflow_handler h);
+
+        /// Returns the \ref buffer_overflow_handler.
+        /// \returns The current \ref buffer_overflow_handler. This is never \c nullptr.
+        /// \ingroup core
+        buffer_overflow_handler get_buffer_overflow_handler();
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DEBUGGING_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/default_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/default_allocator.hpp
new file mode 100644
index 0000000..107a641
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/default_allocator.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DEFAULT_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_DEFAULT_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// The typedef \ref wpi::memory::default_allocator.
+
+#include "config.hpp"
+#include "heap_allocator.hpp"
+#include "new_allocator.hpp"
+#include "static_allocator.hpp"
+#include "virtual_memory.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include "malloc_allocator.hpp"
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// The default \concept{concept_rawallocator,RawAllocator} that will be used as \concept{concept_blockallocator,BlockAllocator} in memory arenas.
+        /// Arena allocators like \ref memory_stack or \ref memory_pool allocate memory by subdividing a huge block.
+        /// They get a \concept{concept_blockallocator,BlockAllocator} that will be used for their internal allocation,
+        /// this type is the default value.
+        /// \requiredbe Its type can be changed via the CMake option \c WPI_MEMORY_DEFAULT_ALLCOATOR,
+        /// but it must be one of the following: \ref heap_allocator, \ref new_allocator, \ref malloc_allocator, \ref static_allocator, \ref virtual_memory_allocator.
+        /// \defaultbe The default is \ref heap_allocator.
+        /// \ingroup allocator
+        using default_allocator = WPI_IMPL_DEFINED(WPI_MEMORY_IMPL_DEFAULT_ALLOCATOR);
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DEFAULT_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/deleter.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/deleter.hpp
new file mode 100644
index 0000000..01c967c
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/deleter.hpp
@@ -0,0 +1,308 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DELETER_HPP_INCLUDED
+#define WPI_MEMORY_DELETER_HPP_INCLUDED
+
+/// \file
+/// \c Deleter classes using a \concept{concept_rawallocator,RawAllocator}.
+
+#include <type_traits>
+
+#include "allocator_storage.hpp"
+#include "config.hpp"
+#include "threading.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// A deleter class that deallocates the memory through a specified \concept{concept_rawallocator,RawAllocator}.
+        ///
+        /// It deallocates memory for a specified type but does not call its destructors.
+        /// \ingroup adapter
+        template <typename Type, class RawAllocator>
+        class allocator_deallocator : WPI_EBO(allocator_reference<RawAllocator>)
+        {
+            static_assert(!std::is_abstract<Type>::value,
+                          "use allocator_polymorphic_deallocator for storing base classes");
+
+        public:
+            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;
+            using value_type     = Type;
+
+            /// \effects Creates it without any associated allocator.
+            /// The deallocator must not be used if that is the case.
+            /// \notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.
+            allocator_deallocator() noexcept = default;
+
+            /// \effects Creates it by passing it an \ref allocator_reference.
+            /// It will store the reference to it and uses the referenced allocator object for the deallocation.
+            allocator_deallocator(allocator_reference<RawAllocator> alloc) noexcept
+            : allocator_reference<RawAllocator>(alloc)
+            {
+            }
+
+            /// \effects Deallocates the memory given to it.
+            /// Calls \c deallocate_node(pointer, sizeof(value_type), alignof(value_type)) on the referenced allocator object.
+            /// \requires The deallocator must not have been created by the default constructor.
+            void operator()(value_type* pointer) noexcept
+            {
+                this->deallocate_node(pointer, sizeof(value_type), alignof(value_type));
+            }
+
+            /// \returns The reference to the allocator.
+            /// It has the same type as the call to \ref allocator_reference::get_allocator().
+            /// \requires The deallocator must not be created by the default constructor.
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
+            {
+                return this->allocator_reference<allocator_type>::get_allocator();
+            }
+        };
+
+        /// Specialization of \ref allocator_deallocator for array types.
+        /// Otherwise the same behavior.
+        /// \ingroup adapter
+        template <typename Type, class RawAllocator>
+        class allocator_deallocator<Type[], RawAllocator>
+        : WPI_EBO(allocator_reference<RawAllocator>)
+        {
+            static_assert(!std::is_abstract<Type>::value, "must not create polymorphic arrays");
+
+        public:
+            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;
+            using value_type     = Type;
+
+            /// \effects Creates it without any associated allocator.
+            /// The deallocator must not be used if that is the case.
+            /// \notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.
+            allocator_deallocator() noexcept : size_(0u) {}
+
+            /// \effects Creates it by passing it an \ref allocator_reference and the size of the array that will be deallocated.
+            /// It will store the reference to the allocator and uses the referenced allocator object for the deallocation.
+            allocator_deallocator(allocator_reference<RawAllocator> alloc,
+                                  std::size_t                       size) noexcept
+            : allocator_reference<RawAllocator>(alloc), size_(size)
+            {
+            }
+
+            /// \effects Deallocates the memory given to it.
+            /// Calls \c deallocate_array(pointer, size, sizeof(value_type), alignof(value_type))
+            /// on the referenced allocator object with the size given in the constructor.
+            /// \requires The deallocator must not have been created by the default constructor.
+            void operator()(value_type* pointer) noexcept
+            {
+                this->deallocate_array(pointer, size_, sizeof(value_type), alignof(value_type));
+            }
+
+            /// \returns The reference to the allocator.
+            /// It has the same type as the call to \ref allocator_reference::get_allocator().
+            /// \requires The deallocator must not have been created by the default constructor.
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
+            {
+                return this->allocator_reference<allocator_type>::get_allocator();
+            }
+
+            /// \returns The size of the array that will be deallocated.
+            /// This is the same value as passed in the constructor, or `0` if it was created by the default constructor.
+            std::size_t array_size() const noexcept
+            {
+                return size_;
+            }
+
+        private:
+            std::size_t size_;
+        };
+
+        /// A deleter class that deallocates the memory of a derived type through a specified \concept{concept_rawallocator,RawAllocator}.
+        ///
+        /// It can only be created from a \ref allocator_deallocator and thus must only be used for smart pointers initialized by derived-to-base conversion of the pointer.
+        /// \ingroup adapter
+        template <typename BaseType, class RawAllocator>
+        class allocator_polymorphic_deallocator : WPI_EBO(allocator_reference<RawAllocator>)
+        {
+        public:
+            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;
+            using value_type     = BaseType;
+
+            /// \effects Creates it from a deallocator for a derived type.
+            /// It will deallocate the memory as if done by the derived type.
+            template <typename T, WPI_REQUIRES((std::is_base_of<BaseType, T>::value))>
+            allocator_polymorphic_deallocator(allocator_deallocator<T, RawAllocator> dealloc)
+            : allocator_reference<RawAllocator>(dealloc.get_allocator()),
+              derived_size_(sizeof(T)),
+              derived_alignment_(alignof(T))
+            {
+            }
+
+            /// \effects Deallocates the memory given to it.
+            /// Calls \c deallocate_node(pointer, size, alignment) on the referenced allocator object,
+            /// where \c size and \c alignment are the values of the type it was created with.
+            void operator()(value_type* pointer) noexcept
+            {
+                this->deallocate_node(pointer, derived_size_, derived_alignment_);
+            }
+
+            /// \returns The reference to the allocator.
+            /// It has the same type as the call to \ref allocator_reference::get_allocator().
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
+            {
+                return this->allocator_reference<allocator_type>::get_allocator();
+            }
+
+        private:
+            std::size_t derived_size_, derived_alignment_;
+        };
+
+        /// Similar to \ref allocator_deallocator but calls the destructors of the object.
+        /// Otherwise behaves the same.
+        /// \ingroup adapter
+        template <typename Type, class RawAllocator>
+        class allocator_deleter : WPI_EBO(allocator_reference<RawAllocator>)
+        {
+            static_assert(!std::is_abstract<Type>::value,
+                          "use allocator_polymorphic_deleter for storing base classes");
+
+        public:
+            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;
+            using value_type     = Type;
+
+            /// \effects Creates it without any associated allocator.
+            /// The deleter must not be used if that is the case.
+            /// \notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.
+            allocator_deleter() noexcept = default;
+
+            /// \effects Creates it by passing it an \ref allocator_reference.
+            /// It will store the reference to it and uses the referenced allocator object for the deallocation.
+            allocator_deleter(allocator_reference<RawAllocator> alloc) noexcept
+            : allocator_reference<RawAllocator>(alloc)
+            {
+            }
+
+            /// \effects Calls the destructor and deallocates the memory given to it.
+            /// Calls \c deallocate_node(pointer, sizeof(value_type), alignof(value_type))
+            /// on the referenced allocator object for the deallocation.
+            /// \requires The deleter must not have been created by the default constructor.
+            void operator()(value_type* pointer) noexcept
+            {
+                pointer->~value_type();
+                this->deallocate_node(pointer, sizeof(value_type), alignof(value_type));
+            }
+
+            /// \returns The reference to the allocator.
+            /// It has the same type as the call to \ref allocator_reference::get_allocator().
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
+            {
+                return this->allocator_reference<allocator_type>::get_allocator();
+            }
+        };
+
+        /// Specialization of \ref allocator_deleter for array types.
+        /// Otherwise the same behavior.
+        /// \ingroup adapter
+        template <typename Type, class RawAllocator>
+        class allocator_deleter<Type[], RawAllocator>
+        : WPI_EBO(allocator_reference<RawAllocator>)
+        {
+            static_assert(!std::is_abstract<Type>::value, "must not create polymorphic arrays");
+
+        public:
+            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;
+            using value_type     = Type;
+
+            /// \effects Creates it without any associated allocator.
+            /// The deleter must not be used if that is the case.
+            /// \notes This functions is useful if you have want to create an empty smart pointer without giving it an allocator.
+            allocator_deleter() noexcept : size_(0u) {}
+
+            /// \effects Creates it by passing it an \ref allocator_reference and the size of the array that will be deallocated.
+            /// It will store the reference to the allocator and uses the referenced allocator object for the deallocation.
+            allocator_deleter(allocator_reference<RawAllocator> alloc, std::size_t size) noexcept
+            : allocator_reference<RawAllocator>(alloc), size_(size)
+            {
+            }
+
+            /// \effects Calls the destructors and deallocates the memory given to it.
+            /// Calls \c deallocate_array(pointer, size, sizeof(value_type), alignof(value_type))
+            /// on the referenced allocator object with the size given in the constructor for the deallocation.
+            /// \requires The deleter must not have been created by the default constructor.
+            void operator()(value_type* pointer) noexcept
+            {
+                for (auto cur = pointer; cur != pointer + size_; ++cur)
+                    cur->~value_type();
+                this->deallocate_array(pointer, size_, sizeof(value_type), alignof(value_type));
+            }
+
+            /// \returns The reference to the allocator.
+            /// It has the same type as the call to \ref allocator_reference::get_allocator().
+            /// \requires The deleter must not be created by the default constructor.
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
+            {
+                return this->allocator_reference<allocator_type>::get_allocator();
+            }
+
+            /// \returns The size of the array that will be deallocated.
+            /// This is the same value as passed in the constructor, or `0` if it was created by the default constructor.
+            std::size_t array_size() const noexcept
+            {
+                return size_;
+            }
+
+        private:
+            std::size_t size_;
+        };
+
+        /// Similar to \ref allocator_polymorphic_deallocator but calls the destructors of the object.
+        /// Otherwise behaves the same.
+        /// \note It has a relatively high space overhead, so only use it if you have to.
+        /// \ingroup adapter
+        template <typename BaseType, class RawAllocator>
+        class allocator_polymorphic_deleter : WPI_EBO(allocator_reference<RawAllocator>)
+        {
+        public:
+            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;
+            using value_type     = BaseType;
+
+            /// \effects Creates it from a deleter for a derived type.
+            /// It will deallocate the memory as if done by the derived type.
+            template <typename T, WPI_REQUIRES((std::is_base_of<BaseType, T>::value))>
+            allocator_polymorphic_deleter(allocator_deleter<T, RawAllocator> deleter)
+            : allocator_reference<RawAllocator>(deleter.get_allocator()),
+              derived_size_(sizeof(T)),
+              derived_alignment_(alignof(T))
+            {
+                WPI_MEMORY_ASSERT(std::size_t(derived_size_) == sizeof(T)
+                                        && std::size_t(derived_alignment_) == alignof(T));
+            }
+
+            /// \effects Deallocates the memory given to it.
+            /// Calls \c deallocate_node(pointer, size, alignment) on the referenced allocator object,
+            /// where \c size and \c alignment are the values of the type it was created with.
+            void operator()(value_type* pointer) noexcept
+            {
+                pointer->~value_type();
+                this->deallocate_node(pointer, derived_size_, derived_alignment_);
+            }
+
+            /// \returns The reference to the allocator.
+            /// It has the same type as the call to \ref allocator_reference::get_allocator().
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
+            {
+                return this->allocator_reference<allocator_type>::get_allocator();
+            }
+
+        private:
+            unsigned short derived_size_,
+                derived_alignment_; // use unsigned short here to save space
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif //WPI_MEMORY_DELETER_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/align.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/align.hpp
new file mode 100644
index 0000000..99d6bcc
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/align.hpp
@@ -0,0 +1,52 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_ALIGN_HPP_INCLUDED
+#define WPI_MEMORY_DETAIL_ALIGN_HPP_INCLUDED
+
+#include <cstdint>
+
+#include "../config.hpp"
+#include "assert.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            // whether or not an alignment is valid, i.e. a power of two not zero
+            constexpr bool is_valid_alignment(std::size_t alignment) noexcept
+            {
+                return alignment && (alignment & (alignment - 1)) == 0u;
+            }
+
+            // returns the offset needed to align ptr for given alignment
+            // alignment must be valid
+            inline std::size_t align_offset(std::uintptr_t address, std::size_t alignment) noexcept
+            {
+                WPI_MEMORY_ASSERT(is_valid_alignment(alignment));
+                auto misaligned = address & (alignment - 1);
+                return misaligned != 0 ? (alignment - misaligned) : 0;
+            }
+            inline std::size_t align_offset(void* ptr, std::size_t alignment) noexcept
+            {
+                return align_offset(reinterpret_cast<std::uintptr_t>(ptr), alignment);
+            }
+
+            // whether or not the pointer is aligned for given alignment
+            // alignment must be valid
+            bool is_aligned(void* ptr, std::size_t alignment) noexcept;
+
+            // maximum alignment value
+            constexpr std::size_t max_alignment = alignof(std::max_align_t);
+            static_assert(is_valid_alignment(max_alignment), "ehm..?");
+
+            // returns the minimum alignment required for a node of given size
+            std::size_t alignment_for(std::size_t size) noexcept;
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DETAIL_ALIGN_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/assert.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/assert.hpp
new file mode 100644
index 0000000..b8a7372
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/assert.hpp
@@ -0,0 +1,57 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_ASSERT_HPP_INCLUDED
+#define WPI_MEMORY_DETAIL_ASSERT_HPP_INCLUDED
+
+#include <cstdlib>
+
+#include "../config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            // handles a failed assertion
+            void handle_failed_assert(const char* msg, const char* file, int line,
+                                      const char* fnc) noexcept;
+
+            void handle_warning(const char* msg, const char* file, int line,
+                                const char* fnc) noexcept;
+
+// note: debug assertion macros don't use fully qualified name
+// because they should only be used in this library, where the whole namespace is available
+// can be override via command line definitions
+#if WPI_MEMORY_DEBUG_ASSERT && !defined(WPI_MEMORY_ASSERT)
+#define WPI_MEMORY_ASSERT(Expr)                                                              \
+    static_cast<void>((Expr)                                                                       \
+                      || (detail::handle_failed_assert("Assertion \"" #Expr "\" failed", __FILE__, \
+                                                       __LINE__, __func__),                        \
+                          true))
+
+#define WPI_MEMORY_ASSERT_MSG(Expr, Msg)                                                     \
+    static_cast<void>((Expr)                                                                       \
+                      || (detail::handle_failed_assert("Assertion \"" #Expr "\" failed: " Msg,     \
+                                                       __FILE__, __LINE__, __func__),              \
+                          true))
+
+#define WPI_MEMORY_UNREACHABLE(Msg)                                                          \
+    detail::handle_failed_assert("Unreachable code reached: " Msg, __FILE__, __LINE__, __func__)
+
+#define WPI_MEMORY_WARNING(Msg) detail::handle_warning(Msg, __FILE__, __LINE__, __func__)
+
+#elif !defined(WPI_MEMORY_ASSERT)
+#define WPI_MEMORY_ASSERT(Expr)
+#define WPI_MEMORY_ASSERT_MSG(Expr, Msg)
+#define WPI_MEMORY_UNREACHABLE(Msg) std::abort()
+#define WPI_MEMORY_WARNING(Msg)
+#endif
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DETAIL_ASSERT_HPP_INCLUDED
+
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/container_node_sizes.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/container_node_sizes.hpp
new file mode 100644
index 0000000..37949ca
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/container_node_sizes.hpp
@@ -0,0 +1,10 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_CONTAINER_NODE_SIZES_HPP_INCLUDED
+#define WPI_MEMORY_DETAIL_CONTAINER_NODE_SIZES_HPP_INCLUDED
+
+#include "container_node_sizes_impl.hpp"
+
+#endif //WPI_MEMORY_DETAIL_CONTAINER_NODE_SIZES_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/debug_helpers.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/debug_helpers.hpp
new file mode 100644
index 0000000..3ef2eed
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/debug_helpers.hpp
@@ -0,0 +1,235 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DEBUG_HELPERS_HPP_INCLUDED
+#define WPI_MEMORY_DEBUG_HELPERS_HPP_INCLUDED
+
+#include <atomic>
+#include <type_traits>
+
+#include "../config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        enum class debug_magic : unsigned char;
+        struct allocator_info;
+
+        namespace detail
+        {
+            using debug_fill_enabled = std::integral_constant<bool, WPI_MEMORY_DEBUG_FILL>;
+            constexpr std::size_t debug_fence_size =
+                WPI_MEMORY_DEBUG_FILL ? WPI_MEMORY_DEBUG_FENCE : 0u;
+
+#if WPI_MEMORY_DEBUG_FILL
+            // fills size bytes of memory with debug_magic
+            void debug_fill(void* memory, std::size_t size, debug_magic m) noexcept;
+
+            // returns nullptr if memory is filled with debug_magic
+            // else returns pointer to mismatched byte
+            void* debug_is_filled(void* memory, std::size_t size, debug_magic m) noexcept;
+
+            // fills fence, new and fence
+            // returns after fence
+            void* debug_fill_new(void* memory, std::size_t node_size,
+                                 std::size_t fence_size = debug_fence_size) noexcept;
+
+            // fills free memory and returns memory starting at fence
+            void* debug_fill_free(void* memory, std::size_t node_size,
+                                  std::size_t fence_size = debug_fence_size) noexcept;
+
+            // fills internal memory
+            void debug_fill_internal(void* memory, std::size_t size, bool free) noexcept;
+#else
+            inline void debug_fill(void*, std::size_t, debug_magic) noexcept {}
+
+            inline void* debug_is_filled(void*, std::size_t, debug_magic) noexcept
+            {
+                return nullptr;
+            }
+
+            inline void* debug_fill_new(void* memory, std::size_t, std::size_t) noexcept
+            {
+                return memory;
+            }
+
+            inline void* debug_fill_free(void* memory, std::size_t, std::size_t) noexcept
+            {
+                return static_cast<char*>(memory);
+            }
+
+            inline void debug_fill_internal(void*, std::size_t, bool) noexcept {}
+#endif
+
+            void debug_handle_invalid_ptr(const allocator_info& info, void* ptr);
+
+            // validates given ptr by evaluating the Functor
+            // if the Functor returns false, calls the debug_leak_checker
+            // note: ptr is just used as the information passed to the invalid ptr handler
+            template <class Functor>
+            void debug_check_pointer(Functor condition, const allocator_info& info, void* ptr)
+            {
+#if WPI_MEMORY_DEBUG_POINTER_CHECK
+                if (!condition())
+                    debug_handle_invalid_ptr(info, ptr);
+#else
+                (void)ptr;
+                (void)condition;
+                (void)info;
+#endif
+            }
+
+            // validates ptr by using a more expensive double-dealloc check
+            template <class Functor>
+            void debug_check_double_dealloc(Functor condition, const allocator_info& info,
+                                            void* ptr)
+            {
+#if WPI_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK
+                debug_check_pointer(condition, info, ptr);
+#else
+                (void)condition;
+                (void)info;
+                (void)ptr;
+#endif
+            }
+
+            void debug_handle_memory_leak(const allocator_info& info, std::ptrdiff_t amount);
+
+            // does no leak checking, null overhead
+            template <class Handler>
+            class no_leak_checker
+            {
+            public:
+                no_leak_checker() noexcept {}
+                no_leak_checker(no_leak_checker&&) noexcept {}
+                ~no_leak_checker() noexcept {}
+
+                no_leak_checker& operator=(no_leak_checker&&) noexcept
+                {
+                    return *this;
+                }
+
+                void on_allocate(std::size_t) noexcept {}
+                void on_deallocate(std::size_t) noexcept {}
+            };
+
+            // does leak checking per-object
+            // leak is detected upon destructor
+            template <class Handler>
+            class object_leak_checker : Handler
+            {
+            public:
+                object_leak_checker() noexcept : allocated_(0) {}
+
+                object_leak_checker(object_leak_checker&& other) noexcept
+                : allocated_(other.allocated_)
+                {
+                    other.allocated_ = 0;
+                }
+
+                ~object_leak_checker() noexcept
+                {
+                    if (allocated_ != 0)
+                        this->operator()(allocated_);
+                }
+
+                object_leak_checker& operator=(object_leak_checker&& other) noexcept
+                {
+                    allocated_       = other.allocated_;
+                    other.allocated_ = 0;
+                    return *this;
+                }
+
+                void on_allocate(std::size_t size) noexcept
+                {
+                    allocated_ += std::ptrdiff_t(size);
+                }
+
+                void on_deallocate(std::size_t size) noexcept
+                {
+                    allocated_ -= std::ptrdiff_t(size);
+                }
+
+            private:
+                std::ptrdiff_t allocated_;
+            };
+
+            // does leak checking on a global basis
+            // call macro WPI_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name) in the header
+            // when last counter gets destroyed, leak is detected
+            template <class Handler>
+            class global_leak_checker_impl
+            {
+            public:
+                struct counter : Handler
+                {
+                    counter()
+                    {
+                        ++no_counter_objects_;
+                    }
+
+                    ~counter()
+                    {
+                        --no_counter_objects_;
+                        if (no_counter_objects_ == 0u && allocated_ != 0u)
+                            this->operator()(allocated_);
+                    }
+                };
+
+                global_leak_checker_impl() noexcept {}
+                global_leak_checker_impl(global_leak_checker_impl&&) noexcept {}
+                ~global_leak_checker_impl() noexcept {}
+
+                global_leak_checker_impl& operator=(global_leak_checker_impl&&) noexcept
+                {
+                    return *this;
+                }
+
+                void on_allocate(std::size_t size) noexcept
+                {
+                    allocated_ += std::ptrdiff_t(size);
+                }
+
+                void on_deallocate(std::size_t size) noexcept
+                {
+                    allocated_ -= std::ptrdiff_t(size);
+                }
+
+            private:
+                static std::atomic<std::size_t>    no_counter_objects_;
+                static std::atomic<std::ptrdiff_t> allocated_;
+            };
+
+            template <class Handler>
+            std::atomic<std::size_t> global_leak_checker_impl<Handler>::no_counter_objects_(0u);
+
+            template <class Handler>
+            std::atomic<std::ptrdiff_t> global_leak_checker_impl<Handler>::allocated_(0);
+
+#if WPI_MEMORY_DEBUG_LEAK_CHECK
+            template <class Handler>
+            using global_leak_checker = global_leak_checker_impl<Handler>;
+
+#define WPI_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name)                                    \
+    static wpi::memory::detail::global_leak_checker<handler>::counter var_name;
+#else
+            template <class Handler>
+            using global_leak_checker = no_leak_checker<int>; // only one instantiation
+
+#define WPI_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name)
+#endif
+
+#if WPI_MEMORY_DEBUG_LEAK_CHECK
+            template <class Handler>
+            using default_leak_checker = object_leak_checker<Handler>;
+#else
+            template <class Handler>
+            using default_leak_checker = no_leak_checker<Handler>;
+#endif
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DEBUG_HELPERS_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/ebo_storage.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/ebo_storage.hpp
new file mode 100644
index 0000000..de53f7f
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/ebo_storage.hpp
@@ -0,0 +1,42 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_EBO_STORAGE_HPP_INCLUDED
+#define WPI_MEMORY_DETAIL_EBO_STORAGE_HPP_INCLUDED
+
+#include "utility.hpp"
+#include "../config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            template <int Tag, typename T>
+            class ebo_storage : T
+            {
+            protected:
+                ebo_storage(const T& t) : T(t) {}
+
+                ebo_storage(T&& t) noexcept(std::is_nothrow_move_constructible<T>::value)
+                : T(detail::move(t))
+                {
+                }
+
+                T& get() noexcept
+                {
+                    return *this;
+                }
+
+                const T& get() const noexcept
+                {
+                    return *this;
+                }
+            };
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DETAIL_EBO_STORAGE_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/free_list.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/free_list.hpp
new file mode 100644
index 0000000..612706d
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/free_list.hpp
@@ -0,0 +1,228 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAILL_FREE_LIST_HPP_INCLUDED
+#define WPI_MEMORY_DETAILL_FREE_LIST_HPP_INCLUDED
+
+#include <cstddef>
+#include <cstdint>
+
+#include "align.hpp"
+#include "utility.hpp"
+#include "../config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            // stores free blocks for a memory pool
+            // memory blocks are fragmented and stored in a list
+            // debug: fills memory and uses a bigger node_size for fence memory
+            class free_memory_list
+            {
+            public:
+                // minimum element size
+                static constexpr auto min_element_size = sizeof(char*);
+                // alignment
+                static constexpr auto min_element_alignment = alignof(char*);
+
+                // minimal size of the block that needs to be inserted
+                static constexpr std::size_t min_block_size(std::size_t node_size,
+                                                            std::size_t number_of_nodes)
+                {
+                    return (node_size < min_element_size ? min_element_size : node_size)
+                           * number_of_nodes;
+                }
+
+                //=== constructor ===//
+                free_memory_list(std::size_t node_size) noexcept;
+
+                // calls other constructor plus insert
+                free_memory_list(std::size_t node_size, void* mem, std::size_t size) noexcept;
+
+                free_memory_list(free_memory_list&& other) noexcept;
+                ~free_memory_list() noexcept = default;
+
+                free_memory_list& operator=(free_memory_list&& other) noexcept;
+
+                friend void swap(free_memory_list& a, free_memory_list& b) noexcept;
+
+                //=== insert/allocation/deallocation ===//
+                // inserts a new memory block, by splitting it up and setting the links
+                // does not own memory!
+                // mem must be aligned for alignment()
+                // pre: size != 0
+                void insert(void* mem, std::size_t size) noexcept;
+
+                // returns the usable size
+                // i.e. how many memory will be actually inserted and usable on a call to insert()
+                std::size_t usable_size(std::size_t size) const noexcept
+                {
+                    // Round down to next multiple of node size.
+                    return (size / node_size_) * node_size_;
+                }
+
+                // returns a single block from the list
+                // pre: !empty()
+                void* allocate() noexcept;
+
+                // returns a memory block big enough for n bytes
+                // might fail even if capacity is sufficient
+                void* allocate(std::size_t n) noexcept;
+
+                // deallocates a single block
+                void deallocate(void* ptr) noexcept;
+
+                // deallocates multiple blocks with n bytes total
+                void deallocate(void* ptr, std::size_t n) noexcept;
+
+                //=== getter ===//
+                std::size_t node_size() const noexcept
+                {
+                    return node_size_;
+                }
+
+                // alignment of all nodes
+                std::size_t alignment() const noexcept;
+
+                // number of nodes remaining
+                std::size_t capacity() const noexcept
+                {
+                    return capacity_;
+                }
+
+                bool empty() const noexcept
+                {
+                    return first_ == nullptr;
+                }
+
+            private:
+                void insert_impl(void* mem, std::size_t size) noexcept;
+
+                char*       first_;
+                std::size_t node_size_, capacity_;
+            };
+
+            void swap(free_memory_list& a, free_memory_list& b) noexcept;
+
+            // same as above but keeps the nodes ordered
+            // this allows array allocations, that is, consecutive nodes
+            // debug: fills memory and uses a bigger node_size for fence memory
+            class ordered_free_memory_list
+            {
+            public:
+                // minimum element size
+                static constexpr auto min_element_size = sizeof(char*);
+                // alignment
+                static constexpr auto min_element_alignment = alignof(char*);
+
+                // minimal size of the block that needs to be inserted
+                static constexpr std::size_t min_block_size(std::size_t node_size,
+                                                            std::size_t number_of_nodes)
+                {
+                    return (node_size < min_element_size ? min_element_size : node_size)
+                           * number_of_nodes;
+                }
+
+                //=== constructor ===//
+                ordered_free_memory_list(std::size_t node_size) noexcept;
+
+                ordered_free_memory_list(std::size_t node_size, void* mem,
+                                         std::size_t size) noexcept
+                : ordered_free_memory_list(node_size)
+                {
+                    insert(mem, size);
+                }
+
+                ordered_free_memory_list(ordered_free_memory_list&& other) noexcept;
+
+                ~ordered_free_memory_list() noexcept = default;
+
+                ordered_free_memory_list& operator=(ordered_free_memory_list&& other) noexcept
+                {
+                    ordered_free_memory_list tmp(detail::move(other));
+                    swap(*this, tmp);
+                    return *this;
+                }
+
+                friend void swap(ordered_free_memory_list& a, ordered_free_memory_list& b) noexcept;
+
+                //=== insert/allocation/deallocation ===//
+                // inserts a new memory block, by splitting it up and setting the links
+                // does not own memory!
+                // mem must be aligned for alignment()
+                // pre: size != 0
+                void insert(void* mem, std::size_t size) noexcept;
+
+                // returns the usable size
+                // i.e. how many memory will be actually inserted and usable on a call to insert()
+                std::size_t usable_size(std::size_t size) const noexcept
+                {
+                    // Round down to next multiple of node size.
+                    return (size / node_size_) * node_size_;
+                }
+
+                // returns a single block from the list
+                // pre: !empty()
+                void* allocate() noexcept;
+
+                // returns a memory block big enough for n bytes (!, not nodes)
+                // might fail even if capacity is sufficient
+                void* allocate(std::size_t n) noexcept;
+
+                // deallocates a single block
+                void deallocate(void* ptr) noexcept;
+
+                // deallocates multiple blocks with n bytes total
+                void deallocate(void* ptr, std::size_t n) noexcept;
+
+                //=== getter ===//
+                std::size_t node_size() const noexcept
+                {
+                    return node_size_;
+                }
+
+                // alignment of all nodes
+                std::size_t alignment() const noexcept;
+
+                // number of nodes remaining
+                std::size_t capacity() const noexcept
+                {
+                    return capacity_;
+                }
+
+                bool empty() const noexcept
+                {
+                    return capacity_ == 0u;
+                }
+
+            private:
+                // returns previous pointer
+                char* insert_impl(void* mem, std::size_t size) noexcept;
+
+                char* begin_node() noexcept;
+                char* end_node() noexcept;
+
+                std::uintptr_t begin_proxy_, end_proxy_;
+                std::size_t    node_size_, capacity_;
+                char *         last_dealloc_, *last_dealloc_prev_;
+            };
+
+            void swap(ordered_free_memory_list& a, ordered_free_memory_list& b) noexcept;
+
+#if WPI_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK
+            // use ordered version to allow pointer check
+            using node_free_memory_list  = ordered_free_memory_list;
+            using array_free_memory_list = ordered_free_memory_list;
+#else
+            using node_free_memory_list  = free_memory_list;
+            using array_free_memory_list = ordered_free_memory_list;
+#endif
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DETAILL_FREE_LIST_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/free_list_array.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/free_list_array.hpp
new file mode 100644
index 0000000..ec57e1e
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/free_list_array.hpp
@@ -0,0 +1,126 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_FREE_LIST_ARRAY_HPP
+#define WPI_MEMORY_DETAIL_FREE_LIST_ARRAY_HPP
+
+#include "align.hpp"
+#include "assert.hpp"
+#include "memory_stack.hpp"
+#include "../config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            // an array of free_memory_list types
+            // indexed via size, AccessPolicy does necessary conversions
+            // requires trivial destructible FreeList type
+            template <class FreeList, class AccessPolicy>
+            class free_list_array
+            {
+                // not supported on GCC 4.7
+                //static_assert(std::is_trivially_destructible<FreeList>::value,
+                //            "free list must be trivially destructible");
+            public:
+                // creates sufficient elements to support up to given maximum node size
+                // all lists are initially empty
+                // actual number is calculated via policy
+                // memory is taken from fixed_memory_stack, it must be sufficient
+                free_list_array(fixed_memory_stack& stack, const char* end,
+                                std::size_t max_node_size) noexcept
+                : no_elements_(AccessPolicy::index_from_size(max_node_size) - min_size_index + 1)
+                {
+                    array_ = static_cast<FreeList*>(
+                        stack.allocate(end, no_elements_ * sizeof(FreeList), alignof(FreeList)));
+                    WPI_MEMORY_ASSERT_MSG(array_, "insufficient memory for free lists");
+                    for (std::size_t i = 0u; i != no_elements_; ++i)
+                    {
+                        auto node_size = AccessPolicy::size_from_index(i + min_size_index);
+                        ::new (static_cast<void*>(array_ + i)) FreeList(node_size);
+                    }
+                }
+
+                // move constructor, does not actually move the elements, just the pointer
+                free_list_array(free_list_array&& other) noexcept
+                : array_(other.array_), no_elements_(other.no_elements_)
+                {
+                    other.array_       = nullptr;
+                    other.no_elements_ = 0u;
+                }
+
+                // destructor, does nothing, list must be trivially destructible!
+                ~free_list_array() noexcept = default;
+
+                free_list_array& operator=(free_list_array&& other) noexcept
+                {
+                    array_       = other.array_;
+                    no_elements_ = other.no_elements_;
+
+                    other.array_       = nullptr;
+                    other.no_elements_ = 0u;
+                    return *this;
+                }
+
+                // access free list for given size
+                FreeList& get(std::size_t node_size) const noexcept
+                {
+                    auto i = AccessPolicy::index_from_size(node_size);
+                    if (i < min_size_index)
+                        i = min_size_index;
+                    return array_[i - min_size_index];
+                }
+
+                // number of free lists
+                std::size_t size() const noexcept
+                {
+                    return no_elements_;
+                }
+
+                // maximum supported node size
+                std::size_t max_node_size() const noexcept
+                {
+                    return AccessPolicy::size_from_index(no_elements_ + min_size_index - 1);
+                }
+
+            private:
+                static const std::size_t min_size_index;
+
+                FreeList*   array_;
+                std::size_t no_elements_;
+            };
+
+            template <class FL, class AP>
+            const std::size_t free_list_array<FL, AP>::min_size_index =
+                AP::index_from_size(FL::min_element_size);
+
+            // AccessPolicy that maps size to indices 1:1
+            // creates a free list for each size!
+            struct identity_access_policy
+            {
+                static std::size_t index_from_size(std::size_t size) noexcept
+                {
+                    return size;
+                }
+
+                static std::size_t size_from_index(std::size_t index) noexcept
+                {
+                    return index;
+                }
+            };
+
+            // AccessPolicy that maps sizes to the integral log2
+            // this creates more nodes and never wastes more than half the size
+            struct log2_access_policy
+            {
+                static std::size_t index_from_size(std::size_t size) noexcept;
+                static std::size_t size_from_index(std::size_t index) noexcept;
+            };
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif //WPI_MEMORY_DETAIL_FREE_LIST_ARRAY_HPP
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/ilog2.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/ilog2.hpp
new file mode 100644
index 0000000..5cf125a
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/ilog2.hpp
@@ -0,0 +1,69 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_ILOG2_HPP_INCLUDED
+#define WPI_MEMORY_DETAIL_ILOG2_HPP_INCLUDED
+
+#include <climits>
+#include <cstdint>
+
+#include "../config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            // undefined for 0
+            template <typename UInt>
+            constexpr bool is_power_of_two(UInt x)
+            {
+                return (x & (x - 1)) == 0;
+            }
+
+            inline std::size_t ilog2_base(std::uint64_t x)
+            {
+#if defined(__GNUC__)
+                unsigned long long value = x;
+                return sizeof(value) * CHAR_BIT - static_cast<unsigned>(__builtin_clzll(value));
+#else
+                // Adapted from https://stackoverflow.com/a/40943402
+                std::size_t clz = 64;
+                std::size_t c   = 32;
+                do
+                {
+                    auto tmp = x >> c;
+                    if (tmp != 0)
+                    {
+                        clz -= c;
+                        x = tmp;
+                    }
+                    c = c >> 1;
+                } while (c != 0);
+                clz -= x ? 1 : 0;
+
+                return 64 - clz;
+#endif
+            }
+
+            // ilog2() implementation, cuts part after the comma
+            // e.g. 1 -> 0, 2 -> 1, 3 -> 1, 4 -> 2, 5 -> 2
+            inline std::size_t ilog2(std::uint64_t x)
+            {
+                return ilog2_base(x) - 1;
+            }
+
+            // ceiling ilog2() implementation, adds one if part after comma
+            // e.g. 1 -> 0, 2 -> 1, 3 -> 2, 4 -> 2, 5 -> 3
+            inline std::size_t ilog2_ceil(std::uint64_t x)
+            {
+                // only subtract one if power of two
+                return ilog2_base(x) - std::size_t(is_power_of_two(x));
+            }
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/lowlevel_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/lowlevel_allocator.hpp
new file mode 100644
index 0000000..2ac45a5
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/lowlevel_allocator.hpp
@@ -0,0 +1,86 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_LOWLEVEL_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_DETAIL_LOWLEVEL_ALLOCATOR_HPP_INCLUDED
+
+#include <type_traits>
+
+#include "../config.hpp"
+#include "../error.hpp"
+#include "align.hpp"
+#include "debug_helpers.hpp"
+#include "assert.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            template <class Functor>
+            struct lowlevel_allocator_leak_handler
+            {
+                void operator()(std::ptrdiff_t amount)
+                {
+                    debug_handle_memory_leak(Functor::info(), amount);
+                }
+            };
+
+            // Functor controls low-level allocation:
+            // static allocator_info info()
+            // static void* allocate(std::size_t size, std::size_t alignment);
+            // static void deallocate(void *memory, std::size_t size, std::size_t alignment);
+            // static std::size_t max_node_size();
+            template <class Functor>
+            class lowlevel_allocator : global_leak_checker<lowlevel_allocator_leak_handler<Functor>>
+            {
+            public:
+                using is_stateful = std::false_type;
+
+                lowlevel_allocator() noexcept {}
+                lowlevel_allocator(lowlevel_allocator&&) noexcept {}
+                ~lowlevel_allocator() noexcept {}
+
+                lowlevel_allocator& operator=(lowlevel_allocator&&) noexcept
+                {
+                    return *this;
+                }
+
+                void* allocate_node(std::size_t size, std::size_t alignment)
+                {
+                    auto actual_size = size + (debug_fence_size ? 2 * max_alignment : 0u);
+
+                    auto memory = Functor::allocate(actual_size, alignment);
+                    if (!memory)
+                        WPI_THROW(out_of_memory(Functor::info(), actual_size));
+
+                    this->on_allocate(actual_size);
+
+                    return debug_fill_new(memory, size, max_alignment);
+                }
+
+                void deallocate_node(void* node, std::size_t size, std::size_t alignment) noexcept
+                {
+                    auto actual_size = size + (debug_fence_size ? 2 * max_alignment : 0u);
+
+                    auto memory = debug_fill_free(node, size, max_alignment);
+                    Functor::deallocate(memory, actual_size, alignment);
+
+                    this->on_deallocate(actual_size);
+                }
+
+                std::size_t max_node_size() const noexcept
+                {
+                    return Functor::max_node_size();
+                }
+            };
+
+#define WPI_MEMORY_LL_ALLOCATOR_LEAK_CHECKER(functor, var_name)                              \
+    WPI_MEMORY_GLOBAL_LEAK_CHECKER(lowlevel_allocator_leak_handler<functor>, var_name)
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DETAIL_LOWLEVEL_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/memory_stack.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/memory_stack.hpp
new file mode 100644
index 0000000..e49d480
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/memory_stack.hpp
@@ -0,0 +1,120 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_MEMORY_STACK_HPP_INCLUDED
+#define WPI_MEMORY_DETAIL_MEMORY_STACK_HPP_INCLUDED
+
+#include <cstddef>
+
+#include "../config.hpp"
+#include "align.hpp"
+#include "debug_helpers.hpp"
+#include "../debugging.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            // simple memory stack implementation that does not support growing
+            class fixed_memory_stack
+            {
+            public:
+                fixed_memory_stack() noexcept : fixed_memory_stack(nullptr) {}
+
+                // gives it the current pointer, the end pointer must be maintained seperataly
+                explicit fixed_memory_stack(void* memory) noexcept
+                : cur_(static_cast<char*>(memory))
+                {
+                }
+
+                fixed_memory_stack(fixed_memory_stack&& other) noexcept : cur_(other.cur_)
+                {
+                    other.cur_ = nullptr;
+                }
+
+                ~fixed_memory_stack() noexcept = default;
+
+                fixed_memory_stack& operator=(fixed_memory_stack&& other) noexcept
+                {
+                    cur_       = other.cur_;
+                    other.cur_ = nullptr;
+                    return *this;
+                }
+
+                // bumps the top pointer without filling it
+                void bump(std::size_t offset) noexcept
+                {
+                    cur_ += offset;
+                }
+
+                // bumps the top pointer by offset and fills
+                void bump(std::size_t offset, debug_magic m) noexcept
+                {
+                    detail::debug_fill(cur_, offset, m);
+                    bump(offset);
+                }
+
+                // same as bump(offset, m) but returns old value
+                void* bump_return(std::size_t offset,
+                                  debug_magic m = debug_magic::new_memory) noexcept
+                {
+                    auto memory = cur_;
+                    detail::debug_fill(memory, offset, m);
+                    cur_ += offset;
+                    return memory;
+                }
+
+                // allocates memory by advancing the stack, returns nullptr if insufficient
+                // debug: mark memory as new_memory, put fence in front and back
+                void* allocate(const char* end, std::size_t size, std::size_t alignment,
+                               std::size_t fence_size = debug_fence_size) noexcept
+                {
+                    if (cur_ == nullptr)
+                        return nullptr;
+
+                    auto remaining = std::size_t(end - cur_);
+                    auto offset    = align_offset(cur_ + fence_size, alignment);
+                    if (fence_size + offset + size + fence_size > remaining)
+                        return nullptr;
+
+                    return allocate_unchecked(size, offset, fence_size);
+                }
+
+                // same as allocate() but does not check the size
+                // note: pass it the align OFFSET, not the alignment
+                void* allocate_unchecked(std::size_t size, std::size_t align_offset,
+                                         std::size_t fence_size = debug_fence_size) noexcept
+                {
+                    bump(fence_size, debug_magic::fence_memory);
+                    bump(align_offset, debug_magic::alignment_memory);
+                    auto mem = bump_return(size);
+                    bump(fence_size, debug_magic::fence_memory);
+                    return mem;
+                }
+
+                // unwindws the stack to a certain older position
+                // debug: marks memory from new top to old top as freed
+                // doesn't check for invalid pointer
+                void unwind(char* top) noexcept
+                {
+                    debug_fill(top, std::size_t(cur_ - top), debug_magic::freed_memory);
+                    cur_ = top;
+                }
+
+                // returns the current top
+                char* top() const noexcept
+                {
+                    return cur_;
+                }
+
+            private:
+                char* cur_;
+            };
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DETAIL_MEMORY_STACK_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/small_free_list.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/small_free_list.hpp
new file mode 100644
index 0000000..682417d
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/small_free_list.hpp
@@ -0,0 +1,164 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_SMALL_FREE_LIST_HPP_INCLUDED
+#define WPI_MEMORY_DETAIL_SMALL_FREE_LIST_HPP_INCLUDED
+
+#include <cstddef>
+#include <climits>
+
+#include "../config.hpp"
+#include "utility.hpp"
+#include "align.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            struct chunk_base
+            {
+                chunk_base* prev = this;
+                chunk_base* next = this;
+
+                unsigned char first_free = 0; // first free node for the linked list
+                unsigned char capacity   = 0; // total number of free nodes available
+                unsigned char no_nodes   = 0; // total number of nodes in memory
+
+                chunk_base() noexcept = default;
+
+                chunk_base(unsigned char no) noexcept : capacity(no), no_nodes(no) {}
+            };
+
+            constexpr std::size_t chunk_memory_offset =
+                sizeof(chunk_base) % detail::max_alignment == 0 ?
+                    sizeof(chunk_base) :
+                    (sizeof(chunk_base) / detail::max_alignment + 1) * detail::max_alignment;
+            constexpr std::size_t chunk_max_nodes = UCHAR_MAX;
+
+            struct chunk;
+
+            // the same as free_memory_list but optimized for small node sizes
+            // it is slower and does not support arrays
+            // but has very small overhead
+            // debug: allocate() and deallocate() mark memory as new and freed, respectively
+            // node_size is increased via two times fence size and fence is put in front and after
+            class small_free_memory_list
+            {
+                static constexpr std::size_t chunk_count(std::size_t number_of_nodes)
+                {
+                    return number_of_nodes / chunk_max_nodes
+                           + (number_of_nodes % chunk_max_nodes == 0 ? 0 : 1);
+                }
+
+            public:
+                // minimum element size
+                static constexpr std::size_t min_element_size = 1;
+                // alignment
+                static constexpr std::size_t min_element_alignment = 1;
+
+                // minimal size of the block that needs to be inserted
+                static constexpr std::size_t min_block_size(std::size_t node_size,
+                                                            std::size_t number_of_nodes)
+                {
+                    return chunk_count(number_of_nodes)
+                           * (chunk_memory_offset + chunk_max_nodes * node_size);
+                }
+
+                //=== constructor ===//
+                small_free_memory_list(std::size_t node_size) noexcept;
+
+                // does not own memory!
+                small_free_memory_list(std::size_t node_size, void* mem, std::size_t size) noexcept;
+
+                small_free_memory_list(small_free_memory_list&& other) noexcept;
+
+                ~small_free_memory_list() noexcept = default;
+
+                small_free_memory_list& operator=(small_free_memory_list&& other) noexcept
+                {
+                    small_free_memory_list tmp(detail::move(other));
+                    swap(*this, tmp);
+                    return *this;
+                }
+
+                friend void swap(small_free_memory_list& a, small_free_memory_list& b) noexcept;
+
+                //=== insert/alloc/dealloc ===//
+                // inserts new memory of given size into the free list
+                // mem must be aligned for maximum alignment
+                void insert(void* mem, std::size_t size) noexcept;
+
+                // returns the usable size
+                // i.e. how many memory will be actually inserted and usable on a call to insert()
+                std::size_t usable_size(std::size_t size) const noexcept;
+
+                // allocates a node big enough for the node size
+                // pre: !empty()
+                void* allocate() noexcept;
+
+                // always returns nullptr, because array allocations are not supported
+                void* allocate(std::size_t) noexcept
+                {
+                    return nullptr;
+                }
+
+                // deallocates the node previously allocated via allocate()
+                void deallocate(void* node) noexcept;
+
+                // forwards to insert()
+                void deallocate(void* mem, std::size_t size) noexcept
+                {
+                    insert(mem, size);
+                }
+
+                // hint for allocate() to be prepared to allocate n nodes
+                // it searches for a chunk that has n nodes free
+                // returns false, if there is none like that
+                // never fails for n == 1 if not empty()
+                // pre: capacity() >= n * node_size()
+                bool find_chunk(std::size_t n) noexcept
+                {
+                    return find_chunk_impl(n) != nullptr;
+                }
+
+                //=== getter ===//
+                std::size_t node_size() const noexcept
+                {
+                    return node_size_;
+                }
+
+                // the alignment of all nodes
+                std::size_t alignment() const noexcept;
+
+                // number of nodes remaining
+                std::size_t capacity() const noexcept
+                {
+                    return capacity_;
+                }
+
+                bool empty() const noexcept
+                {
+                    return capacity_ == 0u;
+                }
+
+            private:
+                chunk* find_chunk_impl(std::size_t n = 1) noexcept;
+                chunk* find_chunk_impl(unsigned char* node, chunk_base* first,
+                                       chunk_base* last) noexcept;
+                chunk* find_chunk_impl(unsigned char* node) noexcept;
+
+                chunk_base  base_;
+                std::size_t node_size_, capacity_;
+                chunk_base *alloc_chunk_, *dealloc_chunk_;
+            };
+
+            // for some reason, this is required in order to define it
+            void swap(small_free_memory_list& a, small_free_memory_list& b) noexcept;
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_DETAIL_SMALL_FREE_LIST_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/utility.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/utility.hpp
new file mode 100644
index 0000000..c746fa2
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/detail/utility.hpp
@@ -0,0 +1,118 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_DETAIL_UTILITY_HPP
+#define WPI_MEMORY_DETAIL_UTILITY_HPP
+
+// implementation of some functions from <utility> to prevent dependencies on it
+
+#include <type_traits>
+
+#include "../config.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <utility>
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            // move - taken from http://stackoverflow.com/a/7518365
+            template <typename T>
+            typename std::remove_reference<T>::type&& move(T&& arg) noexcept
+            {
+                return static_cast<typename std::remove_reference<T>::type&&>(arg);
+            }
+            // forward - taken from http://stackoverflow.com/a/27501759
+            template <class T>
+            T&& forward(typename std::remove_reference<T>::type& t) noexcept
+            {
+                return static_cast<T&&>(t);
+            }
+            template <class T>
+            T&& forward(typename std::remove_reference<T>::type&& t) noexcept
+            {
+                static_assert(!std::is_lvalue_reference<T>::value,
+                              "Can not forward an rvalue as an lvalue.");
+                return static_cast<T&&>(t);
+            }
+
+            namespace swap_
+            {
+#if WPI_HOSTED_IMPLEMENTATION
+                using std::swap;
+#else
+                template <typename T>
+                void swap(T& a, T& b)
+                {
+                    T tmp = move(a);
+                    a     = move(b);
+                    b     = move(tmp);
+                }
+#endif
+            } // namespace swap_
+
+            // ADL aware swap
+            template <typename T>
+            void adl_swap(T& a, T& b) noexcept
+            {
+                using swap_::swap;
+                swap(a, b);
+            }
+
+// fancier syntax for enable_if
+// used as (template) parameter
+// also useful for doxygen
+// define PREDEFINED: WPI_REQUIRES(x):=
+#define WPI_REQUIRES(Expr) typename std::enable_if<(Expr), int>::type = 0
+
+// same as above, but as return type
+// also useful for doxygen:
+// defined PREDEFINED: WPI_REQUIRES_RET(x,r):=r
+#define WPI_REQUIRES_RET(Expr, ...) typename std::enable_if<(Expr), __VA_ARGS__>::type
+
+// fancier syntax for enable_if on non-templated member function
+#define WPI_ENABLE_IF(Expr)                                                                  \
+    template <typename Dummy = std::true_type, WPI_REQUIRES(Dummy::value && (Expr))>
+
+// fancier syntax for general expression SFINAE
+// used as (template) parameter
+// also useful for doxygen:
+// define PREDEFINED: WPI_SFINAE(x):=
+#define WPI_SFINAE(Expr) decltype((Expr), int()) = 0
+
+// avoids code repetition for one-line forwarding functions
+#define WPI_AUTO_RETURN(Expr)                                                                \
+    decltype(Expr)                                                                                 \
+    {                                                                                              \
+        return Expr;                                                                               \
+    }
+
+// same as above, but requires certain type
+#define WPI_AUTO_RETURN_TYPE(Expr, T)                                                        \
+    decltype(Expr)                                                                                 \
+    {                                                                                              \
+        static_assert(std::is_same<decltype(Expr), T>::value,                                      \
+                      #Expr " does not have the return type " #T);                                 \
+        return Expr;                                                                               \
+    }
+
+            // whether or not a type is an instantiation of a template
+            template <template <typename...> class Template, typename T>
+            struct is_instantiation_of : std::false_type
+            {
+            };
+
+            template <template <typename...> class Template, typename... Args>
+            struct is_instantiation_of<Template, Template<Args...>> : std::true_type
+            {
+            };
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif //WPI_MEMORY_DETAIL_UTILITY_HPP
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/error.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/error.hpp
new file mode 100644
index 0000000..5ff99cf
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/error.hpp
@@ -0,0 +1,289 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+/// \file
+/// The exception classes.
+
+#ifndef WPI_MEMORY_ERROR_HPP_INCLUDED
+#define WPI_MEMORY_ERROR_HPP_INCLUDED
+
+#include <cstddef>
+#include <new>
+
+#include "config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// Contains information about an allocator.
+        /// It can be used for logging in the various handler functions.
+        /// \ingroup core
+        struct allocator_info
+        {
+            /// The name of the allocator.
+            /// It is a NTBS whose lifetime is not managed by this object,
+            /// it must be stored elsewhere or be a string literal.
+            const char* name;
+
+            /// A pointer representing an allocator.
+            /// It does not necessarily point to the beginning of the allocator object,
+            /// the only guarantee is that different allocator objects result in a different pointer value.
+            /// For stateless allocators it is sometimes \c nullptr.
+            /// \note The pointer must not be cast back to any allocator type.
+            const void* allocator;
+
+            /// \effects Creates it by giving it the name of the allocator and a pointer.
+            constexpr allocator_info(const char* n, const void* alloc) noexcept
+            : name(n), allocator(alloc)
+            {
+            }
+
+            /// @{
+            /// \effects Compares two \ref allocator_info objects, they are equal, if the \ref allocator is the same.
+            /// \returns The result of the comparision.
+            friend constexpr bool operator==(const allocator_info& a,
+                                             const allocator_info& b) noexcept
+            {
+                return a.allocator == b.allocator;
+            }
+
+            friend constexpr bool operator!=(const allocator_info& a,
+                                             const allocator_info& b) noexcept
+            {
+                return a.allocator != b.allocator;
+            }
+            /// @}
+        };
+
+        /// The exception class thrown when a low level allocator runs out of memory.
+        /// It is derived from \c std::bad_alloc.
+        /// This can happen if a low level allocation function like \c std::malloc() runs out of memory.
+        /// Throwing can be prohibited by the handler function.
+        /// \ingroup core
+        class out_of_memory : public std::bad_alloc
+        {
+        public:
+            /// The type of the handler called in the constructor of \ref out_of_memory.
+            /// When an out of memory situation is encountered and the exception class created,
+            /// this handler gets called.
+            /// It is especially useful if exception support is disabled.
+            /// It gets the \ref allocator_info and the amount of memory that was tried to be allocated.
+            /// \requiredbe It can log the error, throw a different exception derived from \c std::bad_alloc or abort the program.
+            /// If it returns, this exception object will be created and thrown.
+            /// \defaultbe On a hosted implementation it logs the error on \c stderr and continues execution,
+            /// leading to this exception being thrown.
+            /// On a freestanding implementation it does nothing.
+            /// \note It is different from \c std::new_handler; it will not be called in a loop trying to allocate memory
+            /// or something like that. Its only job is to report the error.
+            using handler = void (*)(const allocator_info& info, std::size_t amount);
+
+            /// \effects Sets \c h as the new \ref handler in an atomic operation.
+            /// A \c nullptr sets the default \ref handler.
+            /// \returns The previous \ref handler. This is never \c nullptr.
+            static handler set_handler(handler h);
+
+            /// \returns The current \ref handler. This is never \c nullptr.
+            static handler get_handler();
+
+            /// \effects Creates it by passing it the \ref allocator_info and the amount of memory failed to be allocated.
+            /// It also calls the \ref handler to control whether or not it will be thrown.
+            out_of_memory(const allocator_info& info, std::size_t amount);
+
+            /// \returns A static NTBS that describes the error.
+            /// It does not contain any specific information since there is no memory for formatting.
+            const char* what() const noexcept override;
+
+            /// \returns The \ref allocator_info passed to it in the constructor.
+            const allocator_info& allocator() const noexcept
+            {
+                return info_;
+            }
+
+            /// \returns The amount of memory that was tried to be allocated.
+            /// This is the value passed in the constructor.
+            std::size_t failed_allocation_size() const noexcept
+            {
+                return amount_;
+            }
+
+        private:
+            allocator_info info_;
+            std::size_t    amount_;
+        };
+
+        /// A special case of \ref out_of_memory errors
+        /// thrown when a low-level allocator with a fixed size runs out of memory.
+        /// For example, thrown by \ref fixed_block_allocator or \ref static_allocator.<br>
+        /// It is derived from \ref out_of_memory but does not provide its own handler.
+        /// \ingroup core
+        class out_of_fixed_memory : public out_of_memory
+        {
+        public:
+            /// \effects Just forwards to \ref out_of_memory.
+            out_of_fixed_memory(const allocator_info& info, std::size_t amount)
+            : out_of_memory(info, amount)
+            {
+            }
+
+            /// \returns A static NTBS that describes the error.
+            /// It does not contain any specific information since there is no memory for formatting.
+            const char* what() const noexcept override;
+        };
+
+        /// The exception class thrown when an allocation size is bigger than the supported maximum.
+        /// This size is either the node, array or alignment parameter in a call to an allocation function.
+        /// If those exceed the supported maximum returned by \c max_node_size(), \c max_array_size() or \c max_alignment(),
+        /// one of its derived classes will be thrown or this class if in a situation where the type is unknown.
+        /// It is derived from \c std::bad_alloc.
+        /// Throwing can be prohibited by the handler function.
+        /// \note Even if all parameters are less than the maximum, \ref out_of_memory or a similar exception can be thrown,
+        /// because the maximum functions return an upper bound and not the actual supported maximum size,
+        /// since it always depends on fence memory, alignment buffer and the like.
+        /// \note A user should only \c catch for \c bad_allocation_size, not the derived classes.
+        /// \note Most checks will only be done if \ref WPI_MEMORY_CHECK_ALLOCATION_SIZE is \c true.
+        /// \ingroup core
+        class bad_allocation_size : public std::bad_alloc
+        {
+        public:
+            /// The type of the handler called in the constructor of \ref bad_allocation_size.
+            /// When a bad allocation size is detected and the exception object created,
+            /// this handler gets called.
+            /// It is especially useful if exception support is disabled.
+            /// It gets the \ref allocator_info, the size passed to the function and the supported size
+            /// (the latter is still an upper bound).
+            /// \requiredbe It can log the error, throw a different exception derived from \c std::bad_alloc or abort the program.
+            /// If it returns, this exception object will be created and thrown.
+            /// \defaultbe On a hosted implementation it logs the error on \c stderr and continues execution,
+            /// leading to this exception being thrown.
+            /// On a freestanding implementation it does nothing.
+            using handler = void (*)(const allocator_info& info, std::size_t passed,
+                                     std::size_t supported);
+
+            /// \effects Sets \c h as the new \ref handler in an atomic operation.
+            /// A \c nullptr sets the default \ref handler.
+            /// \returns The previous \ref handler. This is never \c nullptr.
+            static handler set_handler(handler h);
+
+            /// \returns The current \ref handler. This is never \c nullptr.
+            static handler get_handler();
+
+            /// \effects Creates it by passing it the \ref allocator_info, the size passed to the allocation function
+            /// and an upper bound on the supported size.
+            /// It also calls the \ref handler to control whether or not it will be thrown.
+            bad_allocation_size(const allocator_info& info, std::size_t passed,
+                                std::size_t supported);
+
+            /// \returns A static NTBS that describes the error.
+            /// It does not contain any specific information since there is no memory for formatting.
+            const char* what() const noexcept override;
+
+            /// \returns The \ref allocator_info passed to it in the constructor.
+            const allocator_info& allocator() const noexcept
+            {
+                return info_;
+            }
+
+            /// \returns The size or alignment value that was passed to the allocation function
+            /// which was too big. This is the same value passed to the constructor.
+            std::size_t passed_value() const noexcept
+            {
+                return passed_;
+            }
+
+            /// \returns An upper bound on the maximum supported size/alignment.
+            /// It is only an upper bound, values below can fail, but values above will always fail.
+            std::size_t supported_value() const noexcept
+            {
+                return supported_;
+            }
+
+        private:
+            allocator_info info_;
+            std::size_t    passed_, supported_;
+        };
+
+        /// The exception class thrown when the node size exceeds the supported maximum,
+        /// i.e. it is bigger than \c max_node_size().
+        /// It is derived from \ref bad_allocation_size but does not override the handler.
+        /// \ingroup core
+        class bad_node_size : public bad_allocation_size
+        {
+        public:
+            /// \effects Just forwards to \ref bad_allocation_size.
+            bad_node_size(const allocator_info& info, std::size_t passed, std::size_t supported)
+            : bad_allocation_size(info, passed, supported)
+            {
+            }
+
+            /// \returns A static NTBS that describes the error.
+            /// It does not contain any specific information since there is no memory for formatting.
+            const char* what() const noexcept override;
+        };
+
+        /// The exception class thrown when the array size exceeds the supported maximum,
+        /// i.e. it is bigger than \c max_array_size().
+        /// It is derived from \ref bad_allocation_size but does not override the handler.
+        /// \ingroup core
+        class bad_array_size : public bad_allocation_size
+        {
+        public:
+            /// \effects Just forwards to \ref bad_allocation_size.
+            bad_array_size(const allocator_info& info, std::size_t passed, std::size_t supported)
+            : bad_allocation_size(info, passed, supported)
+            {
+            }
+
+            /// \returns A static NTBS that describes the error.
+            /// It does not contain any specific information since there is no memory for formatting.
+            const char* what() const noexcept override;
+        };
+
+        /// The exception class thrown when the alignment exceeds the supported maximum,
+        /// i.e. it is bigger than \c max_alignment().
+        /// It is derived from \ref bad_allocation_size but does not override the handler.
+        /// \ingroup core
+        class bad_alignment : public bad_allocation_size
+        {
+        public:
+            /// \effects Just forwards to \ref bad_allocation_size.
+            /// \c passed is <tt>count * size</tt>, \c supported the size in bytes.
+            bad_alignment(const allocator_info& info, std::size_t passed, std::size_t supported)
+            : bad_allocation_size(info, passed, supported)
+            {
+            }
+
+            /// \returns A static NTBS that describes the error.
+            /// It does not contain any specific information since there is no memory for formatting.
+            const char* what() const noexcept override;
+        };
+
+        namespace detail
+        {
+            template <class Ex, typename Func>
+            void check_allocation_size(std::size_t passed, Func f, const allocator_info& info)
+            {
+#if WPI_MEMORY_CHECK_ALLOCATION_SIZE
+                auto supported = f();
+                if (passed > supported)
+                    WPI_THROW(Ex(info, passed, supported));
+#else
+                (void)passed;
+                (void)f;
+                (void)info;
+#endif
+            }
+
+            template <class Ex>
+            void check_allocation_size(std::size_t passed, std::size_t supported,
+                                       const allocator_info& info)
+            {
+                check_allocation_size<Ex>(
+                    passed, [&] { return supported; }, info);
+            }
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_ERROR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/fallback_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/fallback_allocator.hpp
new file mode 100644
index 0000000..3bf530e
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/fallback_allocator.hpp
@@ -0,0 +1,212 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_FALLBACK_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_FALLBACK_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+//// Class template \ref wpi::memory::fallback_allocator.
+
+#include "detail/ebo_storage.hpp"
+#include "detail/utility.hpp"
+#include "allocator_traits.hpp"
+#include "config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// A \concept{raw_allocator,RawAllocator} with a fallback.
+        /// Allocation first tries `Default`, if it fails,
+        /// it uses `Fallback`.
+        /// \requires `Default` must be a composable \concept{concept_rawallocator,RawAllocator},
+        /// `Fallback` must be a \concept{concept_rawallocator,RawAllocator}.
+        /// \ingroup adapter
+        template <class Default, class Fallback>
+        class fallback_allocator
+        : WPI_EBO(detail::ebo_storage<0, typename allocator_traits<Default>::allocator_type>),
+          WPI_EBO(detail::ebo_storage<1, typename allocator_traits<Fallback>::allocator_type>)
+        {
+            using default_traits             = allocator_traits<Default>;
+            using default_composable_traits  = composable_allocator_traits<Default>;
+            using fallback_traits            = allocator_traits<Fallback>;
+            using fallback_composable_traits = composable_allocator_traits<Fallback>;
+            using fallback_composable =
+                is_composable_allocator<typename fallback_traits::allocator_type>;
+
+        public:
+            using default_allocator_type  = typename allocator_traits<Default>::allocator_type;
+            using fallback_allocator_type = typename allocator_traits<Fallback>::allocator_type;
+
+            using is_stateful =
+                std::integral_constant<bool, default_traits::is_stateful::value
+                                                 || fallback_traits::is_stateful::value>;
+
+            /// \effects Default constructs both allocators.
+            /// \notes This function only participates in overload resolution, if both allocators are not stateful.
+            WPI_ENABLE_IF(!is_stateful::value)
+            fallback_allocator()
+            : detail::ebo_storage<0, default_allocator_type>({}),
+              detail::ebo_storage<1, fallback_allocator_type>({})
+            {
+            }
+
+            /// \effects Constructs the allocator by passing in the two allocators it has.
+            explicit fallback_allocator(default_allocator_type&&  default_alloc,
+                                        fallback_allocator_type&& fallback_alloc = {})
+            : detail::ebo_storage<0, default_allocator_type>(detail::move(default_alloc)),
+              detail::ebo_storage<1, fallback_allocator_type>(detail::move(fallback_alloc))
+            {
+            }
+
+            /// @{
+            /// \effects First calls the compositioning (de)allocation function on the `default_allocator_type`.
+            /// If that fails, uses the non-compositioning function of the `fallback_allocator_type`.
+            void* allocate_node(std::size_t size, std::size_t alignment)
+            {
+                auto ptr = default_composable_traits::try_allocate_node(get_default_allocator(),
+                                                                        size, alignment);
+                if (!ptr)
+                    ptr = fallback_traits::allocate_node(get_fallback_allocator(), size, alignment);
+                return ptr;
+            }
+
+            void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)
+            {
+                auto ptr = default_composable_traits::try_allocate_array(get_default_allocator(),
+                                                                         count, size, alignment);
+                if (!ptr)
+                    ptr = fallback_traits::allocate_array(get_fallback_allocator(), count, size,
+                                                          alignment);
+                return ptr;
+            }
+
+            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                auto res = default_composable_traits::try_deallocate_node(get_default_allocator(),
+                                                                          ptr, size, alignment);
+                if (!res)
+                    fallback_traits::deallocate_node(get_fallback_allocator(), ptr, size,
+                                                     alignment);
+            }
+
+            void deallocate_array(void* ptr, std::size_t count, std::size_t size,
+                                  std::size_t alignment) noexcept
+            {
+                auto res =
+                    default_composable_traits::try_deallocate_array(get_default_allocator(), ptr,
+                                                                    count, size, alignment);
+                if (!res)
+                    fallback_traits::deallocate_array(get_fallback_allocator(), ptr, count, size,
+                                                      alignment);
+            }
+            /// @}
+
+            /// @{
+            /// \effects First calls the compositioning (de)allocation function on the `default_allocator_type`.
+            /// If that fails, uses the compositioning function of the `fallback_allocator_type`.
+            /// \requires The `fallback_allocator_type` msut be composable.
+            WPI_ENABLE_IF(fallback_composable::value)
+            void* try_allocate_node(std::size_t size, std::size_t alignment) noexcept
+            {
+                auto ptr = default_composable_traits::try_allocate_node(get_default_allocator(),
+                                                                        size, alignment);
+                if (!ptr)
+                    ptr = fallback_composable_traits::try_allocate_node(get_fallback_allocator(),
+                                                                        size, alignment);
+                return ptr;
+            }
+
+            WPI_ENABLE_IF(fallback_composable::value)
+            void* allocate_array(std::size_t count, std::size_t size,
+                                 std::size_t alignment) noexcept
+            {
+                auto ptr = default_composable_traits::try_allocate_array(get_default_allocator(),
+                                                                         count, size, alignment);
+                if (!ptr)
+                    ptr = fallback_composable_traits::try_allocate_array(get_fallback_allocator(),
+                                                                         count, size, alignment);
+                return ptr;
+            }
+
+            WPI_ENABLE_IF(fallback_composable::value)
+            bool try_deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                auto res = default_composable_traits::try_deallocate_node(get_default_allocator(),
+                                                                          ptr, size, alignment);
+                if (!res)
+                    res = fallback_composable_traits::try_deallocate_node(get_fallback_allocator(),
+                                                                          ptr, size, alignment);
+                return res;
+            }
+
+            WPI_ENABLE_IF(fallback_composable::value)
+            bool try_deallocate_array(void* ptr, std::size_t count, std::size_t size,
+                                      std::size_t alignment) noexcept
+            {
+                auto res =
+                    default_composable_traits::try_deallocate_array(get_default_allocator(), ptr,
+                                                                    count, size, alignment);
+                if (!res)
+                    res = fallback_composable_traits::try_deallocate_array(get_fallback_allocator(),
+                                                                           ptr, count, size,
+                                                                           alignment);
+                return res;
+            }
+            /// @}
+
+            /// @{
+            /// \returns The maximum of the two values from both allocators.
+            std::size_t max_node_size() const
+            {
+                auto def      = default_traits::max_node_size(get_default_allocator());
+                auto fallback = fallback_traits::max_node_size(get_fallback_allocator());
+                return fallback > def ? fallback : def;
+            }
+
+            std::size_t max_array_size() const
+            {
+                auto def      = default_traits::max_array_size(get_default_allocator());
+                auto fallback = fallback_traits::max_array_size(get_fallback_allocator());
+                return fallback > def ? fallback : def;
+            }
+
+            std::size_t max_alignment() const
+            {
+                auto def      = default_traits::max_alignment(get_default_allocator());
+                auto fallback = fallback_traits::max_alignment(get_fallback_allocator());
+                return fallback > def ? fallback : def;
+            }
+            /// @}
+
+            /// @{
+            /// \returns A (`const`) reference to the default allocator.
+            default_allocator_type& get_default_allocator() noexcept
+            {
+                return detail::ebo_storage<0, default_allocator_type>::get();
+            }
+
+            const default_allocator_type& get_default_allocator() const noexcept
+            {
+                return detail::ebo_storage<0, default_allocator_type>::get();
+            }
+            /// @}
+
+            /// @{
+            /// \returns A (`const`) reference to the fallback allocator.
+            fallback_allocator_type& get_fallback_allocator() noexcept
+            {
+                return detail::ebo_storage<1, fallback_allocator_type>::get();
+            }
+
+            const fallback_allocator_type& get_fallback_allocator() const noexcept
+            {
+                return detail::ebo_storage<1, fallback_allocator_type>::get();
+            }
+            /// @}
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_FALLBACK_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/heap_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/heap_allocator.hpp
new file mode 100644
index 0000000..0724937
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/heap_allocator.hpp
@@ -0,0 +1,83 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_HEAP_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_HEAP_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::heap_allocator and related functions.
+
+#include "detail/lowlevel_allocator.hpp"
+#include "config.hpp"
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+#include "allocator_traits.hpp"
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        struct allocator_info;
+
+        /// Allocates heap memory.
+        /// This function is used by the \ref heap_allocator to allocate the heap memory.
+        /// It is not defined on a freestanding implementation, a definition must be provided by the library user.
+        /// \requiredbe This function shall return a block of uninitialized memory that is aligned for \c max_align_t and has the given size.
+        /// The size parameter will not be zero.
+        /// It shall return a \c nullptr if no memory is available.
+        /// It must be thread safe.
+        /// \defaultbe On a hosted implementation this function uses OS specific facilities, \c std::malloc is used as fallback.
+        /// \ingroup allocator
+        void* heap_alloc(std::size_t size) noexcept;
+
+        /// Deallocates heap memory.
+        /// This function is used by the \ref heap_allocator to allocate the heap memory.
+        /// It is not defined on a freestanding implementation, a definition must be provided by the library user.
+        /// \requiredbe This function gets a pointer from a previous call to \ref heap_alloc with the same size.
+        /// It shall free the memory.
+        /// The pointer will not be zero.
+        /// It must be thread safe.
+        /// \defaultbe On a hosted implementation this function uses OS specific facilities, \c std::free is used as fallback.
+        /// \ingroup allocator
+        void heap_dealloc(void* ptr, std::size_t size) noexcept;
+
+        namespace detail
+        {
+            struct heap_allocator_impl
+            {
+                static allocator_info info() noexcept;
+
+                static void* allocate(std::size_t size, std::size_t) noexcept
+                {
+                    return heap_alloc(size);
+                }
+
+                static void deallocate(void* ptr, std::size_t size, std::size_t) noexcept
+                {
+                    heap_dealloc(ptr, size);
+                }
+
+                static std::size_t max_node_size() noexcept;
+            };
+
+            WPI_MEMORY_LL_ALLOCATOR_LEAK_CHECKER(heap_allocator_impl,
+                                                       heap_alloator_leak_checker)
+        } // namespace detail
+
+        /// A stateless \concept{concept_rawallocator,RawAllocator} that allocates memory from the heap.
+        /// It uses the two functions \ref heap_alloc and \ref heap_dealloc for the allocation,
+        /// which default to \c std::malloc and \c std::free.
+        /// \ingroup allocator
+        using heap_allocator =
+            WPI_IMPL_DEFINED(detail::lowlevel_allocator<detail::heap_allocator_impl>);
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class detail::lowlevel_allocator<detail::heap_allocator_impl>;
+        extern template class allocator_traits<heap_allocator>;
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_HEAP_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/iteration_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/iteration_allocator.hpp
new file mode 100644
index 0000000..d35a927
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/iteration_allocator.hpp
@@ -0,0 +1,305 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_ITERATION_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_ITERATION_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Class template \ref wpi::memory::iteration_allocator.
+
+#include "detail/debug_helpers.hpp"
+#include "detail/memory_stack.hpp"
+#include "default_allocator.hpp"
+#include "error.hpp"
+#include "memory_arena.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            template <class BlockOrRawAllocator>
+            using iteration_block_allocator =
+                make_block_allocator_t<BlockOrRawAllocator, fixed_block_allocator>;
+        } // namespace detail
+
+        /// A stateful \concept{concept_rawallocator,RawAllocator} that is designed for allocations in a loop.
+        /// It uses `N` stacks for the allocation, one of them is always active.
+        /// Allocation uses the currently active stack.
+        /// Calling \ref iteration_allocator::next_iteration() at the end of the loop,
+        /// will make the next stack active for allocation,
+        /// effectively releasing all of its memory.
+        /// Any memory allocated will thus be usable for `N` iterations of the loop.
+        /// This type of allocator is a generalization of the double frame allocator.
+        /// \ingroup allocator
+        template <std::size_t N, class BlockOrRawAllocator = default_allocator>
+        class iteration_allocator
+        : WPI_EBO(detail::iteration_block_allocator<BlockOrRawAllocator>)
+        {
+        public:
+            using allocator_type = detail::iteration_block_allocator<BlockOrRawAllocator>;
+
+            /// \effects Creates it with a given initial block size and and other constructor arguments for the \concept{concept_blockallocator,BlockAllocator}.
+            /// It will allocate the first (and only) block and evenly divide it on all the stacks it uses.
+            template <typename... Args>
+            explicit iteration_allocator(std::size_t block_size, Args&&... args)
+            : allocator_type(block_size, detail::forward<Args>(args)...), cur_(0u)
+            {
+                block_         = get_allocator().allocate_block();
+                auto cur       = static_cast<char*>(block_.memory);
+                auto size_each = block_.size / N;
+                for (auto i = 0u; i != N; ++i)
+                {
+                    stacks_[i] = detail::fixed_memory_stack(cur);
+                    cur += size_each;
+                }
+            }
+
+            iteration_allocator(iteration_allocator&& other) noexcept
+            : allocator_type(detail::move(other)),
+              block_(other.block_),
+              cur_(detail::move(other.cur_))
+            {
+                for (auto i = 0u; i != N; ++i)
+                    stacks_[i] = detail::move(other.stacks_[i]);
+
+                other.cur_ = N;
+            }
+
+            ~iteration_allocator() noexcept
+            {
+                if (cur_ < N)
+                    get_allocator().deallocate_block(block_);
+            }
+
+            iteration_allocator& operator=(iteration_allocator&& other) noexcept
+            {
+                allocator_type::operator=(detail::move(other));
+                block_                  = other.block_;
+                cur_                    = other.cur_;
+
+                for (auto i = 0u; i != N; ++i)
+                    stacks_[i] = detail::move(other.stacks_[i]);
+
+                other.cur_ = N;
+
+                return *this;
+            }
+
+            /// \effects Allocates a memory block of given size and alignment.
+            /// It simply moves the top marker of the currently active stack.
+            /// \returns A \concept{concept_node,node} with given size and alignment.
+            /// \throws \ref out_of_fixed_memory if the current stack does not have any memory left.
+            /// \requires \c size and \c alignment must be valid.
+            void* allocate(std::size_t size, std::size_t alignment)
+            {
+                auto& stack = stacks_[cur_];
+
+                auto fence  = detail::debug_fence_size;
+                auto offset = detail::align_offset(stack.top() + fence, alignment);
+                if (!stack.top()
+                    || (fence + offset + size + fence > std::size_t(block_end(cur_) - stack.top())))
+                    WPI_THROW(out_of_fixed_memory(info(), size));
+                return stack.allocate_unchecked(size, offset);
+            }
+
+            /// \effects Allocates a memory block of given size and alignment
+            /// similar to \ref allocate().
+            /// \returns A \concept{concept_node,node} with given size and alignment
+            /// or `nullptr` if the current stack does not have any memory left.
+            void* try_allocate(std::size_t size, std::size_t alignment) noexcept
+            {
+                auto& stack = stacks_[cur_];
+                return stack.allocate(block_end(cur_), size, alignment);
+            }
+
+            /// \effects Goes to the next internal stack.
+            /// This will clear the stack whose \ref max_iterations() lifetime has reached,
+            /// and use it for all allocations in this iteration.
+            /// \note This function should be called at the end of the loop.
+            void next_iteration() noexcept
+            {
+                WPI_MEMORY_ASSERT_MSG(cur_ != N, "moved-from allocator");
+                cur_ = (cur_ + 1) % N;
+                stacks_[cur_].unwind(block_start(cur_));
+            }
+
+            /// \returns The number of iteration each allocation will live.
+            /// This is the template parameter `N`.
+            static std::size_t max_iterations() noexcept
+            {
+                return N;
+            }
+
+            /// \returns The index of the current iteration.
+            /// This is modulo \ref max_iterations().
+            std::size_t cur_iteration() const noexcept
+            {
+                return cur_;
+            }
+
+            /// \returns A reference to the \concept{concept_blockallocator,BlockAllocator} used for managing the memory.
+            /// \requires It is undefined behavior to move this allocator out into another object.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+            /// \returns The amount of memory remaining in the stack with the given index.
+            /// This is the number of bytes that are available for allocation.
+            std::size_t capacity_left(std::size_t i) const noexcept
+            {
+                return std::size_t(block_end(i) - stacks_[i].top());
+            }
+
+            /// \returns The amount of memory remaining in the currently active stack.
+            std::size_t capacity_left() const noexcept
+            {
+                return capacity_left(cur_iteration());
+            }
+
+        private:
+            allocator_info info() const noexcept
+            {
+                return {WPI_MEMORY_LOG_PREFIX "::iteration_allocator", this};
+            }
+
+            char* block_start(std::size_t i) const noexcept
+            {
+                WPI_MEMORY_ASSERT_MSG(i <= N, "moved from state");
+                auto ptr = static_cast<char*>(block_.memory);
+                return ptr + (i * block_.size / N);
+            }
+
+            char* block_end(std::size_t i) const noexcept
+            {
+                WPI_MEMORY_ASSERT_MSG(i < N, "moved from state");
+                return block_start(i + 1);
+            }
+
+            detail::fixed_memory_stack stacks_[N];
+            memory_block               block_;
+            std::size_t                cur_;
+
+            friend allocator_traits<iteration_allocator<N, BlockOrRawAllocator>>;
+            friend composable_allocator_traits<iteration_allocator<N, BlockOrRawAllocator>>;
+        };
+
+        /// An alias for \ref iteration_allocator for two iterations.
+        /// \ingroup allocator
+        template <class BlockOrRawAllocator = default_allocator>
+        WPI_ALIAS_TEMPLATE(double_frame_allocator,
+                                 iteration_allocator<2, BlockOrRawAllocator>);
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class iteration_allocator<2>;
+#endif
+
+        /// Specialization of the \ref allocator_traits for \ref iteration_allocator.
+        /// \note It is not allowed to mix calls through the specialization and through the member functions,
+        /// i.e. \ref memory_stack::allocate() and this \c allocate_node().
+        /// \ingroup allocator
+        template <std::size_t N, class BlockAllocator>
+        class allocator_traits<iteration_allocator<N, BlockAllocator>>
+        {
+        public:
+            using allocator_type = iteration_allocator<N, BlockAllocator>;
+            using is_stateful    = std::true_type;
+
+            /// \returns The result of \ref iteration_allocator::allocate().
+            static void* allocate_node(allocator_type& state, std::size_t size,
+                                       std::size_t alignment)
+            {
+                return state.allocate(size, alignment);
+            }
+
+            /// \returns The result of \ref memory_stack::allocate().
+            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size,
+                                        std::size_t alignment)
+            {
+                return allocate_node(state, count * size, alignment);
+            }
+
+            /// @{
+            /// \effects Does nothing.
+            /// Actual deallocation can only be done via \ref memory_stack::unwind().
+            static void deallocate_node(allocator_type&, void*, std::size_t, std::size_t) noexcept
+            {
+            }
+
+            static void deallocate_array(allocator_type&, void*, std::size_t, std::size_t,
+                                         std::size_t) noexcept
+            {
+            }
+            /// @}
+
+            /// @{
+            /// \returns The maximum size which is \ref iteration_allocator::capacity_left().
+            static std::size_t max_node_size(const allocator_type& state) noexcept
+            {
+                return state.capacity_left();
+            }
+
+            static std::size_t max_array_size(const allocator_type& state) noexcept
+            {
+                return state.capacity_left();
+            }
+            /// @}
+
+            /// \returns The maximum possible value since there is no alignment restriction
+            /// (except indirectly through \ref memory_stack::next_capacity()).
+            static std::size_t max_alignment(const allocator_type&) noexcept
+            {
+                return std::size_t(-1);
+            }
+        };
+
+        /// Specialization of the \ref composable_allocator_traits for \ref iteration_allocator classes.
+        /// \ingroup allocator
+        template <std::size_t N, class BlockAllocator>
+        class composable_allocator_traits<iteration_allocator<N, BlockAllocator>>
+        {
+        public:
+            using allocator_type = iteration_allocator<N, BlockAllocator>;
+
+            /// \returns The result of \ref memory_stack::try_allocate().
+            static void* try_allocate_node(allocator_type& state, std::size_t size,
+                                           std::size_t alignment) noexcept
+            {
+                return state.try_allocate(size, alignment);
+            }
+
+            /// \returns The result of \ref memory_stack::try_allocate().
+            static void* try_allocate_array(allocator_type& state, std::size_t count,
+                                            std::size_t size, std::size_t alignment) noexcept
+            {
+                return state.try_allocate(count * size, alignment);
+            }
+
+            /// @{
+            /// \effects Does nothing.
+            /// \returns Whether the memory will be deallocated by \ref memory_stack::unwind().
+            static bool try_deallocate_node(allocator_type& state, void* ptr, std::size_t,
+                                            std::size_t) noexcept
+            {
+                return state.block_.contains(ptr);
+            }
+
+            static bool try_deallocate_array(allocator_type& state, void* ptr, std::size_t count,
+                                             std::size_t size, std::size_t alignment) noexcept
+            {
+                return try_deallocate_node(state, ptr, count * size, alignment);
+            }
+            /// @}
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class allocator_traits<iteration_allocator<2>>;
+        extern template class composable_allocator_traits<iteration_allocator<2>>;
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_ITERATION_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/joint_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/joint_allocator.hpp
new file mode 100644
index 0000000..db67d46
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/joint_allocator.hpp
@@ -0,0 +1,927 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_JOINT_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_JOINT_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Class template \ref wpi::memory::joint_ptr, \ref wpi::memory::joint_allocator and related.
+
+#include <initializer_list>
+#include <new>
+
+#include "detail/align.hpp"
+#include "detail/memory_stack.hpp"
+#include "detail/utility.hpp"
+#include "allocator_storage.hpp"
+#include "config.hpp"
+#include "default_allocator.hpp"
+#include "error.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        template <typename T, class RawAllocator>
+        class joint_ptr;
+
+        template <typename T>
+        class joint_type;
+
+        namespace detail
+        {
+            // the stack that allocates the joint memory
+            class joint_stack
+            {
+            public:
+                joint_stack(void* mem, std::size_t cap) noexcept
+                : stack_(static_cast<char*>(mem)), end_(static_cast<char*>(mem) + cap)
+                {
+                }
+
+                void* allocate(std::size_t size, std::size_t alignment) noexcept
+                {
+                    return stack_.allocate(end_, size, alignment, 0u);
+                }
+
+                bool bump(std::size_t offset) noexcept
+                {
+                    if (offset > std::size_t(end_ - stack_.top()))
+                        return false;
+                    stack_.bump(offset);
+                    return true;
+                }
+
+                char* top() noexcept
+                {
+                    return stack_.top();
+                }
+
+                const char* top() const noexcept
+                {
+                    return stack_.top();
+                }
+
+                void unwind(void* ptr) noexcept
+                {
+                    stack_.unwind(static_cast<char*>(ptr));
+                }
+
+                std::size_t capacity(const char* mem) const noexcept
+                {
+                    return std::size_t(end_ - mem);
+                }
+
+                std::size_t capacity_left() const noexcept
+                {
+                    return std::size_t(end_ - top());
+                }
+
+                std::size_t capacity_used(const char* mem) const noexcept
+                {
+                    return std::size_t(top() - mem);
+                }
+
+            private:
+                detail::fixed_memory_stack stack_;
+                char*                      end_;
+            };
+
+            template <typename T>
+            detail::joint_stack& get_stack(joint_type<T>& obj) noexcept;
+
+            template <typename T>
+            const detail::joint_stack& get_stack(const joint_type<T>& obj) noexcept;
+        } // namespace detail
+
+        /// Tag type that can't be created.
+        ///
+        /// It isued by \ref joint_ptr.
+        /// \ingroup allocator
+        class joint
+        {
+            joint(std::size_t cap) noexcept : capacity(cap) {}
+
+            std::size_t capacity;
+
+            template <typename T, class RawAllocator>
+            friend class joint_ptr;
+            template <typename T>
+            friend class joint_type;
+        };
+
+        /// Tag type to make the joint size more explicit.
+        ///
+        /// It is used by \ref joint_ptr.
+        /// \ingroup allocator
+        struct joint_size
+        {
+            std::size_t size;
+
+            explicit joint_size(std::size_t s) noexcept : size(s) {}
+        };
+
+        /// CRTP base class for all objects that want to use joint memory.
+        ///
+        /// This will disable default copy/move operations
+        /// and inserts additional members for the joint memory management.
+        /// \ingroup allocator
+        template <typename T>
+        class joint_type
+        {
+        protected:
+            /// \effects Creates the base class,
+            /// the tag type cannot be created by the user.
+            /// \note This ensures that you cannot create joint types yourself.
+            joint_type(joint j) noexcept;
+
+            joint_type(const joint_type&) = delete;
+            joint_type(joint_type&&)      = delete;
+
+        private:
+            detail::joint_stack stack_;
+
+            template <typename U>
+            friend detail::joint_stack& detail::get_stack(joint_type<U>& obj) noexcept;
+            template <typename U>
+            friend const detail::joint_stack& detail::get_stack(const joint_type<U>& obj) noexcept;
+        };
+
+        namespace detail
+        {
+            template <typename T>
+            detail::joint_stack& get_stack(joint_type<T>& obj) noexcept
+            {
+                return obj.stack_;
+            }
+
+            template <typename T>
+            const detail::joint_stack& get_stack(const joint_type<T>& obj) noexcept
+            {
+                return obj.stack_;
+            }
+
+            template <typename T>
+            char* get_memory(joint_type<T>& obj) noexcept
+            {
+                auto mem = static_cast<void*>(&obj);
+                return static_cast<char*>(mem) + sizeof(T);
+            }
+
+            template <typename T>
+            const char* get_memory(const joint_type<T>& obj) noexcept
+            {
+                auto mem = static_cast<const void*>(&obj);
+                return static_cast<const char*>(mem) + sizeof(T);
+            }
+
+        } // namespace detail
+
+        template <typename T>
+        joint_type<T>::joint_type(joint j) noexcept : stack_(detail::get_memory(*this), j.capacity)
+        {
+            WPI_MEMORY_ASSERT(stack_.top() == detail::get_memory(*this));
+            WPI_MEMORY_ASSERT(stack_.capacity_left() == j.capacity);
+        }
+
+        /// A pointer to an object where all allocations are joint.
+        ///
+        /// It can either own an object or not (be `nullptr`).
+        /// When it owns an object, it points to a memory block.
+        /// This memory block contains both the actual object (of the type `T`)
+        /// and space for allocations of `T`s members.
+        ///
+        /// The type `T` must be derived from \ref joint_type and every constructor must take \ref joint
+        /// as first parameter.
+        /// This prevents that you create joint objects yourself,
+        /// without the additional storage.
+        /// The default copy and move constructors are also deleted,
+        /// you need to write them yourself.
+        ///
+        /// You can only access the object through the pointer,
+        /// use \ref joint_allocator or \ref joint_array as members of `T`,
+        /// to enable the memory sharing.
+        /// If you are using \ref joint_allocator inside STL containers,
+        /// make sure that you do not call their regular copy/move constructors,
+        /// but instead the version where you pass an allocator.
+        ///
+        /// The memory block will be managed by the given \concept{concept_rawallocator,RawAllocator},
+        /// it is stored in an \ref allocator_reference and not owned by the pointer directly.
+        /// \ingroup allocator
+        template <typename T, class RawAllocator>
+        class joint_ptr : WPI_EBO(allocator_reference<RawAllocator>)
+        {
+            static_assert(std::is_base_of<joint_type<T>, T>::value,
+                          "T must be derived of joint_type<T>");
+
+        public:
+            using element_type   = T;
+            using allocator_type = typename allocator_reference<RawAllocator>::allocator_type;
+
+            //=== constructors/destructor/assignment ===//
+            /// @{
+            /// \effects Creates it with a \concept{concept_rawallocator,RawAllocator}, but does not own a new object.
+            explicit joint_ptr(allocator_type& alloc) noexcept
+            : allocator_reference<RawAllocator>(alloc), ptr_(nullptr)
+            {
+            }
+
+            explicit joint_ptr(const allocator_type& alloc) noexcept
+            : allocator_reference<RawAllocator>(alloc), ptr_(nullptr)
+            {
+            }
+            /// @}
+
+            /// @{
+            /// \effects Reserves memory for the object and the additional size,
+            /// and creates the object by forwarding the arguments to its constructor.
+            /// The \concept{concept_rawallocator,RawAllocator} will be used for the allocation.
+            template <typename... Args>
+            joint_ptr(allocator_type& alloc, joint_size additional_size, Args&&... args)
+            : joint_ptr(alloc)
+            {
+                create(additional_size.size, detail::forward<Args>(args)...);
+            }
+
+            template <typename... Args>
+            joint_ptr(const allocator_type& alloc, joint_size additional_size, Args&&... args)
+            : joint_ptr(alloc)
+            {
+                create(additional_size.size, detail::forward<Args>(args)...);
+            }
+            /// @}
+
+            /// \effects Move-constructs the pointer.
+            /// Ownership will be transferred from `other` to the new object.
+            joint_ptr(joint_ptr&& other) noexcept
+            : allocator_reference<RawAllocator>(detail::move(other)), ptr_(other.ptr_)
+            {
+                other.ptr_ = nullptr;
+            }
+
+            /// \effects Destroys the object and deallocates its storage.
+            ~joint_ptr() noexcept
+            {
+                reset();
+            }
+
+            /// \effects Move-assings the pointer.
+            /// The previously owned object will be destroyed,
+            /// and ownership of `other` transferred.
+            joint_ptr& operator=(joint_ptr&& other) noexcept
+            {
+                joint_ptr tmp(detail::move(other));
+                swap(*this, tmp);
+                return *this;
+            }
+
+            /// \effects Same as `reset()`.
+            joint_ptr& operator=(std::nullptr_t) noexcept
+            {
+                reset();
+                return *this;
+            }
+
+            /// \effects Swaps to pointers and their ownership and allocator.
+            friend void swap(joint_ptr& a, joint_ptr& b) noexcept
+            {
+                detail::adl_swap(static_cast<allocator_reference<RawAllocator>&>(a),
+                                 static_cast<allocator_reference<RawAllocator>&>(b));
+                detail::adl_swap(a.ptr_, b.ptr_);
+            }
+
+            //=== modifiers ===//
+            /// \effects Destroys the object it refers to,
+            /// if there is any.
+            void reset() noexcept
+            {
+                if (ptr_)
+                {
+                    (**this).~element_type();
+                    this->deallocate_node(ptr_,
+                                          sizeof(element_type)
+                                              + detail::get_stack(*ptr_).capacity(
+                                                  detail::get_memory(*ptr_)),
+                                          alignof(element_type));
+                    ptr_ = nullptr;
+                }
+            }
+
+            //=== accessors ===//
+            /// \returns `true` if the pointer does own an object,
+            /// `false` otherwise.
+            explicit operator bool() const noexcept
+            {
+                return ptr_ != nullptr;
+            }
+
+            /// \returns A reference to the object it owns.
+            /// \requires The pointer must own an object,
+            /// i.e. `operator bool()` must return `true`.
+            element_type& operator*() const noexcept
+            {
+                WPI_MEMORY_ASSERT(ptr_);
+                return *get();
+            }
+
+            /// \returns A pointer to the object it owns.
+            /// \requires The pointer must own an object,
+            /// i.e. `operator bool()` must return `true`.
+            element_type* operator->() const noexcept
+            {
+                WPI_MEMORY_ASSERT(ptr_);
+                return get();
+            }
+
+            /// \returns A pointer to the object it owns
+            /// or `nullptr`, if it does not own any object.
+            element_type* get() const noexcept
+            {
+                return static_cast<element_type*>(ptr_);
+            }
+
+            /// \returns A reference to the allocator it will use for the deallocation.
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<allocator_reference<allocator_type>>().get_allocator())
+            {
+                return this->allocator_reference<allocator_type>::get_allocator();
+            }
+
+        private:
+            template <typename... Args>
+            void create(std::size_t additional_size, Args&&... args)
+            {
+                auto mem = this->allocate_node(sizeof(element_type) + additional_size,
+                                               alignof(element_type));
+
+                element_type* ptr = nullptr;
+#if WPI_HAS_EXCEPTION_SUPPORT
+                try
+                {
+                    ptr = ::new (mem)
+                        element_type(joint(additional_size), detail::forward<Args>(args)...);
+                }
+                catch (...)
+                {
+                    this->deallocate_node(mem, sizeof(element_type) + additional_size,
+                                          alignof(element_type));
+                    throw;
+                }
+#else
+                ptr = ::new (mem)
+                    element_type(joint(additional_size), detail::forward<Args>(args)...);
+#endif
+                ptr_ = ptr;
+            }
+
+            joint_type<T>* ptr_;
+
+            friend class joint_allocator;
+        };
+
+        /// @{
+        /// \returns `!ptr`,
+        /// i.e. if `ptr` does not own anything.
+        /// \relates joint_ptr
+        template <typename T, class RawAllocator>
+        bool operator==(const joint_ptr<T, RawAllocator>& ptr, std::nullptr_t)
+        {
+            return !ptr;
+        }
+
+        template <typename T, class RawAllocator>
+        bool operator==(std::nullptr_t, const joint_ptr<T, RawAllocator>& ptr)
+        {
+            return ptr == nullptr;
+        }
+        /// @}
+
+        /// @{
+        /// \returns `ptr.get() == p`,
+        /// i.e. if `ptr` ownws the object referred to by `p`.
+        /// \relates joint_ptr
+        template <typename T, class RawAllocator>
+        bool operator==(const joint_ptr<T, RawAllocator>& ptr, T* p)
+        {
+            return ptr.get() == p;
+        }
+
+        template <typename T, class RawAllocator>
+        bool operator==(T* p, const joint_ptr<T, RawAllocator>& ptr)
+        {
+            return ptr == p;
+        }
+        /// @}
+
+        /// @{
+        /// \returns `!(ptr == nullptr)`,
+        /// i.e. if `ptr` does own something.
+        /// \relates joint_ptr
+        template <typename T, class RawAllocator>
+        bool operator!=(const joint_ptr<T, RawAllocator>& ptr, std::nullptr_t)
+        {
+            return !(ptr == nullptr);
+        }
+
+        template <typename T, class RawAllocator>
+        bool operator!=(std::nullptr_t, const joint_ptr<T, RawAllocator>& ptr)
+        {
+            return ptr != nullptr;
+        }
+        /// @}
+
+        /// @{
+        /// \returns `!(ptr == p)`,
+        /// i.e. if `ptr` does not ownw the object referred to by `p`.
+        /// \relates joint_ptr
+        template <typename T, class RawAllocator>
+        bool operator!=(const joint_ptr<T, RawAllocator>& ptr, T* p)
+        {
+            return !(ptr == p);
+        }
+
+        template <typename T, class RawAllocator>
+        bool operator!=(T* p, const joint_ptr<T, RawAllocator>& ptr)
+        {
+            return ptr != p;
+        }
+        /// @}
+
+        /// @{
+        /// \returns A new \ref joint_ptr as if created with the same arguments passed to the constructor.
+        /// \relatesalso joint_ptr
+        /// \ingroup allocator
+        template <typename T, class RawAllocator, typename... Args>
+        auto allocate_joint(RawAllocator& alloc, joint_size additional_size, Args&&... args)
+            -> joint_ptr<T, RawAllocator>
+        {
+            return joint_ptr<T, RawAllocator>(alloc, additional_size,
+                                              detail::forward<Args>(args)...);
+        }
+
+        template <typename T, class RawAllocator, typename... Args>
+        auto allocate_joint(const RawAllocator& alloc, joint_size additional_size, Args&&... args)
+            -> joint_ptr<T, RawAllocator>
+        {
+            return joint_ptr<T, RawAllocator>(alloc, additional_size,
+                                              detail::forward<Args>(args)...);
+        }
+        /// @}
+
+        /// @{
+        /// \returns A new \ref joint_ptr that points to a copy of `joint`.
+        /// It will allocate as much memory as needed and forward to the copy constructor.
+        /// \ingroup allocator
+        template <class RawAllocator, typename T>
+        auto clone_joint(RawAllocator& alloc, const joint_type<T>& joint)
+            -> joint_ptr<T, RawAllocator>
+        {
+            return joint_ptr<T, RawAllocator>(alloc,
+                                              joint_size(detail::get_stack(joint).capacity_used(
+                                                  detail::get_memory(joint))),
+                                              static_cast<const T&>(joint));
+        }
+
+        template <class RawAllocator, typename T>
+        auto clone_joint(const RawAllocator& alloc, const joint_type<T>& joint)
+            -> joint_ptr<T, RawAllocator>
+        {
+            return joint_ptr<T, RawAllocator>(alloc,
+                                              joint_size(detail::get_stack(joint).capacity_used(
+                                                  detail::get_memory(joint))),
+                                              static_cast<const T&>(joint));
+        }
+        /// @}
+
+        /// A \concept{concept_rawallocator,RawAllocator} that uses the additional joint memory for its allocation.
+        ///
+        /// It is somewhat limited and allows only allocation once.
+        /// All joint allocators for an object share the joint memory and must not be used in multiple threads.
+        /// The memory it returns is owned by a \ref joint_ptr and will be destroyed through it.
+        /// \ingroup allocator
+        class joint_allocator
+        {
+        public:
+#if defined(__GNUC__) && (!defined(_GLIBCXX_USE_CXX11_ABI) || _GLIBCXX_USE_CXX11_ABI == 0)
+            // std::string requires default constructor for the small string optimization when using gcc's old ABI
+            // so add one, but it must never be used for allocation
+            joint_allocator() noexcept : stack_(nullptr) {}
+#endif
+
+            /// \effects Creates it using the joint memory of the given object.
+            template <typename T>
+            joint_allocator(joint_type<T>& j) noexcept : stack_(&detail::get_stack(j))
+            {
+            }
+
+            joint_allocator(const joint_allocator& other) noexcept = default;
+            joint_allocator& operator=(const joint_allocator& other) noexcept = default;
+
+            /// \effects Allocates a node with given properties.
+            /// \returns A pointer to the new node.
+            /// \throws \ref out_of_fixed_memory exception if this function has been called for a second time
+            /// or the joint memory block is exhausted.
+            void* allocate_node(std::size_t size, std::size_t alignment)
+            {
+                WPI_MEMORY_ASSERT(stack_);
+                auto mem = stack_->allocate(size, alignment);
+                if (!mem)
+                    WPI_THROW(out_of_fixed_memory(info(), size));
+                return mem;
+            }
+
+            /// \effects Deallocates the node, if possible.
+            /// \note It is only possible if it was the last allocation.
+            void deallocate_node(void* ptr, std::size_t size, std::size_t) noexcept
+            {
+                WPI_MEMORY_ASSERT(stack_);
+                auto end = static_cast<char*>(ptr) + size;
+                if (end == stack_->top())
+                    stack_->unwind(ptr);
+            }
+
+        private:
+            allocator_info info() const noexcept
+            {
+                return allocator_info(WPI_MEMORY_LOG_PREFIX "::joint_allocator", this);
+            }
+
+            detail::joint_stack* stack_;
+
+            friend bool operator==(const joint_allocator& lhs, const joint_allocator& rhs) noexcept;
+        };
+
+        /// @{
+        /// \returns Whether `lhs` and `rhs` use the same joint memory for the allocation.
+        /// \relates joint_allocator
+        inline bool operator==(const joint_allocator& lhs, const joint_allocator& rhs) noexcept
+        {
+            return lhs.stack_ == rhs.stack_;
+        }
+
+        inline bool operator!=(const joint_allocator& lhs, const joint_allocator& rhs) noexcept
+        {
+            return !(lhs == rhs);
+        }
+        /// @}
+
+        /// Specialization of \ref is_shared_allocator to mark \ref joint_allocator as shared.
+        /// This allows using it as \ref allocator_reference directly.
+        /// \ingroup allocator
+        template <>
+        struct is_shared_allocator<joint_allocator> : std::true_type
+        {
+        };
+
+        /// Specialization of \ref is_thread_safe_allocator to mark \ref joint_allocator as thread safe.
+        /// This is an optimization to get rid of the mutex in \ref allocator_storage,
+        /// as joint allocator must not be shared between threads.
+        /// \note The allocator is *not* thread safe, it just must not be shared.
+        template <>
+        struct is_thread_safe_allocator<joint_allocator> : std::true_type
+        {
+        };
+
+#if !defined(DOXYGEN)
+        template <class RawAllocator>
+        struct propagation_traits;
+#endif
+
+        /// Specialization of the \ref propagation_traits for the \ref joint_allocator.
+        /// A joint allocator does not propagate on assignment
+        /// and it is not allowed to use the regular copy/move constructor of allocator aware containers,
+        /// instead it needs the copy/move constructor with allocator.
+        /// \note This is required because the container constructor will end up copying/moving the allocator.
+        /// But this is not allowed as you need the allocator with the correct joined memory.
+        /// Copying can be customized (i.e. forbidden), but sadly not move, so keep that in mind.
+        /// \ingroup allocator
+        template <>
+        struct propagation_traits<joint_allocator>
+        {
+            using propagate_on_container_swap            = std::false_type;
+            using propagate_on_container_move_assignment = std::false_type;
+            using propagate_on_container_copy_assignment = std::false_type;
+
+            template <class AllocReference>
+            static AllocReference select_on_container_copy_construction(const AllocReference&)
+            {
+                static_assert(always_false<AllocReference>::value,
+                              "you must not use the regular copy constructor");
+            }
+
+        private:
+            template <typename T>
+            struct always_false : std::false_type
+            {
+            };
+        };
+
+        /// A zero overhead dynamic array using joint memory.
+        ///
+        /// If you use, e.g. `std::vector` with \ref joint_allocator,
+        /// this has a slight additional overhead.
+        /// This type is joint memory aware and has no overhead.
+        ///
+        /// It has a dynamic, but fixed size,
+        /// it cannot grow after it has been created.
+        /// \ingroup allocator
+        template <typename T>
+        class joint_array
+        {
+        public:
+            using value_type     = T;
+            using iterator       = value_type*;
+            using const_iterator = const value_type*;
+
+            //=== constructors ===//
+            /// \effects Creates with `size` default-constructed objects using the specified joint memory.
+            /// \throws \ref out_of_fixed_memory if `size` is too big
+            /// and anything thrown by `T`s constructor.
+            /// If an allocation is thrown, the memory will be released directly.
+            template <typename JointType>
+            joint_array(std::size_t size, joint_type<JointType>& j)
+            : joint_array(detail::get_stack(j), size)
+            {
+            }
+
+            /// \effects Creates with `size` copies of `val`  using the specified joint memory.
+            /// \throws \ref out_of_fixed_memory if `size` is too big
+            /// and anything thrown by `T`s constructor.
+            /// If an allocation is thrown, the memory will be released directly.
+            template <typename JointType>
+            joint_array(std::size_t size, const value_type& val, joint_type<JointType>& j)
+            : joint_array(detail::get_stack(j), size, val)
+            {
+            }
+
+            /// \effects Creates with the copies of the objects in the initializer list using the specified joint memory.
+            /// \throws \ref out_of_fixed_memory if the size is too big
+            /// and anything thrown by `T`s constructor.
+            /// If an allocation is thrown, the memory will be released directly.
+            template <typename JointType>
+            joint_array(std::initializer_list<value_type> ilist, joint_type<JointType>& j)
+            : joint_array(detail::get_stack(j), ilist)
+            {
+            }
+
+            /// \effects Creates it by forwarding each element of the range to `T`s constructor  using the specified joint memory.
+            /// \throws \ref out_of_fixed_memory if the size is too big
+            /// and anything thrown by `T`s constructor.
+            /// If an allocation is thrown, the memory will be released directly.
+            template <typename InIter, typename JointType,
+                      typename = decltype(*std::declval<InIter&>()++)>
+            joint_array(InIter begin, InIter end, joint_type<JointType>& j)
+            : joint_array(detail::get_stack(j), begin, end)
+            {
+            }
+
+            joint_array(const joint_array&) = delete;
+
+            /// \effects Copy constructs each element from `other` into the storage of the specified joint memory.
+            /// \throws \ref out_of_fixed_memory if the size is too big
+            /// and anything thrown by `T`s constructor.
+            /// If an allocation is thrown, the memory will be released directly.
+            template <typename JointType>
+            joint_array(const joint_array& other, joint_type<JointType>& j)
+            : joint_array(detail::get_stack(j), other)
+            {
+            }
+
+            joint_array(joint_array&&) = delete;
+
+            /// \effects Move constructs each element from `other` into the storage of the specified joint memory.
+            /// \throws \ref out_of_fixed_memory if the size is too big
+            /// and anything thrown by `T`s constructor.
+            /// If an allocation is thrown, the memory will be released directly.
+            template <typename JointType>
+            joint_array(joint_array&& other, joint_type<JointType>& j)
+            : joint_array(detail::get_stack(j), detail::move(other))
+            {
+            }
+
+            /// \effects Destroys all objects,
+            /// but does not release the storage.
+            ~joint_array() noexcept
+            {
+                for (std::size_t i = 0u; i != size_; ++i)
+                    ptr_[i].~T();
+            }
+
+            joint_array& operator=(const joint_array&) = delete;
+            joint_array& operator=(joint_array&&) = delete;
+
+            //=== accessors ===//
+            /// @{
+            /// \returns A reference to the `i`th object.
+            /// \requires `i < size()`.
+            value_type& operator[](std::size_t i) noexcept
+            {
+                WPI_MEMORY_ASSERT(i < size_);
+                return ptr_[i];
+            }
+
+            const value_type& operator[](std::size_t i) const noexcept
+            {
+                WPI_MEMORY_ASSERT(i < size_);
+                return ptr_[i];
+            }
+            /// @}
+
+            /// @{
+            /// \returns A pointer to the first object.
+            /// It points to contiguous memory and can be used to access the objects directly.
+            value_type* data() noexcept
+            {
+                return ptr_;
+            }
+
+            const value_type* data() const noexcept
+            {
+                return ptr_;
+            }
+            /// @}
+
+            /// @{
+            /// \returns A random access iterator to the first element.
+            iterator begin() noexcept
+            {
+                return ptr_;
+            }
+
+            const_iterator begin() const noexcept
+            {
+                return ptr_;
+            }
+            /// @}
+
+            /// @{
+            /// \returns A random access iterator one past the last element.
+            iterator end() noexcept
+            {
+                return ptr_ + size_;
+            }
+
+            const_iterator end() const noexcept
+            {
+                return ptr_ + size_;
+            }
+            /// @}
+
+            /// \returns The number of elements in the array.
+            std::size_t size() const noexcept
+            {
+                return size_;
+            }
+
+            /// \returns `true` if the array is empty, `false` otherwise.
+            bool empty() const noexcept
+            {
+                return size_ == 0u;
+            }
+
+        private:
+            // allocate only
+            struct allocate_only
+            {
+            };
+            joint_array(allocate_only, detail::joint_stack& stack, std::size_t size)
+            : ptr_(nullptr), size_(0u)
+            {
+                ptr_ = static_cast<T*>(stack.allocate(size * sizeof(T), alignof(T)));
+                if (!ptr_)
+                    WPI_THROW(out_of_fixed_memory(info(), size * sizeof(T)));
+            }
+
+            class builder
+            {
+            public:
+                builder(detail::joint_stack& stack, T* ptr) noexcept
+                : stack_(&stack), objects_(ptr), size_(0u)
+                {
+                }
+
+                ~builder() noexcept
+                {
+                    for (std::size_t i = 0u; i != size_; ++i)
+                        objects_[i].~T();
+
+                    if (size_)
+                        stack_->unwind(objects_);
+                }
+
+                builder(builder&&) = delete;
+                builder& operator=(builder&&) = delete;
+
+                template <typename... Args>
+                T* create(Args&&... args)
+                {
+                    auto ptr = ::new (static_cast<void*>(&objects_[size_]))
+                        T(detail::forward<Args>(args)...);
+                    ++size_;
+                    return ptr;
+                }
+
+                std::size_t size() const noexcept
+                {
+                    return size_;
+                }
+
+                std::size_t release() noexcept
+                {
+                    auto res = size_;
+                    size_    = 0u;
+                    return res;
+                }
+
+            private:
+                detail::joint_stack* stack_;
+                T*                   objects_;
+                std::size_t          size_;
+            };
+
+            joint_array(detail::joint_stack& stack, std::size_t size)
+            : joint_array(allocate_only{}, stack, size)
+            {
+                builder b(stack, ptr_);
+                for (auto i = 0u; i != size; ++i)
+                    b.create();
+                size_ = b.release();
+            }
+
+            joint_array(detail::joint_stack& stack, std::size_t size, const value_type& value)
+            : joint_array(allocate_only{}, stack, size)
+            {
+                builder b(stack, ptr_);
+                for (auto i = 0u; i != size; ++i)
+                    b.create(value);
+                size_ = b.release();
+            }
+
+            joint_array(detail::joint_stack& stack, std::initializer_list<value_type> ilist)
+            : joint_array(allocate_only{}, stack, ilist.size())
+            {
+                builder b(stack, ptr_);
+                for (auto& elem : ilist)
+                    b.create(elem);
+                size_ = b.release();
+            }
+
+            joint_array(detail::joint_stack& stack, const joint_array& other)
+            : joint_array(allocate_only{}, stack, other.size())
+            {
+                builder b(stack, ptr_);
+                for (auto& elem : other)
+                    b.create(elem);
+                size_ = b.release();
+            }
+
+            joint_array(detail::joint_stack& stack, joint_array&& other)
+            : joint_array(allocate_only{}, stack, other.size())
+            {
+                builder b(stack, ptr_);
+                for (auto& elem : other)
+                    b.create(detail::move(elem));
+                size_ = b.release();
+            }
+
+            template <typename InIter>
+            joint_array(detail::joint_stack& stack, InIter begin, InIter end)
+            : ptr_(nullptr), size_(0u)
+            {
+                if (begin == end)
+                    return;
+
+                ptr_ = static_cast<T*>(stack.allocate(sizeof(T), alignof(T)));
+                if (!ptr_)
+                    WPI_THROW(out_of_fixed_memory(info(), sizeof(T)));
+
+                builder b(stack, ptr_);
+                b.create(*begin++);
+
+                for (auto last = ptr_; begin != end; ++begin)
+                {
+                    // just bump stack to get more memory
+                    if (!stack.bump(sizeof(T)))
+                        WPI_THROW(out_of_fixed_memory(info(), b.size() * sizeof(T)));
+
+                    auto cur = b.create(*begin);
+                    WPI_MEMORY_ASSERT(last + 1 == cur);
+                    last = cur;
+                }
+
+                size_ = b.release();
+            }
+
+            allocator_info info() const noexcept
+            {
+                return {WPI_MEMORY_LOG_PREFIX "::joint_array", this};
+            }
+
+            value_type* ptr_;
+            std::size_t size_;
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_JOINT_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/malloc_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/malloc_allocator.hpp
new file mode 100644
index 0000000..3be9820
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/malloc_allocator.hpp
@@ -0,0 +1,71 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_MALLOC_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_MALLOC_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::malloc_allocator.
+/// \note Only available on a hosted implementation.
+
+#include "config.hpp"
+#if !WPI_HOSTED_IMPLEMENTATION
+#error "This header is only available for a hosted implementation."
+#endif
+
+#include <cstdlib>
+#include <memory>
+
+#include "detail/lowlevel_allocator.hpp"
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+#include "allocator_traits.hpp"
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        struct allocator_info;
+
+        namespace detail
+        {
+            struct malloc_allocator_impl
+            {
+                static allocator_info info() noexcept;
+
+                static void* allocate(std::size_t size, std::size_t) noexcept
+                {
+                    return std::malloc(size);
+                }
+
+                static void deallocate(void* ptr, std::size_t, std::size_t) noexcept
+                {
+                    std::free(ptr);
+                }
+
+                static std::size_t max_node_size() noexcept
+                {
+                    return std::allocator_traits<std::allocator<char>>::max_size({});
+                }
+            };
+
+            WPI_MEMORY_LL_ALLOCATOR_LEAK_CHECKER(malloc_allocator_impl,
+                                                       malloc_alloator_leak_checker)
+        } // namespace detail
+
+        /// A stateless \concept{concept_rawallocator,RawAllocator} that allocates memory using <tt>std::malloc()</tt>.
+        /// It throws \ref out_of_memory when the allocation fails.
+        /// \ingroup allocator
+        using malloc_allocator =
+            WPI_IMPL_DEFINED(detail::lowlevel_allocator<detail::malloc_allocator_impl>);
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class detail::lowlevel_allocator<detail::malloc_allocator_impl>;
+        extern template class allocator_traits<malloc_allocator>;
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif //WPI_MEMORY_MALLOC_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_arena.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_arena.hpp
new file mode 100644
index 0000000..a634993
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_arena.hpp
@@ -0,0 +1,693 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_MEMORY_ARENA_HPP_INCLUDED
+#define WPI_MEMORY_MEMORY_ARENA_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::memory_arena and related functionality regarding \concept{concept_blockallocator,BlockAllocators}.
+
+#include <type_traits>
+
+#include "detail/debug_helpers.hpp"
+#include "detail/assert.hpp"
+#include "detail/utility.hpp"
+#include "allocator_traits.hpp"
+#include "config.hpp"
+#include "default_allocator.hpp"
+#include "error.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// A memory block.
+        /// It is defined by its starting address and size.
+        /// \ingroup core
+        struct memory_block
+        {
+            void*       memory; ///< The address of the memory block (might be \c nullptr).
+            std::size_t size;   ///< The size of the memory block (might be \c 0).
+
+            /// \effects Creates an invalid memory block with starting address \c nullptr and size \c 0.
+            memory_block() noexcept : memory_block(nullptr, std::size_t(0)) {}
+
+            /// \effects Creates a memory block from a given starting address and size.
+            memory_block(void* mem, std::size_t s) noexcept : memory(mem), size(s) {}
+
+            /// \effects Creates a memory block from a [begin,end) range.
+            memory_block(void* begin, void* end) noexcept
+            : memory_block(begin, static_cast<std::size_t>(static_cast<char*>(end)
+                                                           - static_cast<char*>(begin)))
+            {
+            }
+
+            /// \returns Whether or not a pointer is inside the memory.
+            bool contains(const void* address) const noexcept
+            {
+                auto mem  = static_cast<const char*>(memory);
+                auto addr = static_cast<const char*>(address);
+                return addr >= mem && addr < mem + size;
+            }
+        };
+
+        namespace detail
+        {
+            template <class BlockAllocator>
+            std::true_type is_block_allocator_impl(
+                int,
+                WPI_SFINAE(std::declval<memory_block&>() =
+                                     std::declval<BlockAllocator&>().allocate_block()),
+                WPI_SFINAE(std::declval<std::size_t&>() =
+                                     std::declval<BlockAllocator&>().next_block_size()),
+                WPI_SFINAE(std::declval<BlockAllocator>().deallocate_block(memory_block{})));
+
+            template <typename T>
+            std::false_type is_block_allocator_impl(short);
+        } // namespace detail
+
+        /// Traits that check whether a type models concept \concept{concept_blockallocator,BlockAllocator}.
+        /// \ingroup core
+        template <typename T>
+        struct is_block_allocator : decltype(detail::is_block_allocator_impl<T>(0))
+        {
+        };
+
+#if !defined(DOXYGEN)
+        template <class BlockAllocator, bool Cached = true>
+        class memory_arena;
+#endif
+
+        /// @{
+        /// Controls the caching of \ref memory_arena.
+        /// By default, deallocated blocks are put onto a cache, so they can be reused later;
+        /// this tag value enable/disable it..<br>
+        /// This can be useful, e.g. if there will never be blocks available for deallocation.
+        /// The (tiny) overhead for the cache can then be disabled.
+        /// An example is \ref memory_pool.
+        /// \ingroup core
+        constexpr bool cached_arena   = true;
+        constexpr bool uncached_arena = false;
+        /// @}
+
+        namespace detail
+        {
+            // stores memory block in an intrusive linked list and allows LIFO access
+            class memory_block_stack
+            {
+            public:
+                memory_block_stack() noexcept : head_(nullptr) {}
+
+                ~memory_block_stack() noexcept {}
+
+                memory_block_stack(memory_block_stack&& other) noexcept : head_(other.head_)
+                {
+                    other.head_ = nullptr;
+                }
+
+                memory_block_stack& operator=(memory_block_stack&& other) noexcept
+                {
+                    memory_block_stack tmp(detail::move(other));
+                    swap(*this, tmp);
+                    return *this;
+                }
+
+                friend void swap(memory_block_stack& a, memory_block_stack& b) noexcept
+                {
+                    detail::adl_swap(a.head_, b.head_);
+                }
+
+                // the raw allocated block returned from an allocator
+                using allocated_mb = memory_block;
+
+                // the inserted block slightly smaller to allow for the fixup value
+                using inserted_mb = memory_block;
+
+                // how much an inserted block is smaller
+                static constexpr std::size_t implementation_offset() noexcept
+                {
+                    // node size rounded up to the next multiple of max_alignment.
+                    return (sizeof(node) / max_alignment + (sizeof(node) % max_alignment != 0))
+                           * max_alignment;
+                }
+
+                // pushes a memory block
+                void push(allocated_mb block) noexcept;
+
+                // pops a memory block and returns the original block
+                allocated_mb pop() noexcept;
+
+                // steals the top block from another stack
+                void steal_top(memory_block_stack& other) noexcept;
+
+                // returns the last pushed() inserted memory block
+                inserted_mb top() const noexcept
+                {
+                    WPI_MEMORY_ASSERT(head_);
+                    auto mem = static_cast<void*>(head_);
+                    return {static_cast<char*>(mem) + implementation_offset(), head_->usable_size};
+                }
+
+                bool empty() const noexcept
+                {
+                    return head_ == nullptr;
+                }
+
+                bool owns(const void* ptr) const noexcept;
+
+                // O(n) size
+                std::size_t size() const noexcept;
+
+            private:
+                struct node
+                {
+                    node*       prev;
+                    std::size_t usable_size;
+
+                    node(node* p, std::size_t size) noexcept : prev(p), usable_size(size) {}
+                };
+
+                node* head_;
+            };
+
+            template <bool Cached>
+            class memory_arena_cache;
+
+            template <>
+            class memory_arena_cache<cached_arena>
+            {
+            protected:
+                bool cache_empty() const noexcept
+                {
+                    return cached_.empty();
+                }
+
+                std::size_t cache_size() const noexcept
+                {
+                    return cached_.size();
+                }
+
+                std::size_t cached_block_size() const noexcept
+                {
+                    return cached_.top().size;
+                }
+
+                bool take_from_cache(detail::memory_block_stack& used) noexcept
+                {
+                    if (cached_.empty())
+                        return false;
+                    used.steal_top(cached_);
+                    return true;
+                }
+
+                template <class BlockAllocator>
+                void do_deallocate_block(BlockAllocator&, detail::memory_block_stack& used) noexcept
+                {
+                    cached_.steal_top(used);
+                }
+
+                template <class BlockAllocator>
+                void do_shrink_to_fit(BlockAllocator& alloc) noexcept
+                {
+                    detail::memory_block_stack to_dealloc;
+                    // pop from cache and push to temporary stack
+                    // this revers order
+                    while (!cached_.empty())
+                        to_dealloc.steal_top(cached_);
+                    // now dealloc everything
+                    while (!to_dealloc.empty())
+                        alloc.deallocate_block(to_dealloc.pop());
+                }
+
+            private:
+                detail::memory_block_stack cached_;
+            };
+
+            template <>
+            class memory_arena_cache<uncached_arena>
+            {
+            protected:
+                bool cache_empty() const noexcept
+                {
+                    return true;
+                }
+
+                std::size_t cache_size() const noexcept
+                {
+                    return 0u;
+                }
+
+                std::size_t cached_block_size() const noexcept
+                {
+                    return 0u;
+                }
+
+                bool take_from_cache(detail::memory_block_stack&) noexcept
+                {
+                    return false;
+                }
+
+                template <class BlockAllocator>
+                void do_deallocate_block(BlockAllocator&             alloc,
+                                         detail::memory_block_stack& used) noexcept
+                {
+                    alloc.deallocate_block(used.pop());
+                }
+
+                template <class BlockAllocator>
+                void do_shrink_to_fit(BlockAllocator&) noexcept
+                {
+                }
+            };
+        } // namespace detail
+
+        /// A memory arena that manages huge memory blocks for a higher-level allocator.
+        /// Some allocators like \ref memory_stack work on huge memory blocks,
+        /// this class manages them fro those allocators.
+        /// It uses a \concept{concept_blockallocator,BlockAllocator} for the allocation of those blocks.
+        /// The memory blocks in use are put onto a stack like structure, deallocation will pop from the top,
+        /// so it is only possible to deallocate the last allocated block of the arena.
+        /// By default, blocks are not really deallocated but stored in a cache.
+        /// This can be disabled with the second template parameter,
+        /// passing it \ref uncached_arena (or \c false) disables it,
+        /// \ref cached_arena (or \c true) enables it explicitly.
+        /// \ingroup core
+        template <class BlockAllocator, bool Cached /* = true */>
+        class memory_arena : WPI_EBO(BlockAllocator),
+                             WPI_EBO(detail::memory_arena_cache<Cached>)
+        {
+            static_assert(is_block_allocator<BlockAllocator>::value,
+                          "BlockAllocator is not a BlockAllocator!");
+            using cache = detail::memory_arena_cache<Cached>;
+
+        public:
+            using allocator_type = BlockAllocator;
+            using is_cached      = std::integral_constant<bool, Cached>;
+
+            /// \returns The minimum block size required for an arena containing the given amount of memory.
+            /// If an arena is created with the result of `min_block_size(n)`, the resulting capacity will be exactly `n`.
+            /// \requires `byte_size` must be a positive number.
+            static constexpr std::size_t min_block_size(std::size_t byte_size) noexcept
+            {
+                return detail::memory_block_stack::implementation_offset() + byte_size;
+            }
+
+            /// \effects Creates it by giving it the size and other arguments for the \concept{concept_blockallocator,BlockAllocator}.
+            /// It forwards these arguments to its constructor.
+            /// \requires \c block_size must be greater than \c min_block_size(0) and other requirements depending on the \concept{concept_blockallocator,BlockAllocator}.
+            /// \throws Anything thrown by the constructor of the \c BlockAllocator.
+            template <typename... Args>
+            explicit memory_arena(std::size_t block_size, Args&&... args)
+            : allocator_type(block_size, detail::forward<Args>(args)...)
+            {
+                WPI_MEMORY_ASSERT(block_size > min_block_size(0));
+            }
+
+            /// \effects Deallocates all memory blocks that where requested back to the \concept{concept_blockallocator,BlockAllocator}.
+            ~memory_arena() noexcept
+            {
+                // clear cache
+                shrink_to_fit();
+                // now deallocate everything
+                while (!used_.empty())
+                    allocator_type::deallocate_block(used_.pop());
+            }
+
+            /// @{
+            /// \effects Moves the arena.
+            /// The new arena takes ownership over all the memory blocks from the other arena object,
+            /// which is empty after that.
+            /// This does not invalidate any memory blocks.
+            memory_arena(memory_arena&& other) noexcept
+            : allocator_type(detail::move(other)),
+              cache(detail::move(other)),
+              used_(detail::move(other.used_))
+            {
+            }
+
+            memory_arena& operator=(memory_arena&& other) noexcept
+            {
+                memory_arena tmp(detail::move(other));
+                swap(*this, tmp);
+                return *this;
+            }
+            /// @}
+
+            /// \effects Swaps to memory arena objects.
+            /// This does not invalidate any memory blocks.
+            friend void swap(memory_arena& a, memory_arena& b) noexcept
+            {
+                detail::adl_swap(static_cast<allocator_type&>(a), static_cast<allocator_type&>(b));
+                detail::adl_swap(static_cast<cache&>(a), static_cast<cache&>(b));
+                detail::adl_swap(a.used_, b.used_);
+            }
+
+            /// \effects Allocates a new memory block.
+            /// It first uses a cache of previously deallocated blocks, if caching is enabled,
+            /// if it is empty, allocates a new one.
+            /// \returns The new \ref memory_block.
+            /// \throws Anything thrown by the \concept{concept_blockallocator,BlockAllocator} allocation function.
+            memory_block allocate_block()
+            {
+                if (!this->take_from_cache(used_))
+                    used_.push(allocator_type::allocate_block());
+
+                auto block = used_.top();
+                detail::debug_fill_internal(block.memory, block.size, false);
+                return block;
+            }
+
+            /// \returns The current memory block.
+            /// This is the memory block that will be deallocated by the next call to \ref deallocate_block().
+            memory_block current_block() const noexcept
+            {
+                return used_.top();
+            }
+
+            /// \effects Deallocates the current memory block.
+            /// The current memory block is the block on top of the stack of blocks.
+            /// If caching is enabled, it does not really deallocate it but puts it onto a cache for later use,
+            /// use \ref shrink_to_fit() to purge that cache.
+            void deallocate_block() noexcept
+            {
+                auto block = used_.top();
+                detail::debug_fill_internal(block.memory, block.size, true);
+                this->do_deallocate_block(get_allocator(), used_);
+            }
+
+            /// \returns If `ptr` is in memory owned by the arena.
+            bool owns(const void* ptr) const noexcept
+            {
+                return used_.owns(ptr);
+            }
+
+            /// \effects Purges the cache of unused memory blocks by returning them.
+            /// The memory blocks will be deallocated in reversed order of allocation.
+            /// Does nothing if caching is disabled.
+            void shrink_to_fit() noexcept
+            {
+                this->do_shrink_to_fit(get_allocator());
+            }
+
+            /// \returns The capacity of the arena, i.e. how many blocks are used and cached.
+            std::size_t capacity() const noexcept
+            {
+                return size() + cache_size();
+            }
+
+            /// \returns The size of the cache, i.e. how many blocks can be allocated without allocation.
+            std::size_t cache_size() const noexcept
+            {
+                return cache::cache_size();
+            }
+
+            /// \returns The size of the arena, i.e. how many blocks are in use.
+            /// It is always smaller or equal to the \ref capacity().
+            std::size_t size() const noexcept
+            {
+                return used_.size();
+            }
+
+            /// \returns The size of the next memory block,
+            /// i.e. of the next call to \ref allocate_block().
+            /// If there are blocks in the cache, returns size of the next one.
+            /// Otherwise forwards to the \concept{concept_blockallocator,BlockAllocator} and subtracts an implementation offset.
+            std::size_t next_block_size() const noexcept
+            {
+                return this->cache_empty() ?
+                           allocator_type::next_block_size()
+                               - detail::memory_block_stack::implementation_offset() :
+                           this->cached_block_size();
+            }
+
+            /// \returns A reference of the \concept{concept_blockallocator,BlockAllocator} object.
+            /// \requires It is undefined behavior to move this allocator out into another object.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+        private:
+            detail::memory_block_stack used_;
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class memory_arena<static_block_allocator, true>;
+        extern template class memory_arena<static_block_allocator, false>;
+        extern template class memory_arena<virtual_block_allocator, true>;
+        extern template class memory_arena<virtual_block_allocator, false>;
+#endif
+
+        /// A \concept{concept_blockallocator,BlockAllocator} that uses a given \concept{concept_rawallocator,RawAllocator} for allocating the blocks.
+        /// It calls the \c allocate_array() function with a node of size \c 1 and maximum alignment on the used allocator for the block allocation.
+        /// The size of the next memory block will grow by a given factor after each allocation,
+        /// allowing an amortized constant allocation time in the higher level allocator.
+        /// The factor can be given as rational in the template parameter, default is \c 2.
+        /// \ingroup adapter
+        template <class RawAllocator = default_allocator, unsigned Num = 2, unsigned Den = 1>
+        class growing_block_allocator
+        : WPI_EBO(allocator_traits<RawAllocator>::allocator_type)
+        {
+            static_assert(float(Num) / Den >= 1.0, "invalid growth factor");
+
+            using traits = allocator_traits<RawAllocator>;
+
+        public:
+            using allocator_type = typename traits::allocator_type;
+
+            /// \effects Creates it by giving it the initial block size, the allocator object and the growth factor.
+            /// By default, it uses a default-constructed allocator object and a growth factor of \c 2.
+            /// \requires \c block_size must be greater than 0.
+            explicit growing_block_allocator(std::size_t    block_size,
+                                             allocator_type alloc = allocator_type()) noexcept
+            : allocator_type(detail::move(alloc)), block_size_(block_size)
+            {
+            }
+
+            /// \effects Allocates a new memory block and increases the block size for the next allocation.
+            /// \returns The new \ref memory_block.
+            /// \throws Anything thrown by the \c allocate_array() function of the \concept{concept_rawallocator,RawAllocator}.
+            memory_block allocate_block()
+            {
+                auto memory =
+                    traits::allocate_array(get_allocator(), block_size_, 1, detail::max_alignment);
+                memory_block block(memory, block_size_);
+                block_size_ = grow_block_size(block_size_);
+                return block;
+            }
+
+            /// \effects Deallocates a previously allocated memory block.
+            /// This does not decrease the block size.
+            /// \requires \c block must be previously returned by a call to \ref allocate_block().
+            void deallocate_block(memory_block block) noexcept
+            {
+                traits::deallocate_array(get_allocator(), block.memory, block.size, 1,
+                                         detail::max_alignment);
+            }
+
+            /// \returns The size of the memory block returned by the next call to \ref allocate_block().
+            std::size_t next_block_size() const noexcept
+            {
+                return block_size_;
+            }
+
+            /// \returns A reference to the used \concept{concept_rawallocator,RawAllocator} object.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+            /// \returns The growth factor.
+            static float growth_factor() noexcept
+            {
+                static constexpr auto factor = float(Num) / Den;
+                return factor;
+            }
+
+            static std::size_t grow_block_size(std::size_t block_size) noexcept
+            {
+                return block_size * Num / Den;
+            }
+
+        private:
+            std::size_t block_size_;
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class growing_block_allocator<>;
+        extern template class memory_arena<growing_block_allocator<>, true>;
+        extern template class memory_arena<growing_block_allocator<>, false>;
+#endif
+
+        /// A \concept{concept_blockallocator,BlockAllocator} that allows only one block allocation.
+        /// It can be used to prevent higher-level allocators from expanding.
+        /// The one block allocation is performed through the \c allocate_array() function of the given \concept{concept_rawallocator,RawAllocator}.
+        /// \ingroup adapter
+        template <class RawAllocator = default_allocator>
+        class fixed_block_allocator : WPI_EBO(allocator_traits<RawAllocator>::allocator_type)
+        {
+            using traits = allocator_traits<RawAllocator>;
+
+        public:
+            using allocator_type = typename traits::allocator_type;
+
+            /// \effects Creates it by passing it the size of the block and the allocator object.
+            /// \requires \c block_size must be greater than 0,
+            explicit fixed_block_allocator(std::size_t    block_size,
+                                           allocator_type alloc = allocator_type()) noexcept
+            : allocator_type(detail::move(alloc)), block_size_(block_size)
+            {
+            }
+
+            /// \effects Allocates a new memory block or throws an exception if there was already one allocation.
+            /// \returns The new \ref memory_block.
+            /// \throws Anything thrown by the \c allocate_array() function of the \concept{concept_rawallocator,RawAllocator} or \ref out_of_memory if this is not the first call.
+            memory_block allocate_block()
+            {
+                if (block_size_)
+                {
+                    auto         mem = traits::allocate_array(get_allocator(), block_size_, 1,
+                                                      detail::max_alignment);
+                    memory_block block(mem, block_size_);
+                    block_size_ = 0u;
+                    return block;
+                }
+                WPI_THROW(out_of_fixed_memory(info(), block_size_));
+            }
+
+            /// \effects Deallocates the previously allocated memory block.
+            /// It also resets and allows a new call again.
+            void deallocate_block(memory_block block) noexcept
+            {
+                detail::debug_check_pointer([&] { return block_size_ == 0u; }, info(),
+                                            block.memory);
+                traits::deallocate_array(get_allocator(), block.memory, block.size, 1,
+                                         detail::max_alignment);
+                block_size_ = block.size;
+            }
+
+            /// \returns The size of the next block which is either the initial size or \c 0.
+            std::size_t next_block_size() const noexcept
+            {
+                return block_size_;
+            }
+
+            /// \returns A reference to the used \concept{concept_rawallocator,RawAllocator} object.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+        private:
+            allocator_info info() noexcept
+            {
+                return {WPI_MEMORY_LOG_PREFIX "::fixed_block_allocator", this};
+            }
+
+            std::size_t block_size_;
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class fixed_block_allocator<>;
+        extern template class memory_arena<fixed_block_allocator<>, true>;
+        extern template class memory_arena<fixed_block_allocator<>, false>;
+#endif
+
+        namespace detail
+        {
+            template <class RawAlloc>
+            using default_block_wrapper = growing_block_allocator<RawAlloc>;
+
+            template <template <class...> class Wrapper, class BlockAllocator, typename... Args>
+            BlockAllocator make_block_allocator(std::true_type, std::size_t block_size,
+                                                Args&&... args)
+            {
+                return BlockAllocator(block_size, detail::forward<Args>(args)...);
+            }
+
+            template <template <class...> class Wrapper, class RawAlloc>
+            auto make_block_allocator(std::false_type, std::size_t block_size,
+                                      RawAlloc alloc = RawAlloc()) -> Wrapper<RawAlloc>
+            {
+                return Wrapper<RawAlloc>(block_size, detail::move(alloc));
+            }
+        } // namespace detail
+
+        /// Takes either a \concept{concept_blockallocator,BlockAllocator} or a \concept{concept_rawallocator,RawAllocator}.
+        /// In the first case simply aliases the type unchanged, in the second to \ref growing_block_allocator (or the template in `BlockAllocator`) with the \concept{concept_rawallocator,RawAllocator}.
+        /// Using this allows passing normal \concept{concept_rawallocator,RawAllocators} as \concept{concept_blockallocator,BlockAllocators}.
+        /// \ingroup core
+        template <class BlockOrRawAllocator,
+                  template <typename...> class BlockAllocator = detail::default_block_wrapper>
+        using make_block_allocator_t = WPI_IMPL_DEFINED(
+            typename std::conditional<is_block_allocator<BlockOrRawAllocator>::value,
+                                      BlockOrRawAllocator,
+                                      BlockAllocator<BlockOrRawAllocator>>::type);
+
+        /// @{
+        /// Helper function make a \concept{concept_blockallocator,BlockAllocator}.
+        /// \returns A \concept{concept_blockallocator,BlockAllocator} of the given type created with the given arguments.
+        /// \requires Same requirements as the constructor.
+        /// \ingroup core
+        template <class BlockOrRawAllocator, typename... Args>
+        make_block_allocator_t<BlockOrRawAllocator> make_block_allocator(std::size_t block_size,
+                                                                         Args&&... args)
+        {
+            return detail::make_block_allocator<
+                detail::default_block_wrapper,
+                BlockOrRawAllocator>(is_block_allocator<BlockOrRawAllocator>{}, block_size,
+                                     detail::forward<Args>(args)...);
+        }
+
+        template <template <class...> class BlockAllocator, class BlockOrRawAllocator,
+                  typename... Args>
+        make_block_allocator_t<BlockOrRawAllocator, BlockAllocator> make_block_allocator(
+            std::size_t block_size, Args&&... args)
+        {
+            return detail::make_block_allocator<
+                BlockAllocator, BlockOrRawAllocator>(is_block_allocator<BlockOrRawAllocator>{},
+                                                     block_size, detail::forward<Args>(args)...);
+        }
+        /// @}
+
+        namespace literals
+        {
+            /// Syntax sugar to express sizes with unit prefixes.
+            /// \returns The number of bytes `value` is in the given unit.
+            /// \ingroup core
+            /// @{
+            constexpr std::size_t operator"" _KiB(unsigned long long value) noexcept
+            {
+                return std::size_t(value * 1024);
+            }
+
+            constexpr std::size_t operator"" _KB(unsigned long long value) noexcept
+            {
+                return std::size_t(value * 1000);
+            }
+
+            constexpr std::size_t operator"" _MiB(unsigned long long value) noexcept
+            {
+                return std::size_t(value * 1024 * 1024);
+            }
+
+            constexpr std::size_t operator"" _MB(unsigned long long value) noexcept
+            {
+                return std::size_t(value * 1000 * 1000);
+            }
+
+            constexpr std::size_t operator"" _GiB(unsigned long long value) noexcept
+            {
+                return std::size_t(value * 1024 * 1024 * 1024);
+            }
+
+            constexpr std::size_t operator"" _GB(unsigned long long value) noexcept
+            {
+                return std::size_t(value * 1000 * 1000 * 1000);
+            }
+        } // namespace literals
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_MEMORY_ARENA_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool.hpp
new file mode 100644
index 0000000..09c2b66
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool.hpp
@@ -0,0 +1,433 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_MEMORY_POOL_HPP_INCLUDED
+#define WPI_MEMORY_MEMORY_POOL_HPP_INCLUDED
+
+// Inform that wpi::memory::memory_pool::min_block_size API is available
+#define WPI_MEMORY_MEMORY_POOL_HAS_MIN_BLOCK_SIZE
+
+/// \file
+/// Class \ref wpi::memory::memory_pool and its \ref wpi::memory::allocator_traits specialization.
+
+#include <type_traits>
+
+#include "detail/align.hpp"
+#include "detail/debug_helpers.hpp"
+#include "detail/assert.hpp"
+#include "config.hpp"
+#include "error.hpp"
+#include "memory_arena.hpp"
+#include "memory_pool_type.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            struct memory_pool_leak_handler
+            {
+                void operator()(std::ptrdiff_t amount);
+            };
+        } // namespace detail
+
+        /// A stateful \concept{concept_rawallocator,RawAllocator} that manages \concept{concept_node,nodes} of fixed size.
+        /// It uses a \ref memory_arena with a given \c BlockOrRawAllocator defaulting to \ref growing_block_allocator,
+        /// subdivides them in small nodes of given size and puts them onto a free list.
+        /// Allocation and deallocation simply remove or add nodes from this list and are thus fast.
+        /// The way the list is maintained can be controlled via the \c PoolType
+        /// which is either \ref node_pool, \ref array_pool or \ref small_node_pool.<br>
+        /// This kind of allocator is ideal for fixed size allocations and deallocations in any order,
+        /// for example in a node based container like \c std::list.
+        /// It is not so good for different allocation sizes and has some drawbacks for arrays
+        /// as described in \ref memory_pool_type.hpp.
+        /// \ingroup allocator
+        template <typename PoolType = node_pool, class BlockOrRawAllocator = default_allocator>
+        class memory_pool
+        : WPI_EBO(detail::default_leak_checker<detail::memory_pool_leak_handler>)
+        {
+            using free_list    = typename PoolType::type;
+            using leak_checker = detail::default_leak_checker<detail::memory_pool_leak_handler>;
+
+        public:
+            using allocator_type = make_block_allocator_t<BlockOrRawAllocator>;
+            using pool_type      = PoolType;
+
+            static constexpr std::size_t min_node_size =
+                WPI_IMPL_DEFINED(free_list::min_element_size);
+
+            /// \returns The minimum block size required for certain number of \concept{concept_node,node}.
+            /// \requires \c node_size must be a valid \concept{concept_node,node size}
+            /// and \c number_of_nodes must be a non-zero value.
+            /// \note MSVC's implementation of \c std::list for example is never empty and always allocates proxy nodes.
+            /// To get enough memory for \c N elements of a list, \c number_of_nodes needs to include the proxy count in addition to \c N.
+            static constexpr std::size_t min_block_size(std::size_t node_size,
+                                                        std::size_t number_of_nodes) noexcept
+            {
+                return detail::memory_block_stack::implementation_offset()
+                       + free_list::min_block_size(node_size, number_of_nodes);
+            }
+
+            /// \effects Creates it by specifying the size each \concept{concept_node,node} will have,
+            /// the initial block size for the arena and other constructor arguments for the \concept{concept_blockallocator,BlockAllocator}.
+            /// If the \c node_size is less than the \c min_node_size, the \c min_node_size will be the actual node size.
+            /// It will allocate an initial memory block with given size from the \concept{concept_blockallocator,BlockAllocator}
+            /// and puts it onto the free list.
+            /// \requires \c node_size must be a valid \concept{concept_node,node size}
+            /// and \c block_size must be at least \c min_block_size(node_size, 1).
+            template <typename... Args>
+            memory_pool(std::size_t node_size, std::size_t block_size, Args&&... args)
+            : arena_(block_size, detail::forward<Args>(args)...), free_list_(node_size)
+            {
+                allocate_block();
+            }
+
+            /// \effects Destroys the \ref memory_pool by returning all memory blocks,
+            /// regardless of properly deallocated back to the \concept{concept_blockallocator,BlockAllocator}.
+            ~memory_pool() noexcept {}
+
+            /// @{
+            /// \effects Moving a \ref memory_pool object transfers ownership over the free list,
+            /// i.e. the moved from pool is completely empty and the new one has all its memory.
+            /// That means that it is not allowed to call \ref deallocate_node() on a moved-from allocator
+            /// even when passing it memory that was previously allocated by this object.
+            memory_pool(memory_pool&& other) noexcept
+            : leak_checker(detail::move(other)),
+              arena_(detail::move(other.arena_)),
+              free_list_(detail::move(other.free_list_))
+            {
+            }
+
+            memory_pool& operator=(memory_pool&& other) noexcept
+            {
+                leak_checker::operator=(detail::move(other));
+                arena_                = detail::move(other.arena_);
+                free_list_            = detail::move(other.free_list_);
+                return *this;
+            }
+            /// @}
+
+            /// \effects Allocates a single \concept{concept_node,node} by removing it from the free list.
+            /// If the free list is empty, a new memory block will be allocated from the arena and put onto it.
+            /// The new block size will be \ref next_capacity() big.
+            /// \returns A node of size \ref node_size() suitable aligned,
+            /// i.e. suitable for any type where <tt>sizeof(T) < node_size()</tt>.
+            /// \throws Anything thrown by the used \concept{concept_blockallocator,BlockAllocator}'s allocation function if a growth is needed.
+            void* allocate_node()
+            {
+                if (free_list_.empty())
+                    allocate_block();
+                WPI_MEMORY_ASSERT(!free_list_.empty());
+                return free_list_.allocate();
+            }
+
+            /// \effects Allocates a single \concept{concept_node,node} similar to \ref allocate_node().
+            /// But if the free list is empty, a new block will *not* be allocated.
+            /// \returns A suitable aligned node of size \ref node_size() or `nullptr`.
+            void* try_allocate_node() noexcept
+            {
+                return free_list_.empty() ? nullptr : free_list_.allocate();
+            }
+
+            /// \effects Allocates an \concept{concept_array,array} of nodes by searching for \c n continuous nodes on the list and removing them.
+            /// Depending on the \c PoolType this can be a slow operation or not allowed at all.
+            /// This can sometimes lead to a growth, even if technically there is enough continuous memory on the free list.
+            /// \returns An array of \c n nodes of size \ref node_size() suitable aligned.
+            /// \throws Anything thrown by the used \concept{concept_blockallocator,BlockAllocator}'s allocation function if a growth is needed,
+            /// or \ref bad_array_size if <tt>n * node_size()</tt> is too big.
+            /// \requires \c n must be valid \concept{concept_array,array count}.
+            void* allocate_array(std::size_t n)
+            {
+                detail::check_allocation_size<bad_array_size>(
+                    n * node_size(), [&] { return pool_type::value ? next_capacity() : 0; },
+                    info());
+                return allocate_array(n, node_size());
+            }
+
+            /// \effects Allocates an \concept{concept_array,array} of nodes similar to \ref allocate_array().
+            /// But it will never allocate a new memory block.
+            /// \returns An array of \c n nodes of size \ref node_size() suitable aligned
+            /// or `nullptr`.
+            void* try_allocate_array(std::size_t n) noexcept
+            {
+                return try_allocate_array(n, node_size());
+            }
+
+            /// \effects Deallocates a single \concept{concept_node,node} by putting it back onto the free list.
+            /// \requires \c ptr must be a result from a previous call to \ref allocate_node() on the same free list,
+            /// i.e. either this allocator object or a new object created by moving this to it.
+            void deallocate_node(void* ptr) noexcept
+            {
+                free_list_.deallocate(ptr);
+            }
+
+            /// \effects Deallocates a single \concept{concept_node,node} but it does not be a result of a previous call to \ref allocate_node().
+            /// \returns `true` if the node could be deallocated, `false` otherwise.
+            /// \note Some free list implementations can deallocate any memory,
+            /// doesn't matter where it is coming from.
+            bool try_deallocate_node(void* ptr) noexcept
+            {
+                if (!arena_.owns(ptr))
+                    return false;
+                free_list_.deallocate(ptr);
+                return true;
+            }
+
+            /// \effects Deallocates an \concept{concept_array,array} by putting it back onto the free list.
+            /// \requires \c ptr must be a result from a previous call to \ref allocate_array() with the same \c n on the same free list,
+            /// i.e. either this allocator object or a new object created by moving this to it.
+            void deallocate_array(void* ptr, std::size_t n) noexcept
+            {
+                WPI_MEMORY_ASSERT_MSG(pool_type::value, "does not support array allocations");
+                free_list_.deallocate(ptr, n * node_size());
+            }
+
+            /// \effects Deallocates an \concept{concept_array,array} but it does not be a result of a previous call to \ref allocate_array().
+            /// \returns `true` if the node could be deallocated, `false` otherwise.
+            /// \note Some free list implementations can deallocate any memory,
+            /// doesn't matter where it is coming from.
+            bool try_deallocate_array(void* ptr, std::size_t n) noexcept
+            {
+                return try_deallocate_array(ptr, n, node_size());
+            }
+
+            /// \returns The size of each \concept{concept_node,node} in the pool,
+            /// this is either the same value as in the constructor or \c min_node_size if the value was too small.
+            std::size_t node_size() const noexcept
+            {
+                return free_list_.node_size();
+            }
+
+            /// \effects Returns the total amount of bytes remaining on the free list.
+            /// Divide it by \ref node_size() to get the number of nodes that can be allocated without growing the arena.
+            /// \note Array allocations may lead to a growth even if the capacity_left left is big enough.
+            std::size_t capacity_left() const noexcept
+            {
+                return free_list_.capacity() * node_size();
+            }
+
+            /// \returns The size of the next memory block after the free list gets empty and the arena grows.
+            /// \ref capacity_left() will increase by this amount.
+            /// \note Due to fence memory in debug mode this cannot be just divided by the \ref node_size() to get the number of nodes.
+            std::size_t next_capacity() const noexcept
+            {
+                return free_list_.usable_size(arena_.next_block_size());
+            }
+
+            /// \returns A reference to the \concept{concept_blockallocator,BlockAllocator} used for managing the arena.
+            /// \requires It is undefined behavior to move this allocator out into another object.
+            allocator_type& get_allocator() noexcept
+            {
+                return arena_.get_allocator();
+            }
+
+        private:
+            allocator_info info() const noexcept
+            {
+                return {WPI_MEMORY_LOG_PREFIX "::memory_pool", this};
+            }
+
+            void allocate_block()
+            {
+                auto mem = arena_.allocate_block();
+                free_list_.insert(static_cast<char*>(mem.memory), mem.size);
+            }
+
+            void* allocate_array(std::size_t n, std::size_t node_size)
+            {
+                auto mem = free_list_.empty() ? nullptr : free_list_.allocate(n * node_size);
+                if (!mem)
+                {
+                    allocate_block();
+                    mem = free_list_.allocate(n * node_size);
+                    if (!mem)
+                        WPI_THROW(bad_array_size(info(), n * node_size, capacity_left()));
+                }
+                return mem;
+            }
+
+            void* try_allocate_array(std::size_t n, std::size_t node_size) noexcept
+            {
+                return !pool_type::value || free_list_.empty() ? nullptr :
+                                                                 free_list_.allocate(n * node_size);
+            }
+
+            bool try_deallocate_array(void* ptr, std::size_t n, std::size_t node_size) noexcept
+            {
+                if (!pool_type::value || !arena_.owns(ptr))
+                    return false;
+                free_list_.deallocate(ptr, n * node_size);
+                return true;
+            }
+
+            memory_arena<allocator_type, false> arena_;
+            free_list                           free_list_;
+
+            friend allocator_traits<memory_pool<PoolType, BlockOrRawAllocator>>;
+            friend composable_allocator_traits<memory_pool<PoolType, BlockOrRawAllocator>>;
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class memory_pool<node_pool>;
+        extern template class memory_pool<array_pool>;
+        extern template class memory_pool<small_node_pool>;
+#endif
+
+        template <class Type, class Alloc>
+        constexpr std::size_t memory_pool<Type, Alloc>::min_node_size;
+
+        /// Specialization of the \ref allocator_traits for \ref memory_pool classes.
+        /// \note It is not allowed to mix calls through the specialization and through the member functions,
+        /// i.e. \ref memory_pool::allocate_node() and this \c allocate_node().
+        /// \ingroup allocator
+        template <typename PoolType, class ImplRawAllocator>
+        class allocator_traits<memory_pool<PoolType, ImplRawAllocator>>
+        {
+        public:
+            using allocator_type = memory_pool<PoolType, ImplRawAllocator>;
+            using is_stateful    = std::true_type;
+
+            /// \returns The result of \ref memory_pool::allocate_node().
+            /// \throws Anything thrown by the pool allocation function
+            /// or a \ref bad_allocation_size exception.
+            static void* allocate_node(allocator_type& state, std::size_t size,
+                                       std::size_t alignment)
+            {
+                detail::check_allocation_size<bad_node_size>(size, max_node_size(state),
+                                                             state.info());
+                detail::check_allocation_size<bad_alignment>(
+                    alignment, [&] { return max_alignment(state); }, state.info());
+                auto mem = state.allocate_node();
+                state.on_allocate(size);
+                return mem;
+            }
+
+            /// \effects Forwards to \ref memory_pool::allocate_array()
+            /// with the number of nodes adjusted to be the minimum,
+            /// i.e. when the \c size is less than the \ref memory_pool::node_size().
+            /// \returns A \concept{concept_array,array} with specified properties.
+            /// \requires The \ref memory_pool has to support array allocations.
+            /// \throws Anything thrown by the pool allocation function.
+            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size,
+                                        std::size_t alignment)
+            {
+                detail::check_allocation_size<bad_node_size>(size, max_node_size(state),
+                                                             state.info());
+                detail::check_allocation_size<bad_alignment>(
+                    alignment, [&] { return max_alignment(state); }, state.info());
+                detail::check_allocation_size<bad_array_size>(count * size, max_array_size(state),
+                                                              state.info());
+                auto mem = state.allocate_array(count, size);
+                state.on_allocate(count * size);
+                return mem;
+            }
+
+            /// \effects Just forwards to \ref memory_pool::deallocate_node().
+            static void deallocate_node(allocator_type& state, void* node, std::size_t size,
+                                        std::size_t) noexcept
+            {
+                state.deallocate_node(node);
+                state.on_deallocate(size);
+            }
+
+            /// \effects Forwards to \ref memory_pool::deallocate_array() with the same size adjustment.
+            static void deallocate_array(allocator_type& state, void* array, std::size_t count,
+                                         std::size_t size, std::size_t) noexcept
+            {
+                state.free_list_.deallocate(array, count * size);
+                state.on_deallocate(count * size);
+            }
+
+            /// \returns The maximum size of each node which is \ref memory_pool::node_size().
+            static std::size_t max_node_size(const allocator_type& state) noexcept
+            {
+                return state.node_size();
+            }
+
+            /// \returns An upper bound on the maximum array size which is \ref memory_pool::next_capacity().
+            static std::size_t max_array_size(const allocator_type& state) noexcept
+            {
+                return state.next_capacity();
+            }
+
+            /// \returns The maximum alignment which is the next bigger power of two if less than \c alignof(std::max_align_t)
+            /// or the maximum alignment itself otherwise.
+            static std::size_t max_alignment(const allocator_type& state) noexcept
+            {
+                return state.free_list_.alignment();
+            }
+        };
+
+        /// Specialization of the \ref composable_allocator_traits for \ref memory_pool classes.
+        /// \ingroup allocator
+        template <typename PoolType, class BlockOrRawAllocator>
+        class composable_allocator_traits<memory_pool<PoolType, BlockOrRawAllocator>>
+        {
+            using traits = allocator_traits<memory_pool<PoolType, BlockOrRawAllocator>>;
+
+        public:
+            using allocator_type = memory_pool<PoolType, BlockOrRawAllocator>;
+
+            /// \returns The result of \ref memory_pool::try_allocate_node()
+            /// or `nullptr` if the allocation size was too big.
+            static void* try_allocate_node(allocator_type& state, std::size_t size,
+                                           std::size_t alignment) noexcept
+            {
+                if (size > traits::max_node_size(state) || alignment > traits::max_alignment(state))
+                    return nullptr;
+                return state.try_allocate_node();
+            }
+
+            /// \effects Forwards to \ref memory_pool::try_allocate_array()
+            /// with the number of nodes adjusted to be the minimum,
+            /// if the \c size is less than the \ref memory_pool::node_size().
+            /// \returns A \concept{concept_array,array} with specified properties
+            /// or `nullptr` if it was unable to allocate.
+            static void* try_allocate_array(allocator_type& state, std::size_t count,
+                                            std::size_t size, std::size_t alignment) noexcept
+            {
+                if (size > traits::max_node_size(state)
+                    || count * size > traits::max_array_size(state)
+                    || alignment > traits::max_alignment(state))
+                    return nullptr;
+                return state.try_allocate_array(count, size);
+            }
+
+            /// \effects Just forwards to \ref memory_pool::try_deallocate_node().
+            /// \returns Whether the deallocation was successful.
+            static bool try_deallocate_node(allocator_type& state, void* node, std::size_t size,
+                                            std::size_t alignment) noexcept
+            {
+                if (size > traits::max_node_size(state) || alignment > traits::max_alignment(state))
+                    return false;
+                return state.try_deallocate_node(node);
+            }
+
+            /// \effects Forwards to \ref memory_pool::deallocate_array() with the same size adjustment.
+            /// \returns Whether the deallocation was successful.
+            static bool try_deallocate_array(allocator_type& state, void* array, std::size_t count,
+                                             std::size_t size, std::size_t alignment) noexcept
+            {
+                if (size > traits::max_node_size(state)
+                    || count * size > traits::max_array_size(state)
+                    || alignment > traits::max_alignment(state))
+                    return false;
+                return state.try_deallocate_array(array, count, size);
+            }
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class allocator_traits<memory_pool<node_pool>>;
+        extern template class allocator_traits<memory_pool<array_pool>>;
+        extern template class allocator_traits<memory_pool<small_node_pool>>;
+
+        extern template class composable_allocator_traits<memory_pool<node_pool>>;
+        extern template class composable_allocator_traits<memory_pool<array_pool>>;
+        extern template class composable_allocator_traits<memory_pool<small_node_pool>>;
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_MEMORY_POOL_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool_collection.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool_collection.hpp
new file mode 100644
index 0000000..294dd0a
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool_collection.hpp
@@ -0,0 +1,569 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_MEMORY_POOL_COLLECTION_HPP_INCLUDED
+#define WPI_MEMORY_MEMORY_POOL_COLLECTION_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::memory_pool_collection and related classes.
+
+#include <type_traits>
+
+#include "detail/align.hpp"
+#include "detail/assert.hpp"
+#include "detail/memory_stack.hpp"
+#include "detail/free_list_array.hpp"
+#include "config.hpp"
+#include "debugging.hpp"
+#include "error.hpp"
+#include "memory_arena.hpp"
+#include "memory_pool_type.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            struct memory_pool_collection_leak_handler
+            {
+                void operator()(std::ptrdiff_t amount);
+            };
+        } // namespace detail
+
+        /// A \c BucketDistribution for \ref memory_pool_collection defining that there is a bucket, i.e. pool, for each size.
+        /// That means that for each possible size up to an upper bound there will be a seperate free list.
+        /// Allocating a node will not waste any memory.
+        /// \ingroup allocator
+        struct identity_buckets
+        {
+            using type = detail::identity_access_policy;
+        };
+
+        /// A \c BucketDistribution for \ref memory_pool_collection defining that there is a bucket, i.e. pool, for each power of two.
+        /// That means for each power of two up to an upper bound there will be a separate free list.
+        /// Allocating a node will only waste half of the memory.
+        /// \ingroup allocator
+        struct log2_buckets
+        {
+            using type = detail::log2_access_policy;
+        };
+
+        /// A stateful \concept{concept_rawallocator,RawAllocator} that behaves as a collection of multiple \ref memory_pool objects.
+        /// It maintains a list of multiple free lists, whose types are controlled via the \c PoolType tags defined in \ref memory_pool_type.hpp,
+        /// each of a different size as defined in the \c BucketDistribution (\ref identity_buckets or \ref log2_buckets).
+        /// Allocating a node of given size will use the appropriate free list.<br>
+        /// This allocator is ideal for \concept{concept_node,node} allocations in any order but with a predefined set of sizes,
+        /// not only one size like \ref memory_pool.
+        /// \ingroup allocator
+        template <class PoolType, class BucketDistribution,
+                  class BlockOrRawAllocator = default_allocator>
+        class memory_pool_collection
+        : WPI_EBO(detail::default_leak_checker<detail::memory_pool_collection_leak_handler>)
+        {
+            using free_list_array =
+                detail::free_list_array<typename PoolType::type, typename BucketDistribution::type>;
+            using leak_checker =
+                detail::default_leak_checker<detail::memory_pool_collection_leak_handler>;
+
+        public:
+            using allocator_type      = make_block_allocator_t<BlockOrRawAllocator>;
+            using pool_type           = PoolType;
+            using bucket_distribution = BucketDistribution;
+
+            /// \effects Creates it by giving it the maximum node size it should be able to allocate,
+            /// the size of the initial memory block and other constructor arguments for the \concept{concept_blockallocator,BlockAllocator}.
+            /// The \c BucketDistribution controls how many free lists are created,
+            /// but unlike in \ref memory_pool all free lists are initially empty and the first memory block queued.
+            /// \requires \c max_node_size must be a valid \concept{concept_node,node} size
+            /// and \c block_size must be non-zero.
+            template <typename... Args>
+            memory_pool_collection(std::size_t max_node_size, std::size_t block_size,
+                                   Args&&... args)
+            : arena_(block_size, detail::forward<Args>(args)...),
+              stack_(allocate_block()),
+              pools_(stack_, block_end(), max_node_size)
+            {
+            }
+
+            /// \effects Destroys the \ref memory_pool_collection by returning all memory blocks,
+            /// regardless of properly deallocated back to the \concept{concept_blockallocator,BlockAllocator}.
+            ~memory_pool_collection() noexcept = default;
+
+            /// @{
+            /// \effects Moving a \ref memory_pool_collection object transfers ownership over the free lists,
+            /// i.e. the moved from pool is completely empty and the new one has all its memory.
+            /// That means that it is not allowed to call \ref deallocate_node() on a moved-from allocator
+            /// even when passing it memory that was previously allocated by this object.
+            memory_pool_collection(memory_pool_collection&& other) noexcept
+            : leak_checker(detail::move(other)),
+              arena_(detail::move(other.arena_)),
+              stack_(detail::move(other.stack_)),
+              pools_(detail::move(other.pools_))
+            {
+            }
+
+            memory_pool_collection& operator=(memory_pool_collection&& other) noexcept
+            {
+                leak_checker::operator=(detail::move(other));
+                arena_                = detail::move(other.arena_);
+                stack_                = detail::move(other.stack_);
+                pools_                = detail::move(other.pools_);
+                return *this;
+            }
+            /// @}
+
+            /// \effects Allocates a \concept{concept_node,node} of given size.
+            /// It first finds the appropriate free list as defined in the \c BucketDistribution.
+            /// If it is empty, it will use an implementation defined amount of memory from the arena
+            /// and inserts it in it.
+            /// If the arena is empty too, it will request a new memory block from the \concept{concept_blockallocator,BlockAllocator}
+            /// of size \ref next_capacity() and puts part of it onto this free list.
+            /// Then it removes a node from it.
+            /// \returns A \concept{concept_node,node} of given size suitable aligned,
+            /// i.e. suitable for any type where <tt>sizeof(T) < node_size</tt>.
+            /// \throws Anything thrown by the \concept{concept_blockallocator,BlockAllocator} if a growth is needed or a \ref bad_node_size exception if the node size is too big.
+            void* allocate_node(std::size_t node_size)
+            {
+                detail::check_allocation_size<bad_node_size>(
+                    node_size, [&] { return max_node_size(); }, info());
+                auto& pool = pools_.get(node_size);
+                if (pool.empty())
+                {
+                    auto block = reserve_memory(pool, def_capacity());
+                    pool.insert(block.memory, block.size);
+                }
+
+                auto mem = pool.allocate();
+                WPI_MEMORY_ASSERT(mem);
+                return mem;
+            }
+
+            /// \effects Allocates a \concept{concept_node,node} of given size.
+            /// It is similar to \ref allocate_node() but will return `nullptr` on any failure,
+            /// instead of growing the arnea and possibly throwing.
+            /// \returns A \concept{concept_node,node} of given size suitable aligned
+            /// or `nullptr` in case of failure.
+            void* try_allocate_node(std::size_t node_size) noexcept
+            {
+                if (node_size > max_node_size())
+                    return nullptr;
+                auto& pool = pools_.get(node_size);
+                if (pool.empty())
+                {
+                    try_reserve_memory(pool, def_capacity());
+                    return pool.empty() ? nullptr : pool.allocate();
+                }
+                else
+                    return pool.allocate();
+            }
+
+            /// \effects Allocates an \concept{concept_array,array} of nodes by searching for \c n continuous nodes on the appropriate free list and removing them.
+            /// Depending on the \c PoolType this can be a slow operation or not allowed at all.
+            /// This can sometimes lead to a growth on the free list, even if technically there is enough continuous memory on the free list.
+            /// Otherwise has the same behavior as \ref allocate_node().
+            /// \returns An array of \c n nodes of size \c node_size suitable aligned.
+            /// \throws Anything thrown by the used \concept{concept_blockallocator,BlockAllocator}'s allocation function if a growth is needed,
+            /// or a \ref bad_allocation_size exception.
+            /// \requires \c count must be valid \concept{concept_array,array count} and
+            /// \c node_size must be valid \concept{concept_node,node size}.
+            void* allocate_array(std::size_t count, std::size_t node_size)
+            {
+                detail::check_allocation_size<bad_node_size>(
+                    node_size, [&] { return max_node_size(); }, info());
+
+                auto& pool = pools_.get(node_size);
+
+                // try allocating if not empty
+                // for pools without array allocation support, allocate() will always return nullptr
+                auto mem = pool.empty() ? nullptr : pool.allocate(count * node_size);
+                if (!mem)
+                {
+                    // reserve more memory
+                    auto block = reserve_memory(pool, def_capacity());
+                    pool.insert(block.memory, block.size);
+
+                    mem = pool.allocate(count * node_size);
+                    if (!mem)
+                    {
+                        // reserve more then the default capacity if that didn't work either
+                        detail::check_allocation_size<bad_array_size>(
+                            count * node_size,
+                            [&] { return next_capacity() - pool.alignment() + 1; }, info());
+
+                        block = reserve_memory(pool, count * node_size);
+                        pool.insert(block.memory, block.size);
+
+                        mem = pool.allocate(count * node_size);
+                        WPI_MEMORY_ASSERT(mem);
+                    }
+                }
+
+                return mem;
+            }
+
+            /// \effects Allocates a \concept{concept_array,array} of given size.
+            /// It is similar to \ref allocate_node() but will return `nullptr` on any failure,
+            /// instead of growing the arnea and possibly throwing.
+            /// \returns A \concept{concept_array,array} of given size suitable aligned
+            /// or `nullptr` in case of failure.
+            void* try_allocate_array(std::size_t count, std::size_t node_size) noexcept
+            {
+                if (!pool_type::value || node_size > max_node_size())
+                    return nullptr;
+                auto& pool = pools_.get(node_size);
+                if (pool.empty())
+                {
+                    try_reserve_memory(pool, def_capacity());
+                    return pool.empty() ? nullptr : pool.allocate(count * node_size);
+                }
+                else
+                    return pool.allocate(count * node_size);
+            }
+
+            /// \effects Deallocates a \concept{concept_node,node} by putting it back onto the appropriate free list.
+            /// \requires \c ptr must be a result from a previous call to \ref allocate_node() with the same size on the same free list,
+            /// i.e. either this allocator object or a new object created by moving this to it.
+            void deallocate_node(void* ptr, std::size_t node_size) noexcept
+            {
+                pools_.get(node_size).deallocate(ptr);
+            }
+
+            /// \effects Deallocates a \concept{concept_node,node} similar to \ref deallocate_node().
+            /// But it checks if it can deallocate this memory.
+            /// \returns `true` if the node could be deallocated,
+            /// `false` otherwise.
+            bool try_deallocate_node(void* ptr, std::size_t node_size) noexcept
+            {
+                if (node_size > max_node_size() || !arena_.owns(ptr))
+                    return false;
+                pools_.get(node_size).deallocate(ptr);
+                return true;
+            }
+
+            /// \effects Deallocates an \concept{concept_array,array} by putting it back onto the free list.
+            /// \requires \c ptr must be a result from a previous call to \ref allocate_array() with the same sizes on the same free list,
+            /// i.e. either this allocator object or a new object created by moving this to it.
+            void deallocate_array(void* ptr, std::size_t count, std::size_t node_size) noexcept
+            {
+                pools_.get(node_size).deallocate(ptr, count * node_size);
+            }
+
+            /// \effects Deallocates a \concept{concept_array,array} similar to \ref deallocate_array().
+            /// But it checks if it can deallocate this memory.
+            /// \returns `true` if the array could be deallocated,
+            /// `false` otherwise.
+            bool try_deallocate_array(void* ptr, std::size_t count, std::size_t node_size) noexcept
+            {
+                if (!pool_type::value || node_size > max_node_size() || !arena_.owns(ptr))
+                    return false;
+                pools_.get(node_size).deallocate(ptr, count * node_size);
+                return true;
+            }
+
+            /// \effects Inserts more memory on the free list for nodes of given size.
+            /// It will try to put \c capacity_left bytes from the arena onto the free list defined over the \c BucketDistribution,
+            /// if the arena is empty, a new memory block is requested from the \concept{concept_blockallocator,BlockAllocator}
+            /// and it will be used.
+            /// \throws Anything thrown by the \concept{concept_blockallocator,BlockAllocator} if a growth is needed.
+            /// \requires \c node_size must be valid \concept{concept_node,node size} less than or equal to \ref max_node_size(),
+            /// \c capacity_left must be less than \ref next_capacity().
+            void reserve(std::size_t node_size, std::size_t capacity)
+            {
+                WPI_MEMORY_ASSERT_MSG(node_size <= max_node_size(), "node_size too big");
+                auto& pool = pools_.get(node_size);
+                reserve_memory(pool, capacity);
+            }
+
+            /// \returns The maximum node size for which is a free list.
+            /// This is the value passed to it in the constructor.
+            std::size_t max_node_size() const noexcept
+            {
+                return pools_.max_node_size();
+            }
+
+            /// \returns The amount of nodes available in the free list for nodes of given size
+            /// as defined over the \c BucketDistribution.
+            /// This is the number of nodes that can be allocated without the free list requesting more memory from the arena.
+            /// \note Array allocations may lead to a growth even if the capacity_left is big enough.
+            std::size_t pool_capacity_left(std::size_t node_size) const noexcept
+            {
+                WPI_MEMORY_ASSERT_MSG(node_size <= max_node_size(), "node_size too big");
+                return pools_.get(node_size).capacity();
+            }
+
+            /// \returns The amount of memory available in the arena not inside the free lists.
+            /// This is the number of bytes that can be inserted into the free lists
+            /// without requesting more memory from the \concept{concept_blockallocator,BlockAllocator}.
+            /// \note Array allocations may lead to a growth even if the capacity is big enough.
+            std::size_t capacity_left() const noexcept
+            {
+                return std::size_t(block_end() - stack_.top());
+            }
+
+            /// \returns The size of the next memory block after \ref capacity_left() arena grows.
+            /// This is the amount of memory that can be distributed in the pools.
+            /// \note If the `PoolType` is \ref small_node_pool, the exact usable memory is lower than that.
+            std::size_t next_capacity() const noexcept
+            {
+                return arena_.next_block_size();
+            }
+
+            /// \returns A reference to the \concept{concept_blockallocator,BlockAllocator} used for managing the arena.
+            /// \requires It is undefined behavior to move this allocator out into another object.
+            allocator_type& get_allocator() noexcept
+            {
+                return arena_.get_allocator();
+            }
+
+        private:
+            allocator_info info() const noexcept
+            {
+                return {WPI_MEMORY_LOG_PREFIX "::memory_pool_collection", this};
+            }
+
+            std::size_t def_capacity() const noexcept
+            {
+                return arena_.next_block_size() / pools_.size();
+            }
+
+            detail::fixed_memory_stack allocate_block()
+            {
+                return detail::fixed_memory_stack(arena_.allocate_block().memory);
+            }
+
+            const char* block_end() const noexcept
+            {
+                auto block = arena_.current_block();
+                return static_cast<const char*>(block.memory) + block.size;
+            }
+
+            bool insert_rest(typename pool_type::type& pool) noexcept
+            {
+                if (auto remaining = std::size_t(block_end() - stack_.top()))
+                {
+                    auto offset = detail::align_offset(stack_.top(), detail::max_alignment);
+                    if (offset < remaining)
+                    {
+                        detail::debug_fill(stack_.top(), offset, debug_magic::alignment_memory);
+                        pool.insert(stack_.top() + offset, remaining - offset);
+                        return true;
+                    }
+                }
+
+                return false;
+            }
+
+            void try_reserve_memory(typename pool_type::type& pool, std::size_t capacity) noexcept
+            {
+                auto mem = stack_.allocate(block_end(), capacity, detail::max_alignment);
+                if (!mem)
+                    insert_rest(pool);
+                else
+                    pool.insert(mem, capacity);
+            }
+
+            memory_block reserve_memory(typename pool_type::type& pool, std::size_t capacity)
+            {
+                auto mem = stack_.allocate(block_end(), capacity, detail::max_alignment);
+                if (!mem)
+                {
+                    insert_rest(pool);
+                    // get new block
+                    stack_ = allocate_block();
+
+                    // allocate ensuring alignment
+                    mem = stack_.allocate(block_end(), capacity, detail::max_alignment);
+                    WPI_MEMORY_ASSERT(mem);
+                }
+                return {mem, capacity};
+            }
+
+            memory_arena<allocator_type, false> arena_;
+            detail::fixed_memory_stack          stack_;
+            free_list_array                     pools_;
+
+            friend allocator_traits<memory_pool_collection>;
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class memory_pool_collection<node_pool, identity_buckets>;
+        extern template class memory_pool_collection<array_pool, identity_buckets>;
+        extern template class memory_pool_collection<small_node_pool, identity_buckets>;
+
+        extern template class memory_pool_collection<node_pool, log2_buckets>;
+        extern template class memory_pool_collection<array_pool, log2_buckets>;
+        extern template class memory_pool_collection<small_node_pool, log2_buckets>;
+#endif
+
+        /// An alias for \ref memory_pool_collection using the \ref identity_buckets policy
+        /// and a \c PoolType defaulting to \ref node_pool.
+        /// \ingroup allocator
+        template <class PoolType = node_pool, class ImplAllocator = default_allocator>
+        WPI_ALIAS_TEMPLATE(bucket_allocator,
+                                 memory_pool_collection<PoolType, identity_buckets, ImplAllocator>);
+
+        template <class Allocator>
+        class allocator_traits;
+
+        /// Specialization of the \ref allocator_traits for \ref memory_pool_collection classes.
+        /// \note It is not allowed to mix calls through the specialization and through the member functions,
+        /// i.e. \ref memory_pool_collection::allocate_node() and this \c allocate_node().
+        /// \ingroup allocator
+        template <class Pool, class BucketDist, class RawAllocator>
+        class allocator_traits<memory_pool_collection<Pool, BucketDist, RawAllocator>>
+        {
+        public:
+            using allocator_type = memory_pool_collection<Pool, BucketDist, RawAllocator>;
+            using is_stateful    = std::true_type;
+
+            /// \returns The result of \ref memory_pool_collection::allocate_node().
+            /// \throws Anything thrown by the pool allocation function
+            /// or a \ref bad_allocation_size exception if \c size / \c alignment exceeds \ref max_node_size() / the suitable alignment value,
+            /// i.e. the node is over-aligned.
+            static void* allocate_node(allocator_type& state, std::size_t size,
+                                       std::size_t alignment)
+            {
+                // node already checked
+                detail::check_allocation_size<bad_alignment>(
+                    alignment, [&] { return detail::alignment_for(size); }, state.info());
+                auto mem = state.allocate_node(size);
+                state.on_allocate(size);
+                return mem;
+            }
+
+            /// \returns The result of \ref memory_pool_collection::allocate_array().
+            /// \throws Anything thrown by the pool allocation function or a \ref bad_allocation_size exception.
+            /// \requires The \ref memory_pool_collection has to support array allocations.
+            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size,
+                                        std::size_t alignment)
+            {
+                // node and array already checked
+                detail::check_allocation_size<bad_alignment>(
+                    alignment, [&] { return detail::alignment_for(size); }, state.info());
+                auto mem = state.allocate_array(count, size);
+                state.on_allocate(count * size);
+                return mem;
+            }
+
+            /// \effects Calls \ref memory_pool_collection::deallocate_node().
+            static void deallocate_node(allocator_type& state, void* node, std::size_t size,
+                                        std::size_t) noexcept
+            {
+                state.deallocate_node(node, size);
+                state.on_deallocate(size);
+            }
+
+            /// \effects Calls \ref memory_pool_collection::deallocate_array().
+            /// \requires The \ref memory_pool_collection has to support array allocations.
+            static void deallocate_array(allocator_type& state, void* array, std::size_t count,
+                                         std::size_t size, std::size_t) noexcept
+            {
+                state.deallocate_array(array, count, size);
+                state.on_deallocate(count * size);
+            }
+
+            /// \returns The maximum size of each node which is \ref memory_pool_collection::max_node_size().
+            static std::size_t max_node_size(const allocator_type& state) noexcept
+            {
+                return state.max_node_size();
+            }
+
+            /// \returns An upper bound on the maximum array size which is \ref memory_pool::next_capacity().
+            static std::size_t max_array_size(const allocator_type& state) noexcept
+            {
+                return state.next_capacity();
+            }
+
+            /// \returns Just \c alignof(std::max_align_t) since the actual maximum alignment depends on the node size,
+            /// the nodes must not be over-aligned.
+            static std::size_t max_alignment(const allocator_type&) noexcept
+            {
+                return detail::max_alignment;
+            }
+        };
+
+        /// Specialization of the \ref composable_allocator_traits for \ref memory_pool_collection classes.
+        /// \ingroup allocator
+        template <class Pool, class BucketDist, class RawAllocator>
+        class composable_allocator_traits<memory_pool_collection<Pool, BucketDist, RawAllocator>>
+        {
+            using traits = allocator_traits<memory_pool_collection<Pool, BucketDist, RawAllocator>>;
+
+        public:
+            using allocator_type = memory_pool_collection<Pool, BucketDist, RawAllocator>;
+
+            /// \returns The result of \ref memory_pool_collection::try_allocate_node()
+            /// or `nullptr` if the allocation size was too big.
+            static void* try_allocate_node(allocator_type& state, std::size_t size,
+                                           std::size_t alignment) noexcept
+            {
+                if (alignment > traits::max_alignment(state))
+                    return nullptr;
+                return state.try_allocate_node(size);
+            }
+
+            /// \returns The result of \ref memory_pool_collection::try_allocate_array()
+            /// or `nullptr` if the allocation size was too big.
+            static void* try_allocate_array(allocator_type& state, std::size_t count,
+                                            std::size_t size, std::size_t alignment) noexcept
+            {
+                if (count * size > traits::max_array_size(state)
+                    || alignment > traits::max_alignment(state))
+                    return nullptr;
+                return state.try_allocate_array(count, size);
+            }
+
+            /// \effects Just forwards to \ref memory_pool_collection::try_deallocate_node().
+            /// \returns Whether the deallocation was successful.
+            static bool try_deallocate_node(allocator_type& state, void* node, std::size_t size,
+                                            std::size_t alignment) noexcept
+            {
+                if (alignment > traits::max_alignment(state))
+                    return false;
+                return state.try_deallocate_node(node, size);
+            }
+
+            /// \effects Forwards to \ref memory_pool_collection::deallocate_array().
+            /// \returns Whether the deallocation was successful.
+            static bool try_deallocate_array(allocator_type& state, void* array, std::size_t count,
+                                             std::size_t size, std::size_t alignment) noexcept
+            {
+                if (count * size > traits::max_array_size(state)
+                    || alignment > traits::max_alignment(state))
+                    return false;
+                return state.try_deallocate_array(array, count, size);
+            }
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class allocator_traits<memory_pool_collection<node_pool, identity_buckets>>;
+        extern template class allocator_traits<
+            memory_pool_collection<array_pool, identity_buckets>>;
+        extern template class allocator_traits<
+            memory_pool_collection<small_node_pool, identity_buckets>>;
+
+        extern template class allocator_traits<memory_pool_collection<node_pool, log2_buckets>>;
+        extern template class allocator_traits<memory_pool_collection<array_pool, log2_buckets>>;
+        extern template class allocator_traits<
+            memory_pool_collection<small_node_pool, log2_buckets>>;
+
+        extern template class composable_allocator_traits<
+            memory_pool_collection<node_pool, identity_buckets>>;
+        extern template class composable_allocator_traits<
+            memory_pool_collection<array_pool, identity_buckets>>;
+        extern template class composable_allocator_traits<
+            memory_pool_collection<small_node_pool, identity_buckets>>;
+
+        extern template class composable_allocator_traits<
+            memory_pool_collection<node_pool, log2_buckets>>;
+        extern template class composable_allocator_traits<
+            memory_pool_collection<array_pool, log2_buckets>>;
+        extern template class composable_allocator_traits<
+            memory_pool_collection<small_node_pool, log2_buckets>>;
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_MEMORY_POOL_COLLECTION_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool_type.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool_type.hpp
new file mode 100644
index 0000000..a7c8ff8
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_pool_type.hpp
@@ -0,0 +1,53 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_MEMORY_POOL_TYPE_HPP_INCLUDED
+#define WPI_MEMORY_MEMORY_POOL_TYPE_HPP_INCLUDED
+
+/// \file
+/// The \c PoolType tag types.
+
+#include <type_traits>
+
+#include "detail/free_list.hpp"
+#include "detail/small_free_list.hpp"
+#include "config.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// Tag type defining a memory pool optimized for nodes.
+        /// It does not support array allocations that great and may trigger a growth even if there is enough memory.
+        /// But it is the fastest pool type.
+        /// \ingroup allocator
+        struct node_pool : WPI_EBO(std::true_type)
+        {
+            using type = detail::node_free_memory_list;
+        };
+
+        /// Tag type defining a memory pool optimized for arrays.
+        /// It keeps the nodes oredered inside the free list and searches the list for an appropriate memory block.
+        /// Array allocations are still pretty slow, if the array gets big enough it can get slower than \c new.
+        /// Node allocations are still fast, unless there is deallocation in random order.
+        /// \note Use this tag type only if you really need to have a memory pool!
+        /// \ingroup allocator
+        struct array_pool : WPI_EBO(std::true_type)
+        {
+            using type = detail::array_free_memory_list;
+        };
+
+        /// Tag type defining a memory pool optimized for small nodes.
+        /// The free list is intrusive and thus requires that each node has at least the size of a pointer.
+        /// This tag type does not have this requirement and thus allows zero-memory-overhead allocations of small nodes.
+        /// It is a little bit slower than \ref node_pool and does not support arrays.
+        /// \ingroup allocator
+        struct small_node_pool : WPI_EBO(std::false_type)
+        {
+            using type = detail::small_free_memory_list;
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_MEMORY_POOL_TYPE_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_resource_adapter.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_resource_adapter.hpp
new file mode 100644
index 0000000..e805f9b
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_resource_adapter.hpp
@@ -0,0 +1,239 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_MEMORY_RESOURCE_ADAPTER_HPP_INCLUDED
+#define WPI_MEMORY_MEMORY_RESOURCE_ADAPTER_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::memory_resource_adapter and \ref wpi::memory::memory_resource_allocator to allow usage of PMRs.
+
+#include "detail/assert.hpp"
+#include "detail/utility.hpp"
+#include "config.hpp"
+#include "allocator_traits.hpp"
+
+#if defined(__has_include) && __has_include(<memory_resource>)
+
+#if !defined(__GNUC__) || __cplusplus >= 201703L
+// The experimental/memory_resource header lacks a check for C++17 on older GCC,
+// so we have to do it for them.
+#include <memory_resource>
+#endif
+
+#elif defined(__has_include) && __has_include(<experimental/memory_resource>)
+
+#if !defined(__GNUC__) || __cplusplus >= 201402L
+// The experimental/memory_resource header lacks a check for C++14 on older GCC,
+// so we have to do it for them.
+#include <experimental/memory_resource>
+#endif
+
+#endif
+
+#if defined(__cpp_lib_memory_resource)
+
+// We use std::pmr::memory_resource.
+namespace wpi_memory_pmr = std::pmr;
+
+#elif defined(__cpp_lib_experimental_memory_resources)
+
+// We use std::experimental::pmr::memory_resource.
+namespace wpi_memory_pmr = std::experimental::pmr;
+
+#else
+
+// We use our own implementation.
+namespace wpi_memory_pmr
+{
+    // see N3916 for documentation
+    class memory_resource
+    {
+        static const std::size_t max_alignment = alignof(std::max_align_t);
+
+    public:
+        virtual ~memory_resource() noexcept {}
+        void* allocate(std::size_t bytes, std::size_t alignment = max_alignment)
+        {
+            return do_allocate(bytes, alignment);
+        }
+        void deallocate(void* p, std::size_t bytes, std::size_t alignment = max_alignment)
+        {
+            do_deallocate(p, bytes, alignment);
+        }
+        bool is_equal(const memory_resource& other) const noexcept
+        {
+            return do_is_equal(other);
+        }
+
+    protected:
+        virtual void* do_allocate(std::size_t bytes, std::size_t alignment)            = 0;
+        virtual void  do_deallocate(void* p, std::size_t bytes, std::size_t alignment) = 0;
+        virtual bool  do_is_equal(const memory_resource& other) const noexcept         = 0;
+    };
+    inline bool operator==(const memory_resource& a, const memory_resource& b) noexcept
+    {
+        return &a == &b || a.is_equal(b);
+    }
+    inline bool operator!=(const memory_resource& a, const memory_resource& b) noexcept
+    {
+        return !(a == b);
+    }
+} // namespace wpi_memory_pmr
+
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// The \c memory_resource abstract base class used in the implementation.
+        /// \ingroup adapter
+        WPI_ALIAS_TEMPLATE(memory_resource, foonathan_memory_pmr::memory_resource);
+
+        /// Wraps a \concept{concept_rawallocator,RawAllocator} and makes it a \ref memory_resource.
+        /// \ingroup adapter
+        template <class RawAllocator>
+        class memory_resource_adapter
+        : public memory_resource,
+          WPI_EBO(allocator_traits<RawAllocator>::allocator_type)
+        {
+        public:
+            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;
+
+            /// \effects Creates the resource by moving in the allocator.
+            memory_resource_adapter(allocator_type&& other) noexcept
+            : allocator_type(detail::move(other))
+            {
+            }
+
+            /// @{
+            /// \returns A reference to the wrapped allocator.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+            const allocator_type& get_allocator() const noexcept
+            {
+                return *this;
+            }
+            /// @}
+
+        protected:
+            using traits_type = allocator_traits<RawAllocator>;
+
+            /// \effects Allocates raw memory with given size and alignment.
+            /// It forwards to \c allocate_node() or \c allocate_array() depending on the size.
+            /// \returns The new memory as returned by the \concept{concept_rawallocator,RawAllocator}.
+            /// \throws Anything thrown by the allocation function.
+            void* do_allocate(std::size_t bytes, std::size_t alignment) override
+            {
+                auto max = traits_type::max_node_size(*this);
+                if (bytes <= max)
+                    return traits_type::allocate_node(*this, bytes, alignment);
+                auto div = bytes / max;
+                auto mod = bytes % max;
+                auto n   = div + (mod != 0);
+                return traits_type::allocate_array(*this, n, max, alignment);
+            }
+
+            /// \effects Deallocates memory previously allocated by \ref do_allocate.
+            /// It forwards to \c deallocate_node() or \c deallocate_array() depending on the size.
+            /// \throws Nothing.
+            void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) override
+            {
+                auto max = traits_type::max_node_size(*this);
+                if (bytes <= max)
+                    traits_type::deallocate_node(*this, p, bytes, alignment);
+                else
+                {
+                    auto div = bytes / max;
+                    auto mod = bytes % max;
+                    auto n   = div + (mod != 0);
+                    traits_type::deallocate_array(*this, p, n, max, alignment);
+                }
+            }
+
+            /// \returns Whether or not \c *this is equal to \c other
+            /// by comparing the addresses.
+            bool do_is_equal(const memory_resource& other) const noexcept override
+            {
+                return this == &other;
+            }
+        };
+
+        /// Wraps a \ref memory_resource and makes it a \concept{concept_rawallocator,RawAllocator}.
+        /// \ingroup adapter
+        class memory_resource_allocator
+        {
+        public:
+            /// \effects Creates it by giving it a pointer to the \ref memory_resource.
+            /// \requires \c ptr must not be \c nullptr.
+            memory_resource_allocator(memory_resource* ptr) noexcept : ptr_(ptr)
+            {
+                WPI_MEMORY_ASSERT(ptr);
+            }
+
+            /// \effects Allocates a node by forwarding to the \c allocate() function.
+            /// \returns The node as returned by the \ref memory_resource.
+            /// \throws Anything thrown by the \c allocate() function.
+            void* allocate_node(std::size_t size, std::size_t alignment)
+            {
+                return ptr_->allocate(size, alignment);
+            }
+
+            /// \effects Deallocates a node by forwarding to the \c deallocate() function.
+            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                ptr_->deallocate(ptr, size, alignment);
+            }
+
+            /// \returns The maximum alignment which is the maximum value of type \c std::size_t.
+            std::size_t max_alignment() const noexcept
+            {
+                return std::size_t(-1);
+            }
+
+            /// \returns A pointer to the used \ref memory_resource, this is never \c nullptr.
+            memory_resource* resource() const noexcept
+            {
+                return ptr_;
+            }
+
+        private:
+            memory_resource* ptr_;
+        };
+
+        /// @{
+        /// \returns Whether `lhs` and `rhs` share the same resource.
+        /// \relates memory_resource_allocator
+        inline bool operator==(const memory_resource_allocator& lhs,
+                               const memory_resource_allocator& rhs) noexcept
+        {
+            return lhs.resource() == rhs.resource();
+        }
+
+        inline bool operator!=(const memory_resource_allocator& lhs,
+                               const memory_resource_allocator& rhs) noexcept
+        {
+            return !(lhs == rhs);
+        }
+        /// @}
+
+#if !defined(DOXYGEN)
+        template <class RawAllocator>
+        struct is_shared_allocator;
+#endif
+
+        /// Specialization of \ref is_shared_allocator to mark \ref memory_resource_allocator as shared.
+        /// This allows using it as \ref allocator_reference directly.
+        /// \ingroup adapter
+        template <>
+        struct is_shared_allocator<memory_resource_allocator> : std::true_type
+        {
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_MEMORY_RESOURCE_ADAPTER_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_stack.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_stack.hpp
new file mode 100644
index 0000000..4c9f524
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/memory_stack.hpp
@@ -0,0 +1,489 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_MEMORY_STACK_HPP_INCLUDED
+#define WPI_MEMORY_MEMORY_STACK_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::memory_stack and its \ref wpi::memory::allocator_traits specialization.
+
+// Inform that wpi::memory::memory_stack::min_block_size API is available
+#define WPI_MEMORY_MEMORY_STACK_HAS_MIN_BLOCK_SIZE
+
+#include <cstdint>
+#include <type_traits>
+
+#include "detail/assert.hpp"
+#include "detail/memory_stack.hpp"
+#include "config.hpp"
+#include "error.hpp"
+#include "memory_arena.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+#if !defined(DOXYGEN)
+        template <class Impl>
+        class memory_stack;
+#endif
+
+        namespace detail
+        {
+            class stack_marker
+            {
+                std::size_t index;
+                char*       top;
+                const char* end;
+
+                stack_marker(std::size_t i, const detail::fixed_memory_stack& s,
+                             const char* e) noexcept
+                : index(i), top(s.top()), end(e)
+                {
+                }
+
+                friend bool operator==(const stack_marker& lhs, const stack_marker& rhs) noexcept
+                {
+                    if (lhs.index != rhs.index)
+                        return false;
+                    WPI_MEMORY_ASSERT_MSG(lhs.end == rhs.end, "you must not compare two "
+                                                                    "stack markers from different "
+                                                                    "stacks");
+                    return lhs.top == rhs.top;
+                }
+
+                friend bool operator!=(const stack_marker& lhs, const stack_marker& rhs) noexcept
+                {
+                    return !(rhs == lhs);
+                }
+
+                friend bool operator<(const stack_marker& lhs, const stack_marker& rhs) noexcept
+                {
+                    if (lhs.index != rhs.index)
+                        return lhs.index < rhs.index;
+                    WPI_MEMORY_ASSERT_MSG(lhs.end == rhs.end, "you must not compare two "
+                                                                    "stack markers from different "
+                                                                    "stacks");
+                    return lhs.top < rhs.top;
+                }
+
+                friend bool operator>(const stack_marker& lhs, const stack_marker& rhs) noexcept
+                {
+                    return rhs < lhs;
+                }
+
+                friend bool operator<=(const stack_marker& lhs, const stack_marker& rhs) noexcept
+                {
+                    return !(rhs < lhs);
+                }
+
+                friend bool operator>=(const stack_marker& lhs, const stack_marker& rhs) noexcept
+                {
+                    return !(lhs < rhs);
+                }
+
+                template <class Impl>
+                friend class memory::memory_stack;
+            };
+
+            struct memory_stack_leak_handler
+            {
+                void operator()(std::ptrdiff_t amount);
+            };
+        } // namespace detail
+
+        /// A stateful \concept{concept_rawallocator,RawAllocator} that provides stack-like (LIFO) allocations.
+        /// It uses a \ref memory_arena with a given \c BlockOrRawAllocator defaulting to \ref growing_block_allocator to allocate huge blocks
+        /// and saves a marker to the current top.
+        /// Allocation simply moves this marker by the appropriate number of bytes and returns the pointer at the old marker position,
+        /// deallocation is not directly supported, only setting the marker to a previously queried position.
+        /// \ingroup allocator
+        template <class BlockOrRawAllocator = default_allocator>
+        class memory_stack
+        : WPI_EBO(detail::default_leak_checker<detail::memory_stack_leak_handler>)
+        {
+        public:
+            using allocator_type = make_block_allocator_t<BlockOrRawAllocator>;
+
+            /// \returns The minimum block size required for a stack containing the given amount of memory.
+            /// If a stack is created with the result of `min_block_size(n)`, the resulting capacity will be exactly `n`.
+            /// \requires `byte_size` must be a positive number.
+            /// \note Due to debug fence sizes, the actual amount of usable memory can vary.
+            /// However, this is impossible to compute without knowing the exact allocation pattern before,
+            /// so this is just a rough estimate.
+            static constexpr std::size_t min_block_size(std::size_t byte_size) noexcept
+            {
+                return detail::memory_block_stack::implementation_offset() + byte_size;
+            }
+
+            /// \effects Creates it with a given initial block size and and other constructor arguments for the \concept{concept_blockallocator,BlockAllocator}.
+            /// It will allocate the first block and sets the top to its beginning.
+            /// \requires \c block_size must be at least \c min_block_size(1).
+            template <typename... Args>
+            explicit memory_stack(std::size_t block_size, Args&&... args)
+            : arena_(block_size, detail::forward<Args>(args)...),
+              stack_(arena_.allocate_block().memory)
+            {
+            }
+
+            /// \effects Allocates a memory block of given size and alignment.
+            /// It simply moves the top marker.
+            /// If there is not enough space on the current memory block,
+            /// a new one will be allocated by the \concept{concept_blockallocator,BlockAllocator} or taken from a cache
+            /// and used for the allocation.
+            /// \returns A \concept{concept_node,node} with given size and alignment.
+            /// \throws Anything thrown by the \concept{concept_blockallocator,BlockAllocator} on growth
+            /// or \ref bad_allocation_size if \c size is too big.
+            /// \requires \c size and \c alignment must be valid.
+            void* allocate(std::size_t size, std::size_t alignment)
+            {
+                auto fence  = detail::debug_fence_size;
+                auto offset = detail::align_offset(stack_.top() + fence, alignment);
+
+                if (!stack_.top()
+                    || fence + offset + size + fence > std::size_t(block_end() - stack_.top()))
+                {
+                    // need to grow
+                    auto block = arena_.allocate_block();
+                    stack_     = detail::fixed_memory_stack(block.memory);
+
+                    // new alignment required for over-aligned types
+                    offset = detail::align_offset(stack_.top() + fence, alignment);
+
+                    auto needed = fence + offset + size + fence;
+                    detail::check_allocation_size<bad_allocation_size>(needed, block.size, info());
+                }
+
+                return stack_.allocate_unchecked(size, offset);
+            }
+
+            /// \effects Allocates a memory block of given size and alignment,
+            /// similar to \ref allocate().
+            /// But it does not attempt a growth if the arena is empty.
+            /// \returns A \concept{concept_node,node} with given size and alignment
+            /// or `nullptr` if there wasn't enough memory available.
+            void* try_allocate(std::size_t size, std::size_t alignment) noexcept
+            {
+                return stack_.allocate(block_end(), size, alignment);
+            }
+
+            /// The marker type that is used for unwinding.
+            /// The exact type is implementation defined,
+            /// it is only required that it is efficiently copyable
+            /// and has all the comparision operators defined for two markers on the same stack.
+            /// Two markers are equal, if they are copies or created from two `top()` calls without a call to `unwind()` or `allocate()`.
+            /// A marker `a` is less than marker `b`, if after `a` was obtained, there was one or more call to `allocate()` and no call to `unwind()`.
+            using marker = WPI_IMPL_DEFINED(detail::stack_marker);
+
+            /// \returns A marker to the current top of the stack.
+            marker top() const noexcept
+            {
+                return {arena_.size() - 1, stack_, block_end()};
+            }
+
+            /// \effects Unwinds the stack to a certain marker position.
+            /// This sets the top pointer of the stack to the position described by the marker
+            /// and has the effect of deallocating all memory allocated since the marker was obtained.
+            /// If any memory blocks are unused after the operation,
+            /// they are not deallocated but put in a cache for later use,
+            /// call \ref shrink_to_fit() to actually deallocate them.
+            /// \requires The marker must point to memory that is still in use and was the whole time,
+            /// i.e. it must have been pointed below the top at all time.
+            void unwind(marker m) noexcept
+            {
+                WPI_MEMORY_ASSERT(m <= top());
+                detail::debug_check_pointer([&] { return m.index <= arena_.size() - 1; }, info(),
+                                            m.top);
+
+                if (std::size_t to_deallocate = (arena_.size() - 1) - m.index) // different index
+                {
+                    arena_.deallocate_block();
+                    for (std::size_t i = 1; i != to_deallocate; ++i)
+                        arena_.deallocate_block();
+
+                    detail::debug_check_pointer(
+                        [&] {
+                            auto cur = arena_.current_block();
+                            return m.end == static_cast<char*>(cur.memory) + cur.size;
+                        },
+                        info(), m.top);
+
+                    // mark memory from new top to end of the block as freed
+                    detail::debug_fill_free(m.top, std::size_t(m.end - m.top), 0);
+                    stack_ = detail::fixed_memory_stack(m.top);
+                }
+                else // same index
+                {
+                    detail::debug_check_pointer([&] { return stack_.top() >= m.top; }, info(),
+                                                m.top);
+                    stack_.unwind(m.top);
+                }
+            }
+
+            /// \effects \ref unwind() does not actually do any deallocation of blocks on the \concept{concept_blockallocator,BlockAllocator},
+            /// unused memory is stored in a cache for later reuse.
+            /// This function clears that cache.
+            void shrink_to_fit() noexcept
+            {
+                arena_.shrink_to_fit();
+            }
+
+            /// \returns The amount of memory remaining in the current block.
+            /// This is the number of bytes that are available for allocation
+            /// before the cache or \concept{concept_blockallocator,BlockAllocator} needs to be used.
+            std::size_t capacity_left() const noexcept
+            {
+                return std::size_t(block_end() - stack_.top());
+            }
+
+            /// \returns The size of the next memory block after the current block is exhausted and the arena grows.
+            /// This function just forwards to the \ref memory_arena.
+            /// \note All of it is available for the stack to use, but due to fences and alignment buffers,
+            /// this may not be the exact amount of memory usable for the user.
+            std::size_t next_capacity() const noexcept
+            {
+                return arena_.next_block_size();
+            }
+
+            /// \returns A reference to the \concept{concept_blockallocator,BlockAllocator} used for managing the arena.
+            /// \requires It is undefined behavior to move this allocator out into another object.
+            allocator_type& get_allocator() noexcept
+            {
+                return arena_.get_allocator();
+            }
+
+        private:
+            allocator_info info() const noexcept
+            {
+                return {WPI_MEMORY_LOG_PREFIX "::memory_stack", this};
+            }
+
+            const char* block_end() const noexcept
+            {
+                auto block = arena_.current_block();
+                return static_cast<const char*>(block.memory) + block.size;
+            }
+
+            memory_arena<allocator_type> arena_;
+            detail::fixed_memory_stack   stack_;
+
+            friend allocator_traits<memory_stack<BlockOrRawAllocator>>;
+            friend composable_allocator_traits<memory_stack<BlockOrRawAllocator>>;
+        };
+
+        /// Simple utility that automatically unwinds a `Stack` to a previously saved location.
+        /// A `Stack` is anything that provides a `marker`, a `top()` function returning a `marker`
+        /// and an `unwind()` function to unwind to a `marker`,
+        /// like a \ref wpi::memory::memory_stack
+        /// \ingroup allocator
+        template <class Stack = memory_stack<>>
+        class memory_stack_raii_unwind
+        {
+        public:
+            using stack_type  = Stack;
+            using marker_type = typename stack_type::marker;
+
+            /// \effects Same as `memory_stack_raii_unwind(stack, stack.top())`.
+            explicit memory_stack_raii_unwind(stack_type& stack) noexcept
+            : memory_stack_raii_unwind(stack, stack.top())
+            {
+            }
+
+            /// \effects Creates the unwinder by giving it the stack and the marker.
+            /// \requires The stack must live longer than this object.
+            memory_stack_raii_unwind(stack_type& stack, marker_type marker) noexcept
+            : marker_(marker), stack_(&stack)
+            {
+            }
+
+            /// \effects Move constructs the unwinder by taking the saved position from `other`.
+            /// `other.will_unwind()` will return `false` after it.
+            memory_stack_raii_unwind(memory_stack_raii_unwind&& other) noexcept
+            : marker_(other.marker_), stack_(other.stack_)
+            {
+                other.stack_ = nullptr;
+            }
+
+            /// \effects Unwinds to the previously saved location,
+            /// if there is any, by calling `unwind()`.
+            ~memory_stack_raii_unwind() noexcept
+            {
+                if (stack_)
+                    stack_->unwind(marker_);
+            }
+
+            /// \effects Move assigns the unwinder by taking the saved position from `other`.
+            /// `other.will_unwind()` will return `false` after it.
+            memory_stack_raii_unwind& operator=(memory_stack_raii_unwind&& other) noexcept
+            {
+                if (stack_)
+                    stack_->unwind(marker_);
+
+                marker_ = other.marker_;
+                stack_  = other.stack_;
+
+                other.stack_ = nullptr;
+
+                return *this;
+            }
+
+            /// \effects Removes the location without unwinding it.
+            /// `will_unwind()` will return `false`.
+            void release() noexcept
+            {
+                stack_ = nullptr;
+            }
+
+            /// \effects Unwinds to the saved location explictly.
+            /// \requires `will_unwind()` must return `true`.
+            void unwind() noexcept
+            {
+                WPI_MEMORY_ASSERT(will_unwind());
+                stack_->unwind(marker_);
+            }
+
+            /// \returns Whether or not the unwinder will actually unwind.
+            /// \note It will not unwind if it is in the moved-from state.
+            bool will_unwind() const noexcept
+            {
+                return stack_ != nullptr;
+            }
+
+            /// \returns The saved marker, if there is any.
+            /// \requires `will_unwind()` must return `true`.
+            marker_type get_marker() const noexcept
+            {
+                WPI_MEMORY_ASSERT(will_unwind());
+                return marker_;
+            }
+
+            /// \returns The stack it will unwind.
+            /// \requires `will_unwind()` must return `true`.
+            stack_type& get_stack() const noexcept
+            {
+                WPI_MEMORY_ASSERT(will_unwind());
+                return *stack_;
+            }
+
+        private:
+            marker_type marker_;
+            stack_type* stack_;
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class memory_stack<>;
+        extern template class memory_stack_raii_unwind<memory_stack<>>;
+#endif
+
+        /// Specialization of the \ref allocator_traits for \ref memory_stack classes.
+        /// \note It is not allowed to mix calls through the specialization and through the member functions,
+        /// i.e. \ref memory_stack::allocate() and this \c allocate_node().
+        /// \ingroup allocator
+        template <class BlockAllocator>
+        class allocator_traits<memory_stack<BlockAllocator>>
+        {
+        public:
+            using allocator_type = memory_stack<BlockAllocator>;
+            using is_stateful    = std::true_type;
+
+            /// \returns The result of \ref memory_stack::allocate().
+            static void* allocate_node(allocator_type& state, std::size_t size,
+                                       std::size_t alignment)
+            {
+                auto mem = state.allocate(size, alignment);
+                state.on_allocate(size);
+                return mem;
+            }
+
+            /// \returns The result of \ref memory_stack::allocate().
+            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size,
+                                        std::size_t alignment)
+            {
+                return allocate_node(state, count * size, alignment);
+            }
+
+            /// @{
+            /// \effects Does nothing besides bookmarking for leak checking, if that is enabled.
+            /// Actual deallocation can only be done via \ref memory_stack::unwind().
+            static void deallocate_node(allocator_type& state, void*, std::size_t size,
+                                        std::size_t) noexcept
+            {
+                state.on_deallocate(size);
+            }
+
+            static void deallocate_array(allocator_type& state, void* ptr, std::size_t count,
+                                         std::size_t size, std::size_t alignment) noexcept
+            {
+                deallocate_node(state, ptr, count * size, alignment);
+            }
+            /// @}
+
+            /// @{
+            /// \returns The maximum size which is \ref memory_stack::next_capacity().
+            static std::size_t max_node_size(const allocator_type& state) noexcept
+            {
+                return state.next_capacity();
+            }
+
+            static std::size_t max_array_size(const allocator_type& state) noexcept
+            {
+                return state.next_capacity();
+            }
+            /// @}
+
+            /// \returns The maximum possible value since there is no alignment restriction
+            /// (except indirectly through \ref memory_stack::next_capacity()).
+            static std::size_t max_alignment(const allocator_type&) noexcept
+            {
+                return std::size_t(-1);
+            }
+        };
+
+        /// Specialization of the \ref composable_allocator_traits for \ref memory_stack classes.
+        /// \ingroup allocator
+        template <class BlockAllocator>
+        class composable_allocator_traits<memory_stack<BlockAllocator>>
+        {
+        public:
+            using allocator_type = memory_stack<BlockAllocator>;
+
+            /// \returns The result of \ref memory_stack::try_allocate().
+            static void* try_allocate_node(allocator_type& state, std::size_t size,
+                                           std::size_t alignment) noexcept
+            {
+                return state.try_allocate(size, alignment);
+            }
+
+            /// \returns The result of \ref memory_stack::try_allocate().
+            static void* try_allocate_array(allocator_type& state, std::size_t count,
+                                            std::size_t size, std::size_t alignment) noexcept
+            {
+                return state.try_allocate(count * size, alignment);
+            }
+
+            /// @{
+            /// \effects Does nothing.
+            /// \returns Whether the memory will be deallocated by \ref memory_stack::unwind().
+            static bool try_deallocate_node(allocator_type& state, void* ptr, std::size_t,
+                                            std::size_t) noexcept
+            {
+                return state.arena_.owns(ptr);
+            }
+
+            static bool try_deallocate_array(allocator_type& state, void* ptr, std::size_t count,
+                                             std::size_t size, std::size_t alignment) noexcept
+            {
+                return try_deallocate_node(state, ptr, count * size, alignment);
+            }
+            /// @}
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class allocator_traits<memory_stack<>>;
+        extern template class composable_allocator_traits<memory_stack<>>;
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_MEMORY_STACK_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/namespace_alias.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/namespace_alias.hpp
new file mode 100644
index 0000000..bf2b95d
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/namespace_alias.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_NAMESPACE_ALIAS_HPP_INCLUDED
+#define WPI_MEMORY_NAMESPACE_ALIAS_HPP_INCLUDED
+
+/// \file
+/// Convenient namespace alias.
+
+/// \defgroup core Core components
+
+/// \defgroup allocator Allocator implementations
+
+/// \defgroup adapter Adapters and Wrappers
+
+/// \defgroup storage Allocator storage
+
+/// \namespace wpi
+/// Foonathan namespace.
+
+/// \namespace wpi::memory
+/// Memory namespace.
+
+/// \namespace wpi::memory::literals
+/// Literals namespace.
+
+namespace wpi
+{
+    namespace memory
+    {
+    }
+} // namespace wpi
+
+namespace memory = wpi::memory;
+
+#endif // WPI_MEMORY_NAMESPACE_ALIAS_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/new_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/new_allocator.hpp
new file mode 100644
index 0000000..8e24f2f
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/new_allocator.hpp
@@ -0,0 +1,55 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_NEW_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_NEW_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::new_allocator.
+
+#include "detail/lowlevel_allocator.hpp"
+#include "config.hpp"
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+#include "allocator_traits.hpp"
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        struct allocator_info;
+
+        namespace detail
+        {
+            struct new_allocator_impl
+            {
+                static allocator_info info() noexcept;
+
+                static void* allocate(std::size_t size, std::size_t) noexcept;
+
+                static void deallocate(void* ptr, std::size_t size, std::size_t) noexcept;
+
+                static std::size_t max_node_size() noexcept;
+            };
+
+            WPI_MEMORY_LL_ALLOCATOR_LEAK_CHECKER(new_allocator_impl,
+                                                       new_alloator_leak_checker)
+        } // namespace detail
+
+        /// A stateless \concept{concept_rawallocator,RawAllocator} that allocates memory using (nothrow) <tt>operator new</tt>.
+        /// If the operator returns \c nullptr, it behaves like \c new and loops calling \c std::new_handler,
+        /// but instead of throwing a \c std::bad_alloc exception, it throws \ref out_of_memory.
+        /// \ingroup allocator
+        using new_allocator =
+            WPI_IMPL_DEFINED(detail::lowlevel_allocator<detail::new_allocator_impl>);
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class detail::lowlevel_allocator<detail::new_allocator_impl>;
+        extern template class allocator_traits<new_allocator>;
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_NEW_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/segregator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/segregator.hpp
new file mode 100644
index 0000000..fcd02ac
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/segregator.hpp
@@ -0,0 +1,448 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_SEGREGATOR_HPP_INCLUDED
+#define WPI_MEMORY_SEGREGATOR_HPP_INCLUDED
+
+/// \file
+/// Class template \ref wpi::memory::segregator and related classes.
+
+#include "detail/ebo_storage.hpp"
+#include "detail/utility.hpp"
+#include "allocator_traits.hpp"
+#include "config.hpp"
+#include "error.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// A \concept{concept_segregatable,Segregatable} that allocates until a maximum size.
+        /// \ingroup adapter
+        template <class RawAllocator>
+        class threshold_segregatable : WPI_EBO(allocator_traits<RawAllocator>::allocator_type)
+        {
+        public:
+            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;
+
+            /// \effects Creates it by passing the maximum size it will allocate
+            /// and the allocator it uses.
+            explicit threshold_segregatable(std::size_t    max_size,
+                                            allocator_type alloc = allocator_type())
+            : allocator_type(detail::move(alloc)), max_size_(max_size)
+            {
+            }
+
+            /// \returns `true` if `size` is less then or equal to the maximum size,
+            /// `false` otherwise.
+            /// \note A return value of `true` means that the allocator will be used for the allocation.
+            bool use_allocate_node(std::size_t size, std::size_t) noexcept
+            {
+                return size <= max_size_;
+            }
+
+            /// \returns `true` if `count * size` is less then or equal to the maximum size,
+            /// `false` otherwise.
+            /// \note A return value of `true` means that the allocator will be used for the allocation.
+            bool use_allocate_array(std::size_t count, std::size_t size, std::size_t) noexcept
+            {
+                return count * size <= max_size_;
+            }
+
+            /// @{
+            /// \returns A reference to the allocator it owns.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+            const allocator_type& get_allocator() const noexcept
+            {
+                return *this;
+            }
+            /// @}
+
+        private:
+            std::size_t max_size_;
+        };
+
+        /// \returns A \ref threshold_segregatable with the same parameter.
+        template <class RawAllocator>
+        threshold_segregatable<typename std::decay<RawAllocator>::type> threshold(
+            std::size_t max_size, RawAllocator&& alloc)
+        {
+            return threshold_segregatable<
+                typename std::decay<RawAllocator>::type>(max_size,
+                                                         std::forward<RawAllocator>(alloc));
+        }
+
+        /// A composable \concept{concept_rawallocator,RawAllocator} that will always fail.
+        /// This is useful for compositioning or as last resort in \ref binary_segregator.
+        /// \ingroup allocator
+        class null_allocator
+        {
+        public:
+            /// \effects Will always throw.
+            /// \throws A \ref out_of_fixed_memory exception.
+            void* allocate_node(std::size_t size, std::size_t)
+            {
+                throw out_of_fixed_memory(info(), size);
+            }
+
+            /// \requires Must not be called.
+            void deallocate_node(void*, std::size_t, std::size_t) noexcept
+            {
+                WPI_MEMORY_UNREACHABLE("cannot be called with proper values");
+            }
+
+            /// \effects Does nothing.
+            /// \returns Always returns `nullptr`.
+            void* try_allocate_node(std::size_t, std::size_t) noexcept
+            {
+                return nullptr;
+            }
+
+            /// \effects Does nothing.
+            /// \returns Always returns `false`.
+            bool try_deallocate_node(void*, std::size_t, std::size_t) noexcept
+            {
+                return false;
+            }
+
+        private:
+            allocator_info info() const noexcept
+            {
+                return {WPI_MEMORY_LOG_PREFIX "::null_allocator", this};
+            }
+        };
+
+        /// A \concept{concept_rawallocator,RawAllocator} that either uses the \concept{concept_segregatable,Segregatable} or the other `RawAllocator`.
+        /// It is a faster alternative to \ref fallback_allocator that doesn't require a composable allocator
+        /// and decides about the allocator to use purely with the `Segregatable` based on size and alignment.
+        /// \ingroup adapter
+        template <class Segregatable, class RawAllocator>
+        class binary_segregator
+        : WPI_EBO(
+              detail::ebo_storage<1, typename allocator_traits<RawAllocator>::allocator_type>)
+        {
+            using segregatable_traits = allocator_traits<typename Segregatable::allocator_type>;
+            using fallback_traits     = allocator_traits<RawAllocator>;
+
+        public:
+            using segregatable                = Segregatable;
+            using segregatable_allocator_type = typename segregatable::allocator_type;
+            using fallback_allocator_type = typename allocator_traits<RawAllocator>::allocator_type;
+
+            /// \effects Creates it by giving the \concept{concept_segregatable,Segregatable}
+            /// and the \concept{concept_rawallocator,RawAllocator}.
+            explicit binary_segregator(segregatable            s,
+                                       fallback_allocator_type fallback = fallback_allocator_type())
+            : detail::ebo_storage<1, fallback_allocator_type>(detail::move(fallback)),
+              s_(detail::move(s))
+            {
+            }
+
+            /// @{
+            /// \effects Uses the \concept{concept_segregatable,Segregatable} to decide which allocator to use.
+            /// Then forwards to the chosen allocator.
+            void* allocate_node(std::size_t size, std::size_t alignment)
+            {
+                if (get_segregatable().use_allocate_node(size, alignment))
+                    return segregatable_traits::allocate_node(get_segregatable_allocator(), size,
+                                                              alignment);
+                else
+                    return fallback_traits::allocate_node(get_fallback_allocator(), size,
+                                                          alignment);
+            }
+
+            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                if (get_segregatable().use_allocate_node(size, alignment))
+                    segregatable_traits::deallocate_node(get_segregatable_allocator(), ptr, size,
+                                                         alignment);
+                else
+                    fallback_traits::deallocate_node(get_fallback_allocator(), ptr, size,
+                                                     alignment);
+            }
+
+            void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)
+            {
+                if (get_segregatable().use_allocate_array(count, size, alignment))
+                    return segregatable_traits::allocate_array(get_segregatable_allocator(), count,
+                                                               size, alignment);
+                else
+                    return fallback_traits::allocate_array(get_fallback_allocator(), count, size,
+                                                           alignment);
+            }
+
+            void deallocate_array(void* array, std::size_t count, std::size_t size,
+                                  std::size_t alignment) noexcept
+            {
+                if (get_segregatable().use_allocate_array(count, size, alignment))
+                    segregatable_traits::deallocate_array(get_segregatable_allocator(), array,
+                                                          count, size, alignment);
+                else
+                    fallback_traits::deallocate_array(get_fallback_allocator(), array, count, size,
+                                                      alignment);
+            }
+            /// @}
+
+            /// @{
+            /// \returns The maximum value of the fallback.
+            /// \note It assumes that the fallback will be used for larger allocations,
+            /// and the `Segregatable` for smaller ones.
+            std::size_t max_node_size() const
+            {
+                return fallback_traits::max_node_size(get_fallback_allocator());
+            }
+
+            std::size_t max_array_size() const
+            {
+                return fallback_traits::max_array_size(get_fallback_allocator());
+            }
+
+            std::size_t max_alignemnt() const
+            {
+                return fallback_traits::max_alignment(get_fallback_allocator());
+            }
+            /// @}
+
+            /// @{
+            /// \returns A reference to the segregatable allocator.
+            /// This is the one primarily used.
+            segregatable_allocator_type& get_segregatable_allocator() noexcept
+            {
+                return get_segregatable().get_allocator();
+            }
+
+            const segregatable_allocator_type& get_segregatable_allocator() const noexcept
+            {
+                return get_segregatable().get_allocator();
+            }
+            /// @}
+
+            /// @{
+            /// \returns A reference to the fallback allocator.
+            /// It will be used if the \concept{concept_segregator,Segregator} doesn't want the alloction.
+            fallback_allocator_type& get_fallback_allocator() noexcept
+            {
+                return detail::ebo_storage<1, fallback_allocator_type>::get();
+            }
+
+            const fallback_allocator_type& get_fallback_allocator() const noexcept
+            {
+                return detail::ebo_storage<1, fallback_allocator_type>::get();
+            }
+            /// @}
+
+        private:
+            segregatable& get_segregatable() noexcept
+            {
+                return s_;
+            }
+
+            segregatable s_;
+        };
+
+        namespace detail
+        {
+            template <class... Segregatables>
+            struct make_segregator_t;
+
+            template <class Segregatable>
+            struct make_segregator_t<Segregatable>
+            {
+                using type = binary_segregator<Segregatable, null_allocator>;
+            };
+
+            template <class Segregatable, class RawAllocator>
+            struct make_segregator_t<Segregatable, RawAllocator>
+            {
+                using type = binary_segregator<Segregatable, RawAllocator>;
+            };
+
+            template <class Segregatable, class... Tail>
+            struct make_segregator_t<Segregatable, Tail...>
+            {
+                using type =
+                    binary_segregator<Segregatable, typename make_segregator_t<Tail...>::type>;
+            };
+
+            template <class Segregator, class Fallback = null_allocator>
+            auto make_segregator(Segregator&& seg, Fallback&& f = null_allocator{})
+                -> binary_segregator<typename std::decay<Segregator>::type,
+                                     typename std::decay<Fallback>::type>
+            {
+                return binary_segregator<
+                    typename std::decay<Segregator>::type,
+                    typename std::decay<Fallback>::type>(std::forward<Segregator>(seg),
+                                                         std::forward<Fallback>(f));
+            }
+
+            template <class Segregator, typename... Rest>
+            auto make_segregator(Segregator&& seg, Rest&&... rest)
+                -> binary_segregator<typename std::decay<Segregator>::type,
+                                     decltype(make_segregator(std::forward<Rest>(rest)...))>
+            {
+                return binary_segregator<typename std::decay<Segregator>::type,
+                                         decltype(make_segregator(std::forward<Rest>(
+                                             rest)...))>(std::forward<Segregator>(seg),
+                                                         make_segregator(
+                                                             std::forward<Rest>(rest)...));
+            }
+
+            template <std::size_t I, class Segregator>
+            struct segregatable_type;
+
+            template <class Segregator, class Fallback>
+            struct segregatable_type<0, binary_segregator<Segregator, Fallback>>
+            {
+                using type = typename Segregator::allocator_type;
+
+                static type& get(binary_segregator<Segregator, Fallback>& s)
+                {
+                    return s.get_segregatable_allocator();
+                }
+
+                static const type& get(const binary_segregator<Segregator, Fallback>& s)
+                {
+                    return s.get_segregatable_allocator();
+                }
+            };
+
+            template <std::size_t I, class Segregator, class Fallback>
+            struct segregatable_type<I, binary_segregator<Segregator, Fallback>>
+            {
+                using base = segregatable_type<I - 1, Fallback>;
+                using type = typename base::type;
+
+                static type& get(binary_segregator<Segregator, Fallback>& s)
+                {
+                    return base::get(s.get_fallback_allocator());
+                }
+
+                static const type& get(const binary_segregator<Segregator, Fallback>& s)
+                {
+                    return base::get(s.get_fallback_allocator());
+                }
+            };
+
+            template <class Fallback>
+            struct fallback_type
+            {
+                using type = Fallback;
+
+                static const std::size_t size = 0u;
+
+                static type& get(Fallback& f)
+                {
+                    return f;
+                }
+
+                static const type& get(const Fallback& f)
+                {
+                    return f;
+                }
+            };
+
+            template <class Segregator, class Fallback>
+            struct fallback_type<binary_segregator<Segregator, Fallback>>
+            {
+                using base = fallback_type<Fallback>;
+                using type = typename base::type;
+
+                static const std::size_t size = base::size + 1u;
+
+                static type& get(binary_segregator<Segregator, Fallback>& s)
+                {
+                    return base::get(s.get_fallback_allocator());
+                }
+
+                static const type& get(const binary_segregator<Segregator, Fallback>& s)
+                {
+                    return base::get(s.get_fallback_allocator());
+                }
+            };
+        } // namespace detail
+
+        /// Creates multiple nested \ref binary_segregator.
+        /// If you pass one type, it must be a \concept{concept_segregatable,Segregatable}.
+        /// Then the result is a \ref binary_segregator with that `Segregatable` and \ref null_allocator as fallback.
+        /// If you pass two types, the first one must be a `Segregatable`,
+        /// the second one a \concept{concept_rawallocator,RawAllocator}.
+        /// Then the result is a simple \ref binary_segregator with those arguments.
+        /// If you pass more than one, the last one must be a `RawAllocator` all others `Segregatable`,
+        /// the result is `binary_segregator<Head, segregator<Tail...>>`.
+        /// \note It will result in an allocator that tries each `Segregatable` in the order specified
+        /// using the last parameter as final fallback.
+        /// \ingroup adapter
+        template <class... Allocators>
+        WPI_ALIAS_TEMPLATE(segregator,
+                                 typename detail::make_segregator_t<Allocators...>::type);
+
+        /// \returns A \ref segregator created from the allocators `args`.
+        /// \relates segregator
+        template <typename... Args>
+        auto make_segregator(Args&&... args) -> segregator<typename std::decay<Args>::type...>
+        {
+            return detail::make_segregator(std::forward<Args>(args)...);
+        }
+
+        /// The number of \concept{concept_segregatable,Segregatable} a \ref segregator has.
+        /// \relates segregator
+        template <class Segregator>
+        struct segregator_size
+        {
+            static const std::size_t value = detail::fallback_type<Segregator>::size;
+        };
+
+        /// The type of the `I`th \concept{concept_segregatable,Segregatable}.
+        /// \relates segregator
+        template <std::size_t I, class Segregator>
+        using segregatable_allocator_type = typename detail::segregatable_type<I, Segregator>::type;
+
+        /// @{
+        /// \returns The `I`th \concept{concept_segregatable,Segregatable}.
+        /// \relates segregrator
+        template <std::size_t I, class Segregator, class Fallback>
+        auto get_segregatable_allocator(binary_segregator<Segregator, Fallback>& s)
+            -> segregatable_allocator_type<I, binary_segregator<Segregator, Fallback>>&
+        {
+            return detail::segregatable_type<I, binary_segregator<Segregator, Fallback>>::get(s);
+        }
+
+        template <std::size_t I, class Segregator, class Fallback>
+        auto get_segregatable_allocator(const binary_segregator<Segregator, Fallback>& s)
+            -> const segregatable_allocator_type<I, binary_segregator<Segregator, Fallback>>
+        {
+            return detail::segregatable_type<I, binary_segregator<Segregator, Fallback>>::get(s);
+        }
+        /// @}
+
+        /// The type of the final fallback \concept{concept_rawallocator,RawAllocator}.
+        /// \relates segregator
+        template <class Segregator>
+        using fallback_allocator_type = typename detail::fallback_type<Segregator>::type;
+
+        /// @{
+        /// \returns The final fallback \concept{concept_rawallocator,RawAllocator}.
+        /// \relates segregator
+        template <class Segregator, class Fallback>
+        auto get_fallback_allocator(binary_segregator<Segregator, Fallback>& s)
+            -> fallback_allocator_type<binary_segregator<Segregator, Fallback>>&
+        {
+            return detail::fallback_type<binary_segregator<Segregator, Fallback>>::get(s);
+        }
+
+        template <class Segregator, class Fallback>
+        auto get_fallback_allocator(const binary_segregator<Segregator, Fallback>& s)
+            -> const fallback_allocator_type<binary_segregator<Segregator, Fallback>>&
+        {
+            return detail::fallback_type<binary_segregator<Segregator, Fallback>>::get(s);
+        }
+        /// @}
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_SEGREGATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/smart_ptr.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/smart_ptr.hpp
new file mode 100644
index 0000000..877efd7
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/smart_ptr.hpp
@@ -0,0 +1,210 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_SMART_PTR_HPP_INCLUDED
+#define WPI_MEMORY_SMART_PTR_HPP_INCLUDED
+
+/// \file
+/// \c std::make_unique() / \c std::make_shared() replacement allocating memory through a \concept{concept_rawallocator,RawAllocator}.
+/// \note Only available on a hosted implementation.
+
+#include "config.hpp"
+#if !WPI_HOSTED_IMPLEMENTATION
+#error "This header is only available for a hosted implementation."
+#endif
+
+#include <memory>
+#include <type_traits>
+
+#include "detail/utility.hpp"
+#include "deleter.hpp"
+#include "std_allocator.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            template <typename T, class RawAllocator, typename... Args>
+            auto allocate_unique(allocator_reference<RawAllocator> alloc, Args&&... args)
+                -> std::unique_ptr<T, allocator_deleter<T, RawAllocator>>
+            {
+                using raw_ptr = std::unique_ptr<T, allocator_deallocator<T, RawAllocator>>;
+
+                auto memory = alloc.allocate_node(sizeof(T), alignof(T));
+                // raw_ptr deallocates memory in case of constructor exception
+                raw_ptr result(static_cast<T*>(memory), {alloc});
+                // call constructor
+                ::new (memory) T(detail::forward<Args>(args)...);
+                // pass ownership to return value using a deleter that calls destructor
+                return {result.release(), {alloc}};
+            }
+
+            template <typename T, typename... Args>
+            void construct(std::true_type, T* cur, T* end, Args&&... args)
+            {
+                for (; cur != end; ++cur)
+                    ::new (static_cast<void*>(cur)) T(detail::forward<Args>(args)...);
+            }
+
+            template <typename T, typename... Args>
+            void construct(std::false_type, T* begin, T* end, Args&&... args)
+            {
+#if WPI_HAS_EXCEPTION_SUPPORT
+                auto cur = begin;
+                try
+                {
+                    for (; cur != end; ++cur)
+                        ::new (static_cast<void*>(cur)) T(detail::forward<Args>(args)...);
+                }
+                catch (...)
+                {
+                    for (auto el = begin; el != cur; ++el)
+                        el->~T();
+                    throw;
+                }
+#else
+                construct(std::true_type{}, begin, end, detail::forward<Args>(args)...);
+#endif
+            }
+
+            template <typename T, class RawAllocator>
+            auto allocate_array_unique(std::size_t size, allocator_reference<RawAllocator> alloc)
+                -> std::unique_ptr<T[], allocator_deleter<T[], RawAllocator>>
+            {
+                using raw_ptr = std::unique_ptr<T[], allocator_deallocator<T[], RawAllocator>>;
+
+                auto memory = alloc.allocate_array(size, sizeof(T), alignof(T));
+                // raw_ptr deallocates memory in case of constructor exception
+                raw_ptr result(static_cast<T*>(memory), {alloc, size});
+                construct(std::integral_constant<bool, noexcept(T())>{}, result.get(),
+                          result.get() + size);
+                // pass ownership to return value using a deleter that calls destructor
+                return {result.release(), {alloc, size}};
+            }
+        } // namespace detail
+
+        /// A \c std::unique_ptr that deletes using a \concept{concept_rawallocator,RawAllocator}.
+        ///
+        /// It is an alias template using \ref allocator_deleter as \c Deleter class.
+        /// \ingroup adapter
+        template <typename T, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(unique_ptr,
+                                 std::unique_ptr<T, allocator_deleter<T, RawAllocator>>);
+
+        /// A \c std::unique_ptr that deletes using a \concept{concept_rawallocator,RawAllocator} and allows polymorphic types.
+        ///
+        /// It can only be created by converting a regular unique pointer to a pointer to a derived class,
+        /// and is meant to be used inside containers.
+        /// It is an alias template using \ref allocator_polymorphic_deleter as \c Deleter class.
+        /// \note It has a relatively high overhead, so only use it if you have to.
+        /// \ingroup adapter
+        template <class BaseType, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            unique_base_ptr,
+            std::unique_ptr<BaseType, allocator_polymorphic_deleter<BaseType, RawAllocator>>);
+
+        /// Creates a \c std::unique_ptr using a \concept{concept_rawallocator,RawAllocator} for the allocation.
+        /// \effects Allocates memory for the given type using the allocator
+        /// and creates a new object inside it passing the given arguments to its constructor.
+        /// \returns A \c std::unique_ptr owning that memory.
+        /// \note If the allocator is stateful a reference to the \c RawAllocator will be stored inside the deleter,
+        /// the caller has to ensure that the object lives as long as the smart pointer.
+        /// \ingroup adapter
+        template <typename T, class RawAllocator, typename... Args>
+        auto allocate_unique(RawAllocator&& alloc, Args&&... args) -> WPI_REQUIRES_RET(
+            !std::is_array<T>::value,
+            std::unique_ptr<T, allocator_deleter<T, typename std::decay<RawAllocator>::type>>)
+        {
+            return detail::allocate_unique<T>(make_allocator_reference(
+                                                  detail::forward<RawAllocator>(alloc)),
+                                              detail::forward<Args>(args)...);
+        }
+
+        /// Creates a \c std::unique_ptr using a type-erased \concept{concept_rawallocator,RawAllocator} for the allocation.
+        /// It is the same as the other overload but stores the reference to the allocator type-erased inside the \c std::unique_ptr.
+        /// \effects Allocates memory for the given type using the allocator
+        /// and creates a new object inside it passing the given arguments to its constructor.
+        /// \returns A \c std::unique_ptr with a type-erased allocator reference owning that memory.
+        /// \note If the allocator is stateful a reference to the \c RawAllocator will be stored inside the deleter,
+        /// the caller has to ensure that the object lives as long as the smart pointer.
+        /// \ingroup adapter
+        template <typename T, class RawAllocator, typename... Args>
+        auto allocate_unique(any_allocator, RawAllocator&& alloc, Args&&... args)
+            -> WPI_REQUIRES_RET(!std::is_array<T>::value,
+                                      std::unique_ptr<T, allocator_deleter<T, any_allocator>>)
+        {
+            return detail::allocate_unique<T, any_allocator>(make_allocator_reference(
+                                                                 detail::forward<RawAllocator>(
+                                                                     alloc)),
+                                                             detail::forward<Args>(args)...);
+        }
+
+        /// Creates a \c std::unique_ptr owning an array using a \concept{concept_rawallocator,RawAllocator} for the allocation.
+        /// \effects Allocates memory for an array of given size and value initializes each element inside of it.
+        /// \returns A \c std::unique_ptr owning that array.
+        /// \note If the allocator is stateful a reference to the \c RawAllocator will be stored inside the deleter,
+        /// the caller has to ensure that the object lives as long as the smart pointer.
+        /// \ingroup adapter
+        template <typename T, class RawAllocator>
+        auto allocate_unique(RawAllocator&& alloc, std::size_t size) -> WPI_REQUIRES_RET(
+            std::is_array<T>::value,
+            std::unique_ptr<T, allocator_deleter<T, typename std::decay<RawAllocator>::type>>)
+        {
+            return detail::allocate_array_unique<
+                typename std::remove_extent<T>::type>(size,
+                                                      make_allocator_reference(
+                                                          detail::forward<RawAllocator>(alloc)));
+        }
+
+        /// Creates a \c std::unique_ptr owning an array using a type-erased \concept{concept_rawallocator,RawAllocator} for the allocation.
+        /// It is the same as the other overload but stores the reference to the allocator type-erased inside the \c std::unique_ptr.
+        /// \effects Allocates memory for an array of given size and value initializes each element inside of it.
+        /// \returns A \c std::unique_ptr with a type-erased allocator reference owning that array.
+        /// \note If the allocator is stateful a reference to the \c RawAllocator will be stored inside the deleter,
+        /// the caller has to ensure that the object lives as long as the smart pointer.
+        /// \ingroup adapter
+        template <typename T, class RawAllocator>
+        auto allocate_unique(any_allocator, RawAllocator&& alloc, std::size_t size)
+            -> WPI_REQUIRES_RET(std::is_array<T>::value,
+                                      std::unique_ptr<T, allocator_deleter<T, any_allocator>>)
+        {
+            return detail::allocate_array_unique<typename std::remove_extent<T>::type,
+                                                 any_allocator>(size,
+                                                                make_allocator_reference(
+                                                                    detail::forward<RawAllocator>(
+                                                                        alloc)));
+        }
+
+        /// Creates a \c std::shared_ptr using a \concept{concept_rawallocator,RawAllocator} for the allocation.
+        /// It is similar to \c std::allocate_shared but uses a \c RawAllocator (and thus also supports any \c Allocator).
+        /// \effects Calls \ref std_allocator::make_std_allocator to wrap the allocator and forwards to \c std::allocate_shared.
+        /// \returns A \c std::shared_ptr created using \c std::allocate_shared.
+        /// \note If the allocator is stateful a reference to the \c RawAllocator will be stored inside the shared pointer,
+        /// the caller has to ensure that the object lives as long as the smart pointer.
+        /// \ingroup adapter
+        template <typename T, class RawAllocator, typename... Args>
+        std::shared_ptr<T> allocate_shared(RawAllocator&& alloc, Args&&... args)
+        {
+            return std::allocate_shared<T>(make_std_allocator<T>(
+                                               detail::forward<RawAllocator>(alloc)),
+                                           detail::forward<Args>(args)...);
+        }
+
+#if !defined(DOXYGEN)
+#include "detail/container_node_sizes.hpp"
+#else
+        /// Contains the node size needed for a `std::shared_ptr`.
+        /// These classes are auto-generated and only available if the tools are build and without cross-compiling.
+        /// \ingroup adapter
+        template <typename T>
+        struct shared_ptr_node_size : std::integral_constant<std::size_t, implementation_defined>
+        {
+        };
+#endif
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_SMART_PTR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/static_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/static_allocator.hpp
new file mode 100644
index 0000000..efbbf73
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/static_allocator.hpp
@@ -0,0 +1,179 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_STATIC_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_STATIC_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Allocators using a static, fixed-sized storage.
+
+#include <type_traits>
+
+#include "detail/align.hpp"
+#include "detail/assert.hpp"
+#include "detail/memory_stack.hpp"
+#include "detail/utility.hpp"
+#include "config.hpp"
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+#include "allocator_traits.hpp"
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// Storage for a \ref static_allocator.
+        /// Its constructor will take a reference to it and use it for its allocation.
+        /// The storage type is simply a \c char array aligned for maximum alignment.
+        /// \note It is not allowed to access the memory of the storage.
+        /// \ingroup allocator
+        template <std::size_t Size>
+        struct static_allocator_storage
+        {
+            alignas(detail::max_alignment) char storage[Size];
+        };
+
+        static_assert(sizeof(static_allocator_storage<1024>) == 1024, "");
+        static_assert(alignof(static_allocator_storage<1024>) == detail::max_alignment, "");
+
+        struct allocator_info;
+
+        /// A stateful \concept{concept_rawallocator,RawAllocator} that uses a fixed sized storage for the allocations.
+        /// It works on a \ref static_allocator_storage and uses its memory for all allocations.
+        /// Deallocations are not supported, memory cannot be marked as freed.<br>
+        /// \note It is not allowed to share an \ref static_allocator_storage between multiple \ref static_allocator objects.
+        /// \ingroup allocator
+        class static_allocator
+        {
+        public:
+            using is_stateful = std::true_type;
+
+            /// \effects Creates it by passing it a \ref static_allocator_storage by reference.
+            /// It will take the address of the storage and use its memory for the allocation.
+            /// \requires The storage object must live as long as the allocator object.
+            /// It must not be shared between multiple allocators,
+            /// i.e. the object must not have been passed to a constructor before.
+            template <std::size_t Size>
+            static_allocator(static_allocator_storage<Size>& storage) noexcept
+            : stack_(&storage), end_(stack_.top() + Size)
+            {
+            }
+
+            /// \effects A \concept{concept_rawallocator,RawAllocator} allocation function.
+            /// It uses the specified \ref static_allocator_storage.
+            /// \returns A pointer to a \concept{concept_node,node}, it will never be \c nullptr.
+            /// \throws An exception of type \ref out_of_memory or whatever is thrown by its handler if the storage is exhausted.
+            void* allocate_node(std::size_t size, std::size_t alignment);
+
+            /// \effects A \concept{concept_rawallocator,RawAllocator} deallocation function.
+            /// It does nothing, deallocation is not supported by this allocator.
+            void deallocate_node(void*, std::size_t, std::size_t) noexcept {}
+
+            /// \returns The maximum node size which is the capacity remaining inside the \ref static_allocator_storage.
+            std::size_t max_node_size() const noexcept
+            {
+                return static_cast<std::size_t>(end_ - stack_.top());
+            }
+
+            /// \returns The maximum possible value since there is no alignment restriction
+            /// (except indirectly through the size of the \ref static_allocator_storage).
+            std::size_t max_alignment() const noexcept
+            {
+                return std::size_t(-1);
+            }
+
+        private:
+            allocator_info info() const noexcept;
+
+            detail::fixed_memory_stack stack_;
+            const char*                end_;
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class allocator_traits<static_allocator>;
+#endif
+
+        struct memory_block;
+
+        /// A \concept{concept_blockallocator,BlockAllocator} that allocates the blocks from a fixed size storage.
+        /// It works on a \ref static_allocator_storage and uses it for all allocations,
+        /// deallocations are only allowed in reversed order which is guaranteed by \ref memory_arena.
+        /// \note It is not allowed to share an \ref static_allocator_storage between multiple \ref static_allocator objects.
+        /// \ingroup allocator
+        class static_block_allocator
+        {
+        public:
+            /// \effects Creates it by passing it the block size and a \ref static_allocator_storage by reference.
+            /// It will take the address of the storage and use it to allocate \c block_size'd blocks.
+            /// \requires The storage object must live as long as the allocator object.
+            /// It must not be shared between multiple allocators,
+            /// i.e. the object must not have been passed to a constructor before.
+            /// The size of the \ref static_allocator_storage must be a multiple of the (non-null) block size.
+            template <std::size_t Size>
+            static_block_allocator(std::size_t                     block_size,
+                                   static_allocator_storage<Size>& storage) noexcept
+            : cur_(static_cast<char*>(static_cast<void*>(&storage))),
+              end_(cur_ + Size),
+              block_size_(block_size)
+            {
+                WPI_MEMORY_ASSERT(block_size <= Size);
+                WPI_MEMORY_ASSERT(Size % block_size == 0u);
+            }
+
+            ~static_block_allocator() noexcept = default;
+
+            /// @{
+            /// \effects Moves the block allocator, it transfers ownership over the \ref static_allocator_storage.
+            /// This does not invalidate any memory blocks.
+            static_block_allocator(static_block_allocator&& other) noexcept
+            : cur_(other.cur_), end_(other.end_), block_size_(other.block_size_)
+            {
+                other.cur_ = other.end_ = nullptr;
+                other.block_size_       = 0;
+            }
+
+            static_block_allocator& operator=(static_block_allocator&& other) noexcept
+            {
+                static_block_allocator tmp(detail::move(other));
+                swap(*this, tmp);
+                return *this;
+            }
+            /// @}
+
+            /// \effects Swaps the ownership over the \ref static_allocator_storage.
+            /// This does not invalidate any memory blocks.
+            friend void swap(static_block_allocator& a, static_block_allocator& b) noexcept
+            {
+                detail::adl_swap(a.cur_, b.cur_);
+                detail::adl_swap(a.end_, b.end_);
+                detail::adl_swap(a.block_size_, b.block_size_);
+            }
+
+            /// \effects Allocates a new block by returning the \ref next_block_size() bytes.
+            /// \returns The new memory block.
+            memory_block allocate_block();
+
+            /// \effects Deallocates the last memory block by marking the block as free again.
+            /// This block will be returned again by the next call to \ref allocate_block().
+            /// \requires \c block must be the current top block of the memory,
+            /// this is guaranteed by \ref memory_arena.
+            void deallocate_block(memory_block block) noexcept;
+
+            /// \returns The next block size, this is the size passed to the constructor.
+            std::size_t next_block_size() const noexcept
+            {
+                return block_size_;
+            }
+
+        private:
+            allocator_info info() const noexcept;
+
+            char *      cur_, *end_;
+            std::size_t block_size_;
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif //WPI_MEMORY_STATIC_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/std_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/std_allocator.hpp
new file mode 100644
index 0000000..f727a1c
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/std_allocator.hpp
@@ -0,0 +1,360 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_STD_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_STD_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::std_allocator and related classes and functions.
+
+#include <new>
+#include <type_traits>
+
+#include "detail/utility.hpp"
+#include "config.hpp"
+#include "allocator_storage.hpp"
+#include "threading.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace traits_detail
+        {
+            template <class RawAllocator>
+            auto propagate_on_container_swap(std_concept) ->
+                typename RawAllocator::propagate_on_container_swap;
+
+            template <class RawAllocator>
+            auto propagate_on_container_swap(min_concept) -> std::true_type;
+
+            template <class RawAllocator>
+            auto propagate_on_container_move_assignment(std_concept) ->
+                typename RawAllocator::propagate_on_container_move_assignment;
+
+            template <class RawAllocator>
+            auto propagate_on_container_move_assignment(min_concept) -> std::true_type;
+
+            template <class RawAllocator>
+            auto propagate_on_container_copy_assignment(std_concept) ->
+                typename RawAllocator::propagate_on_container_copy_assignment;
+
+            template <class RawAllocator>
+            auto propagate_on_container_copy_assignment(min_concept) -> std::true_type;
+        } // namespace traits_detail
+
+        /// Controls the propagation of a \ref std_allocator for a certain \concept{concept_rawallocator,RawAllocator}.
+        /// \ingroup adapter
+        template <class RawAllocator>
+        struct propagation_traits
+        {
+            using propagate_on_container_swap =
+                decltype(traits_detail::propagate_on_container_swap<RawAllocator>(
+                    traits_detail::full_concept{}));
+
+            using propagate_on_container_move_assignment =
+                decltype(traits_detail::propagate_on_container_move_assignment<RawAllocator>(
+                    traits_detail::full_concept{}));
+
+            using propagate_on_container_copy_assignment =
+                decltype(traits_detail::propagate_on_container_copy_assignment<RawAllocator>(
+                    traits_detail::full_concept{}));
+
+            template <class AllocReference>
+            static AllocReference select_on_container_copy_construction(const AllocReference& alloc)
+            {
+                return alloc;
+            }
+        };
+
+        /// Wraps a \concept{concept_rawallocator,RawAllocator} and makes it a "normal" \c Allocator.
+        /// It allows using a \c RawAllocator anywhere a \c Allocator is required.
+        /// \ingroup adapter
+        template <typename T, class RawAllocator>
+        class std_allocator :
+#if defined _MSC_VER && defined __clang__
+            WPI_EBO(protected allocator_reference<RawAllocator>)
+#else
+            WPI_EBO(allocator_reference<RawAllocator>)
+#endif
+        {
+            using alloc_reference = allocator_reference<RawAllocator>;
+            // if it is any_allocator_reference an optimized implementation can be used
+            using is_any = std::is_same<alloc_reference, any_allocator_reference>;
+
+            using prop_traits = propagation_traits<RawAllocator>;
+
+        public:
+            //=== typedefs ===//
+            using value_type      = T;
+            using pointer         = T*;
+            using const_pointer   = const T*;
+            using reference       = T&;
+            using const_reference = const T&;
+            using size_type       = std::size_t;
+            using difference_type = std::ptrdiff_t;
+
+            using propagate_on_container_swap = typename prop_traits::propagate_on_container_swap;
+            using propagate_on_container_move_assignment =
+                typename prop_traits::propagate_on_container_move_assignment;
+            using propagate_on_container_copy_assignment =
+                typename prop_traits::propagate_on_container_copy_assignment;
+
+            template <typename U>
+            struct rebind
+            {
+                using other = std_allocator<U, RawAllocator>;
+            };
+
+            using allocator_type = typename alloc_reference::allocator_type;
+
+            //=== constructor ===//
+            /// \effects Default constructs it by storing a default constructed, stateless \c RawAllocator inside the reference.
+            /// \requires The \c RawAllocator type is stateless, otherwise the body of this function will not compile.
+            std_allocator() noexcept : alloc_reference(allocator_type{})
+            {
+#if !defined(__GNUC__) || (defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI != 0)
+                // std::string requires default constructor for the small string optimization when using gcc's old ABI
+                // so don't assert then to allow joint allocator
+                static_assert(!alloc_reference::is_stateful::value,
+                              "default constructor must not be used for stateful allocators");
+#endif
+            }
+
+            /// \effects Creates it from a reference to a \c RawAllocator.
+            /// It will store an \ref allocator_reference to it.
+            /// \requires The expression <tt>allocator_reference<RawAllocator>(alloc)</tt> is well-formed,
+            /// that is either \c RawAlloc is the same as \c RawAllocator or \c RawAllocator is the tag type \ref any_allocator.
+            /// If the requirement is not fulfilled this function does not participate in overload resolution.
+            /// \note The caller has to ensure that the lifetime of the \c RawAllocator is at least as long as the lifetime
+            /// of this \ref std_allocator object.
+            template <
+                class RawAlloc,
+                // MSVC seems to ignore access rights in decltype SFINAE below
+                // use this to prevent this constructor being chosen instead of move/copy for types inheriting from it
+                WPI_REQUIRES((!std::is_base_of<std_allocator, RawAlloc>::value))>
+            std_allocator(RawAlloc& alloc, WPI_SFINAE(alloc_reference(alloc))) noexcept
+            : alloc_reference(alloc)
+            {
+            }
+
+            /// \effects Creates it from a stateless, temporary \c RawAllocator object.
+            /// It will not store a reference but create it on the fly.
+            /// \requires The \c RawAllocator is stateless
+            /// and the expression <tt>allocator_reference<RawAllocator>(alloc)</tt> is well-formed as above,
+            /// otherwise this function does not participate in overload resolution.
+            template <
+                class RawAlloc,
+                // MSVC seems to ignore access rights in decltype SFINAE below
+                // use this to prevent this constructor being chosen instead of move/copy for types inheriting from it
+                WPI_REQUIRES((!std::is_base_of<std_allocator, RawAlloc>::value))>
+            std_allocator(const RawAlloc& alloc, WPI_SFINAE(alloc_reference(alloc))) noexcept
+            : alloc_reference(alloc)
+            {
+            }
+
+            /// \effects Creates it from another \ref allocator_reference using the same allocator type.
+            std_allocator(const alloc_reference& alloc) noexcept : alloc_reference(alloc) {}
+
+            /// \details Implicit conversion from any other \ref allocator_storage is forbidden
+            /// to prevent accidentally wrapping another \ref allocator_storage inside a \ref allocator_reference.
+            template <class StoragePolicy, class OtherMut>
+            std_allocator(const allocator_storage<StoragePolicy, OtherMut>&) = delete;
+
+            /// @{
+            /// \effects Creates it from another \ref std_allocator allocating a different type.
+            /// This is required by the \c Allcoator concept and simply takes the same \ref allocator_reference.
+            template <typename U>
+            std_allocator(const std_allocator<U, RawAllocator>& alloc) noexcept
+            : alloc_reference(alloc)
+            {
+            }
+
+            template <typename U>
+            std_allocator(std_allocator<U, RawAllocator>& alloc) noexcept : alloc_reference(alloc)
+            {
+            }
+            /// @}
+
+            /// \returns A copy of the allocator.
+            /// This is required by the \c Allocator concept and forwards to the \ref propagation_traits.
+            std_allocator<T, RawAllocator> select_on_container_copy_construction() const
+            {
+                return prop_traits::select_on_container_copy_construction(*this);
+            }
+
+            //=== allocation/deallocation ===//
+            /// \effects Allocates memory using the underlying \concept{concept_rawallocator,RawAllocator}.
+            /// If \c n is \c 1, it will call <tt>allocate_node(sizeof(T), alignof(T))</tt>,
+            /// otherwise <tt>allocate_array(n, sizeof(T), alignof(T))</tt>.
+            /// \returns A pointer to a memory block suitable for \c n objects of type \c T.
+            /// \throws Anything thrown by the \c RawAllocator.
+            pointer allocate(size_type n, void* = nullptr)
+            {
+                return static_cast<pointer>(allocate_impl(is_any{}, n));
+            }
+
+            /// \effects Deallcoates memory using the underlying \concept{concept_rawallocator,RawAllocator}.
+            /// It will forward to the deallocation function in the same way as in \ref allocate().
+            /// \requires The pointer must come from a previous call to \ref allocate() with the same \c n on this object or any copy of it.
+            void deallocate(pointer p, size_type n) noexcept
+            {
+                deallocate_impl(is_any{}, p, n);
+            }
+
+            //=== construction/destruction ===//
+            /// \effects Creates an object of type \c U at given address using the passed arguments.
+            template <typename U, typename... Args>
+            void construct(U* p, Args&&... args)
+            {
+                void* mem = p;
+                ::new (mem) U(detail::forward<Args>(args)...);
+            }
+
+            /// \effects Calls the destructor for an object of type \c U at given address.
+            template <typename U>
+            void destroy(U* p) noexcept
+            {
+                // This is to avoid a MSVS 2015 'unreferenced formal parameter' warning
+                (void)p;
+                p->~U();
+            }
+
+            //=== getter ===//
+            /// \returns The maximum size for an allocation which is <tt>max_array_size() / sizeof(value_type)</tt>.
+            /// This is only an upper bound, not the exact maximum.
+            size_type max_size() const noexcept
+            {
+                return this->max_array_size() / sizeof(value_type);
+            }
+
+            /// @{
+            /// \effects Returns a reference to the referenced allocator.
+            /// \returns For stateful allocators: A (\c const) reference to the stored allocator.
+            /// For stateless allocators: A temporary constructed allocator.
+            auto get_allocator() noexcept
+                -> decltype(std::declval<alloc_reference>().get_allocator())
+            {
+                return alloc_reference::get_allocator();
+            }
+
+            auto get_allocator() const noexcept
+                -> decltype(std::declval<const alloc_reference>().get_allocator())
+            {
+                return alloc_reference::get_allocator();
+            }
+            /// @}
+
+        private:
+            // any_allocator_reference: use virtual function which already does a dispatch on node/array
+            void* allocate_impl(std::true_type, size_type n)
+            {
+                return get_allocator().allocate_impl(n, sizeof(T), alignof(T));
+            }
+
+            void deallocate_impl(std::true_type, void* ptr, size_type n)
+            {
+                get_allocator().deallocate_impl(ptr, n, sizeof(T), alignof(T));
+            }
+
+            // alloc_reference: decide between node/array
+            void* allocate_impl(std::false_type, size_type n)
+            {
+                if (n == 1)
+                    return this->allocate_node(sizeof(T), alignof(T));
+                else
+                    return this->allocate_array(n, sizeof(T), alignof(T));
+            }
+
+            void deallocate_impl(std::false_type, void* ptr, size_type n)
+            {
+                if (n == 1)
+                    this->deallocate_node(ptr, sizeof(T), alignof(T));
+                else
+                    this->deallocate_array(ptr, n, sizeof(T), alignof(T));
+            }
+
+            template <typename U> // stateful
+            bool equal_to_impl(std::true_type,
+                               const std_allocator<U, RawAllocator>& other) const noexcept
+            {
+                return &get_allocator() == &other.get_allocator();
+            }
+
+            template <typename U> // non-stateful
+            bool equal_to_impl(std::false_type,
+                               const std_allocator<U, RawAllocator>&) const noexcept
+            {
+                return true;
+            }
+
+            template <typename U> // shared
+            bool equal_to(std::true_type,
+                          const std_allocator<U, RawAllocator>& other) const noexcept
+            {
+                return get_allocator() == other.get_allocator();
+            }
+
+            template <typename U> // not shared
+            bool equal_to(std::false_type,
+                          const std_allocator<U, RawAllocator>& other) const noexcept
+            {
+                return equal_to_impl(typename allocator_traits<RawAllocator>::is_stateful{}, other);
+            }
+
+            template <typename T1, typename T2, class Impl>
+            friend bool operator==(const std_allocator<T1, Impl>& lhs,
+                                   const std_allocator<T2, Impl>& rhs) noexcept;
+
+            template <typename U, class OtherRawAllocator>
+            friend class std_allocator;
+        };
+
+        /// \effects Compares two \ref std_allocator object, they are equal if either stateless or reference the same allocator.
+        /// \returns The result of the comparision for equality.
+        /// \relates std_allocator
+        template <typename T, typename U, class Impl>
+        bool operator==(const std_allocator<T, Impl>& lhs,
+                        const std_allocator<U, Impl>& rhs) noexcept
+        {
+            return lhs.equal_to(is_shared_allocator<Impl>{}, rhs);
+        }
+
+        /// \effects Compares two \ref std_allocator object, they are equal if either stateless or reference the same allocator.
+        /// \returns The result of the comparision for inequality.
+        /// \relates std_allocator
+        template <typename T, typename U, class Impl>
+        bool operator!=(const std_allocator<T, Impl>& lhs,
+                        const std_allocator<U, Impl>& rhs) noexcept
+        {
+            return !(lhs == rhs);
+        }
+
+        /// \returns A new \ref std_allocator for a given type using a certain allocator object.
+        /// \relates std_allocator
+        template <typename T, class RawAllocator>
+        auto make_std_allocator(RawAllocator&& allocator) noexcept
+            -> std_allocator<T, typename std::decay<RawAllocator>::type>
+        {
+            return {detail::forward<RawAllocator>(allocator)};
+        }
+
+        /// An alias template for \ref std_allocator using a type-erased \concept{concept_rawallocator,RawAllocator}.
+        /// This is the same as using a \ref std_allocator with the tag type \ref any_allocator.
+        /// The implementation is optimized to call fewer virtual functions.
+        /// \ingroup adapter
+        template <typename T>
+        WPI_ALIAS_TEMPLATE(any_std_allocator, std_allocator<T, any_allocator>);
+
+        /// \returns A new \ref any_std_allocator for a given type using a certain allocator object.
+        /// \relates any_std_allocator
+        template <typename T, class RawAllocator>
+        any_std_allocator<T> make_any_std_allocator(RawAllocator&& allocator) noexcept
+        {
+            return {detail::forward<RawAllocator>(allocator)};
+        }
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_STD_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/temporary_allocator.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/temporary_allocator.hpp
new file mode 100644
index 0000000..7eba76f
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/temporary_allocator.hpp
@@ -0,0 +1,335 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_TEMPORARY_ALLOCATOR_HPP_INCLUDED
+#define WPI_MEMORY_TEMPORARY_ALLOCATOR_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::temporary_allocator and related functions.
+
+#include "config.hpp"
+#include "memory_stack.hpp"
+
+#if WPI_MEMORY_TEMPORARY_STACK_MODE >= 2
+#include <atomic>
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        class temporary_allocator;
+        class temporary_stack;
+
+        namespace detail
+        {
+            class temporary_block_allocator
+            {
+            public:
+                explicit temporary_block_allocator(std::size_t block_size) noexcept;
+
+                memory_block allocate_block();
+
+                void deallocate_block(memory_block block);
+
+                std::size_t next_block_size() const noexcept
+                {
+                    return block_size_;
+                }
+
+                using growth_tracker = void (*)(std::size_t size);
+
+                growth_tracker set_growth_tracker(growth_tracker t) noexcept;
+
+                growth_tracker get_growth_tracker() noexcept;
+
+            private:
+                growth_tracker tracker_;
+                std::size_t    block_size_;
+            };
+
+            using temporary_stack_impl = memory_stack<temporary_block_allocator>;
+
+            class temporary_stack_list;
+
+#if WPI_MEMORY_TEMPORARY_STACK_MODE >= 2
+            class temporary_stack_list_node
+            {
+            public:
+                // doesn't add into list
+                temporary_stack_list_node() noexcept : in_use_(true) {}
+
+                temporary_stack_list_node(int) noexcept;
+
+                ~temporary_stack_list_node() noexcept {}
+
+            private:
+                temporary_stack_list_node* next_ = nullptr;
+                std::atomic<bool>          in_use_;
+
+                friend temporary_stack_list;
+            };
+
+            static class temporary_allocator_dtor_t
+            {
+            public:
+                temporary_allocator_dtor_t() noexcept;
+                ~temporary_allocator_dtor_t() noexcept;
+            } temporary_allocator_dtor;
+#else
+            class temporary_stack_list_node
+            {
+            protected:
+                temporary_stack_list_node() noexcept {}
+
+                temporary_stack_list_node(int) noexcept {}
+
+                ~temporary_stack_list_node() noexcept {}
+            };
+#endif
+        } // namespace detail
+
+        /// A wrapper around the \ref memory_stack that is used by the \ref temporary_allocator.
+        /// There should be at least one per-thread.
+        /// \ingroup allocator
+        class temporary_stack : WPI_EBO(detail::temporary_stack_list_node)
+        {
+        public:
+            /// The type of the handler called when the internal \ref memory_stack grows.
+            /// It gets the size of the new block that will be allocated.
+            /// \requiredbe The handler shall log the growth, throw an exception or aborts the program.
+            /// If this function does not return, the growth is prevented but the allocator unusable until memory is freed.
+            /// \defaultbe The default handler does nothing.
+            using growth_tracker = detail::temporary_block_allocator::growth_tracker;
+
+            /// \effects Sets \c h as the new \ref growth_tracker.
+            /// A \c nullptr sets the default \ref growth_tracker.
+            /// Each thread has its own, separate tracker.
+            /// \returns The previous \ref growth_tracker. This is never \c nullptr.
+            growth_tracker set_growth_tracker(growth_tracker t) noexcept
+            {
+                return stack_.get_allocator().set_growth_tracker(t);
+            }
+
+            /// \returns The current \ref growth_tracker. This is never \c nullptr.
+            growth_tracker get_growth_tracker() noexcept
+            {
+                return stack_.get_allocator().get_growth_tracker();
+            }
+
+            /// \effects Creates it with a given initial size of the stack.
+            /// It can grow if needed, although that is expensive.
+            /// \requires `initial_size` must be greater than `0`.
+            explicit temporary_stack(std::size_t initial_size) : stack_(initial_size), top_(nullptr)
+            {
+            }
+
+            /// \returns `next_capacity()` of the internal `memory_stack`.
+            std::size_t next_capacity() const noexcept
+            {
+                return stack_.next_capacity();
+            }
+
+        private:
+            temporary_stack(int i, std::size_t initial_size)
+            : detail::temporary_stack_list_node(i), stack_(initial_size), top_(nullptr)
+            {
+            }
+
+            using marker = detail::temporary_stack_impl::marker;
+
+            marker top() const noexcept
+            {
+                return stack_.top();
+            }
+
+            void unwind(marker m) noexcept
+            {
+                stack_.unwind(m);
+            }
+
+            detail::temporary_stack_impl stack_;
+            temporary_allocator*         top_;
+
+#if !defined(DOXYGEN)
+            friend temporary_allocator;
+            friend memory_stack_raii_unwind<temporary_stack>;
+            friend detail::temporary_stack_list;
+#endif
+        };
+
+        /// Manually takes care of the lifetime of the per-thread \ref temporary_stack.
+        /// The constructor will create it, if not already done, and the destructor will destroy it, if not already done.
+        /// \note If there are multiple objects in a thread,
+        /// this will lead to unnecessary construction and destruction of the stack.
+        /// It is thus adviced to create one object on the top-level function of the thread, e.g. in `main()`.
+        /// \note If `WPI_MEMORY_TEMPORARY_STACK_MODE == 2`, it is not necessary to use this class,
+        /// the nifty counter will clean everything upon program termination.
+        /// But it can still be used as an optimization if you have a thread that is terminated long before program exit.
+        /// The automatic clean up will only occur much later.
+        /// \note If `WPI_MEMORY_TEMPORARY_STACK_MODE == 0`, the use of this class has no effect,
+        /// because the per-thread stack is disabled.
+        /// \relatesalso temporary_stack
+        class temporary_stack_initializer
+        {
+        public:
+            static constexpr std::size_t default_stack_size = 4096u;
+
+            static const struct defer_create_t
+            {
+                defer_create_t() noexcept {}
+            } defer_create;
+
+            /// \effects Does not create the per-thread stack.
+            /// It will be created by the first call to \ref get_temporary_stack() in the current thread.
+            /// \note If `WPI_MEMORY_TEMPORARY_STACK_MODE == 0`, this function has no effect.
+            temporary_stack_initializer(defer_create_t) noexcept {}
+
+            /// \effects Creates the per-thread stack with the given default size if it wasn't already created.
+            /// \requires `initial_size` must not be `0` if `WPI_MEMORY_TEMPORARY_STACK_MODE != 0`.
+            /// \note If `WPI_MEMORY_TEMPORARY_STACK_MODE == 0`, this function will issue a warning in debug mode.
+            /// This can be disabled by passing `0` as the initial size.
+            temporary_stack_initializer(std::size_t initial_size = default_stack_size);
+
+            /// \effects Destroys the per-thread stack if it isn't already destroyed.
+            ~temporary_stack_initializer() noexcept;
+
+            temporary_stack_initializer(temporary_stack_initializer&&) = delete;
+            temporary_stack_initializer& operator=(temporary_stack_initializer&&) = delete;
+        };
+
+        /// \effects Creates the per-thread \ref temporary_stack with the given initial size,
+        /// if it wasn't already created.
+        /// \returns The per-thread \ref temporary_stack.
+        /// \requires There must be a per-thread temporary stack (\ref WPI_MEMORY_TEMPORARY_STACK_MODE must not be equal to `0`).
+        /// \note If \ref WPI_MEMORY_TEMPORARY_STACK_MODE is equal to `1`,
+        /// this function can create the temporary stack.
+        /// But if there is no \ref temporary_stack_initializer, it won't be destroyed.
+        /// \relatesalso temporary_stack
+        temporary_stack& get_temporary_stack(
+            std::size_t initial_size = temporary_stack_initializer::default_stack_size);
+
+        /// A stateful \concept{concept_rawallocator,RawAllocator} that handles temporary allocations.
+        /// It works similar to \c alloca() but uses a seperate \ref memory_stack for the allocations,
+        /// instead of the actual program stack.
+        /// This avoids the stack overflow error and is portable,
+        /// with a similar speed.
+        /// All allocations done in the scope of the allocator object are automatically freed when the object is destroyed.
+        /// \ingroup allocator
+        class temporary_allocator
+        {
+        public:
+            /// \effects Creates it by using the \ref get_temporary_stack() to get the temporary stack.
+            /// \requires There must be a per-thread temporary stack (\ref WPI_MEMORY_TEMPORARY_STACK_MODE must not be equal to `0`).
+            temporary_allocator();
+
+            /// \effects Creates it by giving it the \ref temporary_stack it uses for allocation.
+            explicit temporary_allocator(temporary_stack& stack);
+
+            ~temporary_allocator() noexcept;
+
+            temporary_allocator(temporary_allocator&&) = delete;
+            temporary_allocator& operator=(temporary_allocator&&) = delete;
+
+            /// \effects Allocates memory from the internal \ref memory_stack by forwarding to it.
+            /// \returns The result of \ref memory_stack::allocate().
+            /// \requires `is_active()` must return `true`.
+            void* allocate(std::size_t size, std::size_t alignment);
+
+            /// \returns Whether or not the allocator object is active.
+            /// \note The active allocator object is the last object created for one stack.
+            /// Moving changes the active allocator.
+            bool is_active() const noexcept;
+
+            /// \effects Instructs it to release unnecessary memory after automatic unwinding occurs.
+            /// This will effectively forward to \ref memory_stack::shrink_to_fit() of the internal stack.
+            /// \note Like the use of the \ref temporary_stack_initializer this can be used as an optimization,
+            /// to tell when the thread's \ref temporary_stack isn't needed anymore and can be destroyed.
+            /// \note It doesn't call shrink to fit immediately, only in the destructor!
+            void shrink_to_fit() noexcept;
+
+            /// \returns The internal stack the temporary allocator is using.
+            /// \requires `is_active()` must return `true`.
+            temporary_stack& get_stack() const noexcept
+            {
+                return unwind_.get_stack();
+            }
+
+        private:
+            memory_stack_raii_unwind<temporary_stack> unwind_;
+            temporary_allocator*                      prev_;
+            bool                                      shrink_to_fit_;
+        };
+
+        template <class Allocator>
+        class allocator_traits;
+
+        /// Specialization of the \ref allocator_traits for \ref temporary_allocator classes.
+        /// \note It is not allowed to mix calls through the specialization and through the member functions,
+        /// i.e. \ref temporary_allocator::allocate() and this \c allocate_node().
+        /// \ingroup allocator
+        template <>
+        class allocator_traits<temporary_allocator>
+        {
+        public:
+            using allocator_type = temporary_allocator;
+            using is_stateful    = std::true_type;
+
+            /// \returns The result of \ref temporary_allocator::allocate().
+            static void* allocate_node(allocator_type& state, std::size_t size,
+                                       std::size_t alignment)
+            {
+                detail::check_allocation_size<bad_node_size>(size,
+                                                             [&] { return max_node_size(state); },
+                                                             {WPI_MEMORY_LOG_PREFIX
+                                                              "::temporary_allocator",
+                                                              &state});
+                return state.allocate(size, alignment);
+            }
+
+            /// \returns The result of \ref temporary_allocator::allocate().
+            static void* allocate_array(allocator_type& state, std::size_t count, std::size_t size,
+                                        std::size_t alignment)
+            {
+                return allocate_node(state, count * size, alignment);
+            }
+
+            /// @{
+            /// \effects Does nothing besides bookmarking for leak checking, if that is enabled.
+            /// Actual deallocation will be done automatically if the allocator object goes out of scope.
+            static void deallocate_node(const allocator_type&, void*, std::size_t,
+                                        std::size_t) noexcept
+            {
+            }
+
+            static void deallocate_array(const allocator_type&, void*, std::size_t, std::size_t,
+                                         std::size_t) noexcept
+            {
+            }
+            /// @}
+
+            /// @{
+            /// \returns The maximum size which is \ref memory_stack::next_capacity() of the internal stack.
+            static std::size_t max_node_size(const allocator_type& state) noexcept
+            {
+                return state.get_stack().next_capacity();
+            }
+
+            static std::size_t max_array_size(const allocator_type& state) noexcept
+            {
+                return max_node_size(state);
+            }
+            /// @}
+
+            /// \returns The maximum possible value since there is no alignment restriction
+            /// (except indirectly through \ref memory_stack::next_capacity()).
+            static std::size_t max_alignment(const allocator_type&) noexcept
+            {
+                return std::size_t(-1);
+            }
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_TEMPORARY_ALLOCATOR_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/threading.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/threading.hpp
new file mode 100644
index 0000000..0314ea4
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/threading.hpp
@@ -0,0 +1,155 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_THREADING_HPP_INCLUDED
+#define WPI_MEMORY_THREADING_HPP_INCLUDED
+
+/// \file
+/// The mutex types.
+
+#include <type_traits>
+
+#include "allocator_traits.hpp"
+#include "config.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <mutex>
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        /// A dummy \c Mutex class that does not lock anything.
+        /// It is a valid \c Mutex and can be used to disable locking anywhere a \c Mutex is requested.
+        /// \ingroup core
+        struct no_mutex
+        {
+            void lock() noexcept {}
+
+            bool try_lock() noexcept
+            {
+                return true;
+            }
+
+            void unlock() noexcept {}
+        };
+
+        /// Specifies whether or not a \concept{concept_rawallocator,RawAllocator} is thread safe as-is.
+        /// This allows to use \ref no_mutex as an optimization.
+        /// Note that stateless allocators are implictly thread-safe.
+        /// Specialize it only for your own stateful allocators.
+        /// \ingroup core
+        template <class RawAllocator>
+        struct is_thread_safe_allocator
+        : std::integral_constant<bool, !allocator_traits<RawAllocator>::is_stateful::value>
+        {
+        };
+
+        namespace detail
+        {
+            // selects a mutex for an Allocator
+            // stateless allocators don't need locking
+            template <class RawAllocator, class Mutex>
+            using mutex_for =
+                typename std::conditional<is_thread_safe_allocator<RawAllocator>::value, no_mutex,
+                                          Mutex>::type;
+
+            // storage for mutexes to use EBO
+            // it provides const lock/unlock function, inherit from it
+            template <class Mutex>
+            class mutex_storage
+            {
+            public:
+                mutex_storage() noexcept = default;
+                mutex_storage(const mutex_storage&) noexcept {}
+
+                mutex_storage& operator=(const mutex_storage&) noexcept
+                {
+                    return *this;
+                }
+
+                void lock() const
+                {
+                    mutex_.lock();
+                }
+
+                void unlock() const noexcept
+                {
+                    mutex_.unlock();
+                }
+
+            protected:
+                ~mutex_storage() noexcept = default;
+
+            private:
+                mutable Mutex mutex_;
+            };
+
+            template <>
+            class mutex_storage<no_mutex>
+            {
+            public:
+                mutex_storage() noexcept = default;
+
+                void lock() const noexcept {}
+                void unlock() const noexcept {}
+
+            protected:
+                ~mutex_storage() noexcept = default;
+            };
+
+            // non changeable pointer to an Allocator that keeps a lock
+            // I don't think EBO is necessary here...
+            template <class Alloc, class Mutex>
+            class locked_allocator
+            {
+            public:
+                locked_allocator(Alloc& alloc, Mutex& m) noexcept : mutex_(&m), alloc_(&alloc)
+                {
+                    mutex_->lock();
+                }
+
+                locked_allocator(locked_allocator&& other) noexcept
+                : mutex_(other.mutex_), alloc_(other.alloc_)
+                {
+                    other.mutex_ = nullptr;
+                    other.alloc_ = nullptr;
+                }
+
+                ~locked_allocator() noexcept
+                {
+                    if (mutex_)
+                        mutex_->unlock();
+                }
+
+                locked_allocator& operator=(locked_allocator&& other) noexcept = delete;
+
+                Alloc& operator*() const noexcept
+                {
+                    WPI_MEMORY_ASSERT(alloc_);
+                    return *alloc_;
+                }
+
+                Alloc* operator->() const noexcept
+                {
+                    WPI_MEMORY_ASSERT(alloc_);
+                    return alloc_;
+                }
+
+            private:
+                Mutex* mutex_; // don't use unqiue_lock to avoid dependency
+                Alloc* alloc_;
+            };
+
+            template <class Alloc, class Mutex>
+            locked_allocator<Alloc, Mutex> lock_allocator(Alloc& a, Mutex& m)
+            {
+                return {a, m};
+            }
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_THREADING_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/tracking.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/tracking.hpp
new file mode 100644
index 0000000..ccbc343
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/tracking.hpp
@@ -0,0 +1,430 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_TRACKING_HPP_INCLUDED
+#define WPI_MEMORY_TRACKING_HPP_INCLUDED
+
+/// \file
+/// Class \ref wpi::memory::tracked_allocator and related classes and functions.
+
+#include "detail/utility.hpp"
+#include "allocator_traits.hpp"
+#include "memory_arena.hpp"
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            template <class Allocator, class Tracker>
+            auto set_tracker(int, Allocator& allocator, Tracker* tracker) noexcept
+                -> decltype(allocator.get_allocator().set_tracker(tracker))
+            {
+                return allocator.get_allocator().set_tracker(tracker);
+            }
+            template <class Allocator, class Tracker>
+            void set_tracker(short, Allocator&, Tracker*) noexcept
+            {
+            }
+
+            // used with deeply_tracked_allocator
+            template <class Tracker, class BlockAllocator>
+            class deeply_tracked_block_allocator : WPI_EBO(BlockAllocator)
+            {
+            public:
+                template <typename... Args>
+                deeply_tracked_block_allocator(std::size_t block_size, Args&&... args)
+                : BlockAllocator(block_size, detail::forward<Args>(args)...), tracker_(nullptr)
+                {
+                }
+
+                memory_block allocate_block()
+                {
+                    auto block = BlockAllocator::allocate_block();
+                    if (tracker_) // on first call tracker_ is nullptr
+                        tracker_->on_allocator_growth(block.memory, block.size);
+                    return block;
+                }
+
+                void deallocate_block(memory_block block) noexcept
+                {
+                    if (tracker_) // on last call tracker_ is nullptr again
+                        tracker_->on_allocator_shrinking(block.memory, block.size);
+                    BlockAllocator::deallocate_block(block);
+                }
+
+                std::size_t next_block_size() const noexcept
+                {
+                    return BlockAllocator::next_block_size();
+                }
+
+                void set_tracker(Tracker* tracker) noexcept
+                {
+                    tracker_ = tracker;
+                }
+
+            private:
+                Tracker* tracker_;
+            };
+        } // namespace detail
+
+        /// A \concept{concept_blockallocator,BlockAllocator} adapter that tracks another allocator using a \concept{concept_tracker,tracker}.
+        /// It wraps another \concept{concept_blockallocator,BlockAllocator} and calls the tracker function before forwarding to it.
+        /// The class can then be used anywhere a \concept{concept_blockallocator,BlockAllocator} is required and the memory usage will be tracked.<br>
+        /// It will only call the <tt>on_allocator_growth()</tt> and <tt>on_allocator_shrinking()</tt> tracking functions,
+        /// since a \concept{concept_blockallocator,BlockAllocator} is normally used inside higher allocators only.
+        /// \ingroup adapter
+        template <class Tracker, class BlockOrRawAllocator>
+        class tracked_block_allocator
+        : WPI_EBO(Tracker, make_block_allocator_t<BlockOrRawAllocator>)
+        {
+        public:
+            using allocator_type = make_block_allocator_t<BlockOrRawAllocator>;
+            using tracker        = Tracker;
+
+            /// @{
+            /// \effects Creates it by giving it a \concept{concept_tracker,tracker} and the tracked \concept{concept_rawallocator,RawAllocator}.
+            /// It will embed both objects.
+            explicit tracked_block_allocator(tracker t = {}) noexcept : tracker(detail::move(t)) {}
+
+            tracked_block_allocator(tracker t, allocator_type&& alloc) noexcept
+            : tracker(detail::move(t)), allocator_type(detail::move(alloc))
+            {
+            }
+            /// @}
+
+            /// \effects Creates it in the form required by the concept.
+            /// The allocator will be constructed using \c block_size and \c args.
+            template <typename... Args>
+            tracked_block_allocator(std::size_t block_size, tracker t, Args&&... args)
+            : tracker(detail::move(t)), allocator_type(block_size, detail::forward<Args>(args)...)
+            {
+            }
+
+            /// \effects Calls <tt>Tracker::on_allocator_growth()</tt> after forwarding to the allocator.
+            /// \returns The block as the returned by the allocator.
+            memory_block allocate_block()
+            {
+                auto block = allocator_type::allocate_block();
+                this->on_allocator_growth(block.memory, block.size);
+                return block;
+            }
+
+            /// \effects Calls <tt>Tracker::on_allocator_shrinking()</tt> and forwards to the allocator.
+            void deallocate_block(memory_block block) noexcept
+            {
+                this->on_allocator_shrinking(block.memory, block.size);
+                allocator_type::deallocate_block(block);
+            }
+
+            /// \returns The next block size as returned by the allocator.
+            std::size_t next_block_size() const noexcept
+            {
+                return allocator_type::next_block_size();
+            }
+
+            /// @{
+            /// \returns A (const) reference to the used allocator.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+            const allocator_type& get_allocator() const noexcept
+            {
+                return *this;
+            }
+            /// @}
+
+            /// @{
+            /// \returns A (const) reference to the tracker.
+            tracker& get_tracker() noexcept
+            {
+                return *this;
+            }
+
+            const tracker& get_tracker() const noexcept
+            {
+                return *this;
+            }
+            /// @}
+        };
+
+        /// Similar to \ref tracked_block_allocator, but shares the tracker with the higher level allocator.
+        /// This allows tracking both (de-)allocations and growth with one tracker.
+        /// \note Due to implementation reasons, it cannot track growth and shrinking in the constructor/destructor of the higher level allocator.
+        /// \ingroup adapter
+        template <class Tracker, class BlockOrRawAllocator>
+        using deeply_tracked_block_allocator = WPI_IMPL_DEFINED(
+            detail::deeply_tracked_block_allocator<Tracker,
+                                                   make_block_allocator_t<BlockOrRawAllocator>>);
+
+        /// A \concept{concept_rawallocator,RawAllocator} adapter that tracks another allocator using a \concept{concept_tracker,tracker}.
+        /// It wraps another \concept{concept_rawallocator,RawAllocator} and calls the tracker function before forwarding to it.
+        /// The class can then be used anywhere a \concept{concept_rawallocator,RawAllocator} is required and the memory usage will be tracked.<br>
+        /// If the \concept{concept_rawallocator,RawAllocator} uses \ref deeply_tracked_block_allocator as \concept{concept_blockallocator,BlockAllocator},
+        /// it will also track growth and shrinking of the allocator.
+        /// \ingroup adapter
+        template <class Tracker, class RawAllocator>
+        class tracked_allocator
+        : WPI_EBO(Tracker, allocator_traits<RawAllocator>::allocator_type)
+        {
+            using traits            = allocator_traits<RawAllocator>;
+            using composable_traits = composable_allocator_traits<RawAllocator>;
+
+        public:
+            using allocator_type = typename allocator_traits<RawAllocator>::allocator_type;
+            using tracker        = Tracker;
+
+            using is_stateful = std::integral_constant<bool, traits::is_stateful::value
+                                                                 || !std::is_empty<Tracker>::value>;
+
+            /// @{
+            /// \effects Creates it by giving it a \concept{concept_tracker,tracker} and the tracked \concept{concept_rawallocator,RawAllocator}.
+            /// It will embed both objects.
+            /// \note This will never call the <tt>Tracker::on_allocator_growth()</tt> function.
+            explicit tracked_allocator(tracker t = {}) noexcept
+            : tracked_allocator(detail::move(t), allocator_type{})
+            {
+            }
+
+            tracked_allocator(tracker t, allocator_type&& allocator) noexcept
+            : tracker(detail::move(t)), allocator_type(detail::move(allocator))
+            {
+                detail::set_tracker(0, get_allocator(), &get_tracker());
+            }
+            /// @}
+
+            /// \effects Destroys both tracker and allocator.
+            /// \note This will never call the <tt>Tracker::on_allocator_shrinking()</tt> function.
+            ~tracked_allocator() noexcept
+            {
+                detail::set_tracker(0, get_allocator(), static_cast<tracker*>(nullptr));
+            }
+
+            /// @{
+            /// \effects Moving moves both the tracker and the allocator.
+            tracked_allocator(tracked_allocator&& other) noexcept
+            : tracker(detail::move(other)), allocator_type(detail::move(other))
+            {
+                detail::set_tracker(0, get_allocator(), &get_tracker());
+            }
+
+            tracked_allocator& operator=(tracked_allocator&& other) noexcept
+            {
+                tracker::       operator=(detail::move(other));
+                allocator_type::operator=(detail::move(other));
+                detail::set_tracker(0, get_allocator(), &get_tracker());
+                return *this;
+            }
+            /// @}
+
+            /// \effects Calls <tt>Tracker::on_node_allocation()</tt> and forwards to the allocator.
+            /// If a growth occurs and the allocator is deeply tracked, also calls <tt>Tracker::on_allocator_growth()</tt>.
+            /// \returns The result of <tt>allocate_node()</tt>
+            void* allocate_node(std::size_t size, std::size_t alignment)
+            {
+                auto mem = traits::allocate_node(get_allocator(), size, alignment);
+                this->on_node_allocation(mem, size, alignment);
+                return mem;
+            }
+
+            /// \effects Calls the composable node allocation function.
+            /// If allocation was successful, also calls `Tracker::on_node_allocation()`.
+            /// \returns The result of `try_allocate_node()`.
+            void* try_allocate_node(std::size_t size, std::size_t alignment) noexcept
+            {
+                auto mem = composable_traits::try_allocate_node(get_allocator(), size, alignment);
+                if (mem)
+                    this->on_node_allocation(mem, size, alignment);
+                return mem;
+            }
+
+            /// \effects Calls <tt>Tracker::on_array_allocation()</tt> and forwards to the allocator.
+            /// If a growth occurs and the allocator is deeply tracked, also calls <tt>Tracker::on_allocator_growth()</tt>.
+            /// \returns The result of <tt>allocate_array()</tt>
+            void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment)
+            {
+                auto mem = traits::allocate_array(get_allocator(), count, size, alignment);
+                this->on_array_allocation(mem, count, size, alignment);
+                return mem;
+            }
+
+            /// \effects Calls the composable array allocation function.
+            /// If allocation was succesful, also calls `Tracker::on_array_allocation()`.
+            /// \returns The result of `try_allocate_array()`.
+            void* try_allocate_array(std::size_t count, std::size_t size,
+                                     std::size_t alignment) noexcept
+            {
+                auto mem =
+                    composable_traits::try_allocate_array(get_allocator(), count, size, alignment);
+                if (mem)
+                    this->on_array_allocation(mem, count, size, alignment);
+                return mem;
+            }
+
+            /// \effects Calls <tt>Tracker::on_node_deallocation()</tt> and forwards to the allocator's <tt>deallocate_node()</tt>.
+            /// If shrinking occurs and the allocator is deeply tracked, also calls <tt>Tracker::on_allocator_shrinking()</tt>.
+            void deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                this->on_node_deallocation(ptr, size, alignment);
+                traits::deallocate_node(get_allocator(), ptr, size, alignment);
+            }
+
+            /// \effects Calls the composable node deallocation function.
+            /// If it was succesful, also calls `Tracker::on_node_deallocation()`.
+            /// \returns The result of `try_deallocate_node()`.
+            bool try_deallocate_node(void* ptr, std::size_t size, std::size_t alignment) noexcept
+            {
+                auto res =
+                    composable_traits::try_deallocate_node(get_allocator(), ptr, size, alignment);
+                if (res)
+                    this->on_node_deallocation(ptr, size, alignment);
+                return res;
+            }
+
+            /// \effects Calls <tt>Tracker::on_array_deallocation()</tt> and forwards to the allocator's <tt>deallocate_array()</tt>.
+            /// If shrinking occurs and the allocator is deeply tracked, also calls <tt>Tracker::on_allocator_shrinking()</tt>.
+            void deallocate_array(void* ptr, std::size_t count, std::size_t size,
+                                  std::size_t alignment) noexcept
+            {
+                this->on_array_deallocation(ptr, count, size, alignment);
+                traits::deallocate_array(get_allocator(), ptr, count, size, alignment);
+            }
+
+            /// \effects Calls the composable array deallocation function.
+            /// If it was succesful, also calls `Tracker::on_array_deallocation()`.
+            /// \returns The result of `try_deallocate_array()`.
+            bool try_deallocate_array(void* ptr, std::size_t count, std::size_t size,
+                                      std::size_t alignment) noexcept
+            {
+                auto res = composable_traits::try_deallocate_array(ptr, count, size, alignment);
+                if (res)
+                    this->on_array_deallocation(ptr, count, size, alignment);
+                return res;
+            }
+
+            /// @{
+            /// \returns The result of the corresponding function on the wrapped allocator.
+            std::size_t max_node_size() const
+            {
+                return traits::max_node_size(get_allocator());
+            }
+
+            std::size_t max_array_size() const
+            {
+                return traits::max_array_size(get_allocator());
+            }
+
+            std::size_t max_alignment() const
+            {
+                return traits::max_alignment(get_allocator());
+            }
+            /// @}
+
+            /// @{
+            /// \returns A (\c const) reference to the wrapped allocator.
+            allocator_type& get_allocator() noexcept
+            {
+                return *this;
+            }
+
+            const allocator_type& get_allocator() const noexcept
+            {
+                return *this;
+            }
+            /// @}
+
+            /// @{
+            /// \returns A (\c const) reference to the tracker.
+            tracker& get_tracker() noexcept
+            {
+                return *this;
+            }
+
+            const tracker& get_tracker() const noexcept
+            {
+                return *this;
+            }
+            /// @}
+        };
+
+        /// \effects Takes a \concept{concept_rawallocator,RawAllocator} and wraps it with a \concept{concept_tracker,tracker}.
+        /// \returns A \ref tracked_allocator with the corresponding parameters forwarded to the constructor.
+        /// \relates tracked_allocator
+        template <class Tracker, class RawAllocator>
+        auto make_tracked_allocator(Tracker t, RawAllocator&& alloc)
+            -> tracked_allocator<Tracker, typename std::decay<RawAllocator>::type>
+        {
+            return tracked_allocator<Tracker, typename std::decay<RawAllocator>::type>{detail::move(
+                                                                                           t),
+                                                                                       detail::move(
+                                                                                           alloc)};
+        }
+
+        namespace detail
+        {
+            template <typename T, bool Block>
+            struct is_block_or_raw_allocator_impl : std::true_type
+            {
+            };
+
+            template <typename T>
+            struct is_block_or_raw_allocator_impl<T, false> : memory::is_raw_allocator<T>
+            {
+            };
+
+            template <typename T>
+            struct is_block_or_raw_allocator
+            : is_block_or_raw_allocator_impl<T, memory::is_block_allocator<T>::value>
+            {
+            };
+
+            template <class RawAllocator, class BlockAllocator>
+            struct rebind_block_allocator;
+
+            template <template <typename...> class RawAllocator, typename... Args,
+                      class OtherBlockAllocator>
+            struct rebind_block_allocator<RawAllocator<Args...>, OtherBlockAllocator>
+            {
+                using type =
+                    RawAllocator<typename std::conditional<is_block_or_raw_allocator<Args>::value,
+                                                           OtherBlockAllocator, Args>::type...>;
+            };
+
+            template <class Tracker, class RawAllocator>
+            using deeply_tracked_block_allocator_for =
+                memory::deeply_tracked_block_allocator<Tracker,
+                                                       typename RawAllocator::allocator_type>;
+
+            template <class Tracker, class RawAllocator>
+            using rebound_allocator = typename rebind_block_allocator<
+                RawAllocator, deeply_tracked_block_allocator_for<Tracker, RawAllocator>>::type;
+        } // namespace detail
+
+        /// A \ref tracked_allocator that has rebound any \concept{concept_blockallocator,BlockAllocator} to the corresponding \ref deeply_tracked_block_allocator.
+        /// This makes it a deeply tracked allocator.<br>
+        /// It replaces each template argument of the given \concept{concept_rawallocator,RawAllocator} for which \ref is_block_allocator or \ref is_raw_allocator is \c true with a \ref deeply_tracked_block_allocator.
+        /// \ingroup adapter
+        template <class Tracker, class RawAllocator>
+        WPI_ALIAS_TEMPLATE(
+            deeply_tracked_allocator,
+            tracked_allocator<Tracker, detail::rebound_allocator<Tracker, RawAllocator>>);
+
+        /// \effects Takes a \concept{concept_rawallocator,RawAllocator} and deeply wraps it with a \concept{concept_tracker,tracker}.
+        /// \returns A \ref deeply_tracked_allocator with the corresponding parameters forwarded to the constructor.
+        /// \relates deeply_tracked_allocator
+        template <class RawAllocator, class Tracker, typename... Args>
+        auto make_deeply_tracked_allocator(Tracker t, Args&&... args)
+            -> deeply_tracked_allocator<Tracker, RawAllocator>
+        {
+            return deeply_tracked_allocator<Tracker, RawAllocator>(detail::move(t),
+                                                                   {detail::forward<Args>(
+                                                                       args)...});
+        }
+    } // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_TRACKING_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/virtual_memory.hpp b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/virtual_memory.hpp
new file mode 100644
index 0000000..33d82f7
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/include/wpi/memory/virtual_memory.hpp
@@ -0,0 +1,202 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_VIRTUAL_MEMORY_HPP_INCLUDED
+#define WPI_MEMORY_VIRTUAL_MEMORY_HPP_INCLUDED
+
+/// \file
+/// Virtual memory api and (low-level) allocator classes.
+
+#include <cstddef>
+#include <type_traits>
+
+#include "detail/debug_helpers.hpp"
+#include "detail/utility.hpp"
+#include "config.hpp"
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+#include "allocator_traits.hpp"
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            struct virtual_memory_allocator_leak_handler
+            {
+                void operator()(std::ptrdiff_t amount);
+            };
+
+            WPI_MEMORY_GLOBAL_LEAK_CHECKER(virtual_memory_allocator_leak_handler,
+                                                 virtual_memory_allocator_leak_checker)
+        } // namespace detail
+
+        /// The page size of the virtual memory.
+        /// All virtual memory allocations must be multiple of this size.
+        /// It is usually 4KiB.
+        /// \ingroup allocator
+        /// \deprecated use \ref get_virtual_memory_page_size instead.
+        extern const std::size_t virtual_memory_page_size;
+
+        /// \returns the page size of the virtual memory.
+        /// All virtual memory allocations must be multiple of this size.
+        /// It is usually 4KiB.
+        /// \ingroup allocator
+        std::size_t get_virtual_memory_page_size() noexcept;
+
+        /// Reserves virtual memory.
+        /// \effects Reserves the given number of pages.
+        /// Each page is \ref virtual_memory_page_size big.
+        /// \returns The address of the first reserved page,
+        /// or \c nullptr in case of error.
+        /// \note The memory may not be used, it must first be commited.
+        /// \ingroup allocator
+        void* virtual_memory_reserve(std::size_t no_pages) noexcept;
+
+        /// Releases reserved virtual memory.
+        /// \effects Returns previously reserved pages to the system.
+        /// \requires \c pages must come from a previous call to \ref virtual_memory_reserve with the same \c calc_no_pages,
+        /// it must not be \c nullptr.
+        /// \ingroup allocator
+        void virtual_memory_release(void* pages, std::size_t no_pages) noexcept;
+
+        /// Commits reserved virtual memory.
+        /// \effects Marks \c calc_no_pages pages starting at the given address available for use.
+        /// \returns The beginning of the committed area, i.e. \c memory, or \c nullptr in case of error.
+        /// \requires The memory must be previously reserved.
+        /// \ingroup allocator
+        void* virtual_memory_commit(void* memory, std::size_t no_pages) noexcept;
+
+        /// Decommits commited virtual memory.
+        /// \effects Puts commited memory back in the reserved state.
+        /// \requires \c memory must come from a previous call to \ref virtual_memory_commit with the same \c calc_no_pages
+        /// it must not be \c nullptr.
+        /// \ingroup allocator
+        void virtual_memory_decommit(void* memory, std::size_t no_pages) noexcept;
+
+        /// A stateless \concept{concept_rawallocator,RawAllocator} that allocates memory using the virtual memory allocation functions.
+        /// It does not prereserve any memory and will always reserve and commit combined.
+        /// \ingroup allocator
+        class virtual_memory_allocator
+        : WPI_EBO(detail::global_leak_checker<detail::virtual_memory_allocator_leak_handler>)
+        {
+        public:
+            using is_stateful = std::false_type;
+
+            virtual_memory_allocator() noexcept = default;
+            virtual_memory_allocator(virtual_memory_allocator&&) noexcept {}
+            ~virtual_memory_allocator() noexcept = default;
+
+            virtual_memory_allocator& operator=(virtual_memory_allocator&&) noexcept
+            {
+                return *this;
+            }
+
+            /// \effects A \concept{concept_rawallocator,RawAllocator} allocation function.
+            /// It uses \ref virtual_memory_reserve followed by \ref virtual_memory_commit for the allocation.
+            /// The number of pages allocated will be the minimum to hold \c size continuous bytes,
+            /// i.e. \c size will be rounded up to the next multiple.
+            /// If debug fences are activated, one additional page before and after the memory will be allocated.
+            /// \returns A pointer to a \concept{concept_node,node}, it will never be \c nullptr.
+            /// It will always be aligned on a fence boundary, regardless of the alignment parameter.
+            /// \throws An exception of type \ref out_of_memory or whatever is thrown by its handler if the allocation fails.
+            void* allocate_node(std::size_t size, std::size_t alignment);
+
+            /// \effects A \concept{concept_rawallocator,RawAllocator} deallocation function.
+            /// It calls \ref virtual_memory_decommit followed by \ref virtual_memory_release for the deallocation.
+            void deallocate_node(void* node, std::size_t size, std::size_t alignment) noexcept;
+
+            /// \returns The maximum node size by returning the maximum value.
+            std::size_t max_node_size() const noexcept;
+
+            /// \returns The maximum alignment which is the same as the \ref virtual_memory_page_size.
+            std::size_t max_alignment() const noexcept;
+        };
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+        extern template class allocator_traits<virtual_memory_allocator>;
+#endif
+
+        struct memory_block;
+        struct allocator_info;
+
+        /// A \concept{concept_blockallocator,BlockAllocator} that reserves virtual memory and commits it part by part.
+        /// It is similar to \ref memory_stack but does not support growing and uses virtual memory,
+        /// also meant for big blocks not small allocations.
+        /// \ingroup allocator
+        class virtual_block_allocator
+        {
+        public:
+            /// \effects Creates it giving it the block size and the total number of blocks it can allocate.
+            /// It reserves enough virtual memory for <tt>block_size * no_blocks</tt>.
+            /// \requires \c block_size must be non-zero and a multiple of the \ref virtual_memory_page_size.
+            /// \c no_blocks must be bigger than \c 1.
+            /// \throws \ref out_of_memory if it cannot reserve the virtual memory.
+            explicit virtual_block_allocator(std::size_t block_size, std::size_t no_blocks);
+
+            /// \effects Releases the reserved virtual memory.
+            ~virtual_block_allocator() noexcept;
+
+            /// @{
+            /// \effects Moves the block allocator, it transfers ownership over the reserved area.
+            /// This does not invalidate any memory blocks.
+            virtual_block_allocator(virtual_block_allocator&& other) noexcept
+            : cur_(other.cur_), end_(other.end_), block_size_(other.block_size_)
+            {
+                other.cur_ = other.end_ = nullptr;
+                other.block_size_       = 0;
+            }
+
+            virtual_block_allocator& operator=(virtual_block_allocator&& other) noexcept
+            {
+                virtual_block_allocator tmp(detail::move(other));
+                swap(*this, tmp);
+                return *this;
+            }
+            /// @}
+
+            /// \effects Swaps the ownership over the reserved memory.
+            /// This does not invalidate any memory blocks.
+            friend void swap(virtual_block_allocator& a, virtual_block_allocator& b) noexcept
+            {
+                detail::adl_swap(a.cur_, b.cur_);
+                detail::adl_swap(a.end_, b.end_);
+                detail::adl_swap(a.block_size_, b.block_size_);
+            }
+
+            /// \effects Allocates a new memory block by committing the next \ref next_block_size() number of bytes.
+            /// \returns The \ref memory_block committed.
+            /// \throws \ref out_of_memory if it cannot commit the memory or the \ref capacity_left() is exhausted.
+            memory_block allocate_block();
+
+            /// \effects Deallocates the last allocated memory block by decommitting it.
+            /// This block will be returned again on the next call to \ref allocate_block().
+            /// \requires \c block must be the current top block of the memory,
+            /// this is guaranteed by \ref memory_arena.
+            void deallocate_block(memory_block block) noexcept;
+
+            /// \returns The next block size, this is the block size of the constructor.
+            std::size_t next_block_size() const noexcept
+            {
+                return block_size_;
+            }
+
+            /// \returns The number of blocks that can be committed until it runs out of memory.
+            std::size_t capacity_left() const noexcept
+            {
+                return static_cast<std::size_t>(end_ - cur_) / block_size_;
+            }
+
+        private:
+            allocator_info info() noexcept;
+
+            char *      cur_, *end_;
+            std::size_t block_size_;
+        };
+    } // namespace memory
+} // namespace wpi
+
+#endif //WPI_MEMORY_VIRTUAL_MEMORY_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/debugging.cpp b/wpiutil/src/main/native/thirdparty/memory/src/debugging.cpp
new file mode 100644
index 0000000..be1b033
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/debugging.cpp
@@ -0,0 +1,109 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/debugging.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <cstdio>
+#endif
+
+#include <atomic>
+#include <cstdlib>
+
+#include "wpi/memory/error.hpp"
+
+using namespace wpi::memory;
+
+namespace
+{
+    void default_leak_handler(const allocator_info& info, std::ptrdiff_t amount) noexcept
+    {
+#if WPI_HOSTED_IMPLEMENTATION
+        if (amount > 0)
+            std::fprintf(stderr, "[%s] Allocator %s (at %p) leaked %zu bytes.\n",
+                         WPI_MEMORY_LOG_PREFIX, info.name, info.allocator,
+                         std::size_t(amount));
+        else
+            std::fprintf(stderr,
+                         "[%s] Allocator %s (at %p) has deallocated %zu bytes more than "
+                         "ever allocated "
+                         "(it's amazing you're able to see this message!).\n",
+                         WPI_MEMORY_LOG_PREFIX, info.name, info.allocator,
+                         std::size_t(-amount));
+#else
+        (void)info;
+        (void)amount;
+#endif
+    }
+
+    std::atomic<leak_handler> leak_h(default_leak_handler);
+} // namespace
+
+leak_handler wpi::memory::set_leak_handler(leak_handler h)
+{
+    return leak_h.exchange(h ? h : default_leak_handler);
+}
+
+leak_handler wpi::memory::get_leak_handler()
+{
+    return leak_h;
+}
+
+namespace
+{
+    void default_invalid_ptr_handler(const allocator_info& info, const void* ptr) noexcept
+    {
+#if WPI_HOSTED_IMPLEMENTATION
+        std::fprintf(stderr,
+                     "[%s] Deallocation function of allocator %s (at %p) received invalid "
+                     "pointer %p\n",
+                     WPI_MEMORY_LOG_PREFIX, info.name, info.allocator, ptr);
+#endif
+        (void)info;
+        (void)ptr;
+        std::abort();
+    }
+
+    std::atomic<invalid_pointer_handler> invalid_ptr_h(default_invalid_ptr_handler);
+} // namespace
+
+invalid_pointer_handler wpi::memory::set_invalid_pointer_handler(invalid_pointer_handler h)
+{
+    return invalid_ptr_h.exchange(h ? h : default_invalid_ptr_handler);
+}
+
+invalid_pointer_handler wpi::memory::get_invalid_pointer_handler()
+{
+    return invalid_ptr_h;
+}
+
+namespace
+{
+    void default_buffer_overflow_handler(const void* memory, std::size_t node_size,
+                                         const void* ptr) noexcept
+    {
+#if WPI_HOSTED_IMPLEMENTATION
+        std::fprintf(stderr,
+                     "[%s] Buffer overflow at address %p detected, corresponding memory "
+                     "block %p has only size %zu.\n",
+                     WPI_MEMORY_LOG_PREFIX, ptr, memory, node_size);
+#endif
+        (void)memory;
+        (void)node_size;
+        (void)ptr;
+        std::abort();
+    }
+
+    std::atomic<buffer_overflow_handler> buffer_overflow_h(default_buffer_overflow_handler);
+} // namespace
+
+buffer_overflow_handler wpi::memory::set_buffer_overflow_handler(buffer_overflow_handler h)
+{
+    return buffer_overflow_h.exchange(h ? h : default_buffer_overflow_handler);
+}
+
+buffer_overflow_handler wpi::memory::get_buffer_overflow_handler()
+{
+    return buffer_overflow_h;
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/detail/align.cpp b/wpiutil/src/main/native/thirdparty/memory/src/detail/align.cpp
new file mode 100644
index 0000000..e1c4f2a
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/detail/align.cpp
@@ -0,0 +1,22 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/detail/align.hpp"
+
+#include "wpi/memory/detail/ilog2.hpp"
+
+using namespace wpi::memory;
+using namespace detail;
+
+bool wpi::memory::detail::is_aligned(void* ptr, std::size_t alignment) noexcept
+{
+    WPI_MEMORY_ASSERT(is_valid_alignment(alignment));
+    auto address = reinterpret_cast<std::uintptr_t>(ptr);
+    return address % alignment == 0u;
+}
+
+std::size_t wpi::memory::detail::alignment_for(std::size_t size) noexcept
+{
+    return size >= max_alignment ? max_alignment : (std::size_t(1) << ilog2(size));
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/detail/assert.cpp b/wpiutil/src/main/native/thirdparty/memory/src/detail/assert.cpp
new file mode 100644
index 0000000..497f7f8
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/detail/assert.cpp
@@ -0,0 +1,34 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/detail/assert.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <cstdio>
+#endif
+
+#include <cstdlib>
+
+#include "wpi/memory/error.hpp"
+
+using namespace wpi::memory;
+using namespace detail;
+
+void detail::handle_failed_assert(const char* msg, const char* file, int line,
+                                  const char* fnc) noexcept
+{
+#if WPI_HOSTED_IMPLEMENTATION
+    std::fprintf(stderr, "[%s] Assertion failure in function %s (%s:%d): %s.\n",
+                 WPI_MEMORY_LOG_PREFIX, fnc, file, line, msg);
+#endif
+    std::abort();
+}
+
+void detail::handle_warning(const char* msg, const char* file, int line, const char* fnc) noexcept
+{
+#if WPI_HOSTED_IMPLEMENTATION
+    std::fprintf(stderr, "[%s] Warning triggered in function %s (%s:%d): %s.\n",
+                 WPI_MEMORY_LOG_PREFIX, fnc, file, line, msg);
+#endif
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/detail/debug_helpers.cpp b/wpiutil/src/main/native/thirdparty/memory/src/detail/debug_helpers.cpp
new file mode 100644
index 0000000..b5afb20
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/detail/debug_helpers.cpp
@@ -0,0 +1,87 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/detail/debug_helpers.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <cstring>
+#endif
+
+#include "wpi/memory/debugging.hpp"
+
+using namespace wpi::memory;
+using namespace detail;
+
+#if WPI_MEMORY_DEBUG_FILL
+void detail::debug_fill(void* memory, std::size_t size, debug_magic m) noexcept
+{
+#if WPI_HOSTED_IMPLEMENTATION
+    std::memset(memory, static_cast<int>(m), size);
+#else
+    // do the naive loop :(
+    auto ptr = static_cast<unsigned char*>(memory);
+    for (std::size_t i = 0u; i != size; ++i)
+        *ptr++ = static_cast<unsigned char>(m);
+#endif
+}
+
+void* detail::debug_is_filled(void* memory, std::size_t size, debug_magic m) noexcept
+{
+    auto byte = static_cast<unsigned char*>(memory);
+    for (auto end = byte + size; byte != end; ++byte)
+        if (*byte != static_cast<unsigned char>(m))
+            return byte;
+    return nullptr;
+}
+
+void* detail::debug_fill_new(void* memory, std::size_t node_size, std::size_t fence_size) noexcept
+{
+    if (!debug_fence_size)
+        fence_size = 0u; // force override of fence_size
+
+    auto mem = static_cast<char*>(memory);
+    debug_fill(mem, fence_size, debug_magic::fence_memory);
+
+    mem += fence_size;
+    debug_fill(mem, node_size, debug_magic::new_memory);
+
+    debug_fill(mem + node_size, fence_size, debug_magic::fence_memory);
+
+    return mem;
+}
+
+void* detail::debug_fill_free(void* memory, std::size_t node_size, std::size_t fence_size) noexcept
+{
+    if (!debug_fence_size)
+        fence_size = 0u; // force override of fence_size
+
+    debug_fill(memory, node_size, debug_magic::freed_memory);
+
+    auto pre_fence = static_cast<unsigned char*>(memory) - fence_size;
+    if (auto pre_dirty = debug_is_filled(pre_fence, fence_size, debug_magic::fence_memory))
+        get_buffer_overflow_handler()(memory, node_size, pre_dirty);
+
+    auto post_mem = static_cast<unsigned char*>(memory) + node_size;
+    if (auto post_dirty = debug_is_filled(post_mem, fence_size, debug_magic::fence_memory))
+        get_buffer_overflow_handler()(memory, node_size, post_dirty);
+
+    return pre_fence;
+}
+
+void detail::debug_fill_internal(void* memory, std::size_t size, bool free) noexcept
+{
+    debug_fill(memory, size,
+               free ? debug_magic::internal_freed_memory : debug_magic::internal_memory);
+}
+#endif
+
+void detail::debug_handle_invalid_ptr(const allocator_info& info, void* ptr)
+{
+    get_invalid_pointer_handler()(info, ptr);
+}
+
+void detail::debug_handle_memory_leak(const allocator_info& info, std::ptrdiff_t amount)
+{
+    get_leak_handler()(info, amount);
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list.cpp b/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list.cpp
new file mode 100644
index 0000000..2ca7034
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list.cpp
@@ -0,0 +1,557 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/detail/free_list.hpp"
+
+#include "wpi/memory/detail/align.hpp"
+#include "wpi/memory/detail/debug_helpers.hpp"
+#include "wpi/memory/detail/assert.hpp"
+#include "wpi/memory/debugging.hpp"
+#include "wpi/memory/error.hpp"
+
+#include "free_list_utils.hpp"
+
+using namespace wpi::memory;
+using namespace detail;
+
+namespace
+{
+    // i.e. array
+    struct interval
+    {
+        char* prev;  // last before
+        char* first; // first in
+        char* last;  // last in
+        char* next;  // first after
+
+        // number of nodes in the interval
+        std::size_t size(std::size_t node_size) const noexcept
+        {
+            // last is inclusive, so add actual_size to it
+            // note: cannot use next, might not be directly after
+            auto end = last + node_size;
+            WPI_MEMORY_ASSERT(static_cast<std::size_t>(end - first) % node_size == 0u);
+            return static_cast<std::size_t>(end - first) / node_size;
+        }
+    };
+
+    // searches for n consecutive bytes
+    // begin and end are the proxy nodes
+    // assumes list is not empty
+    // similar to list_search_array()
+    interval list_search_array(char* first, std::size_t bytes_needed,
+                               std::size_t node_size) noexcept
+    {
+        interval i;
+        i.prev  = nullptr;
+        i.first = first;
+        // i.last/next are used as iterator for the end of the interval
+        i.last = first;
+        i.next = list_get_next(first);
+
+        auto bytes_so_far = node_size;
+        while (i.next)
+        {
+            if (i.last + node_size != i.next) // not continous
+            {
+                // restart at next
+                i.prev  = i.last;
+                i.first = i.next;
+                i.last  = i.next;
+                i.next  = list_get_next(i.last);
+
+                bytes_so_far = node_size;
+            }
+            else
+            {
+                // extend interval
+                auto new_next = list_get_next(i.next);
+                i.last        = i.next;
+                i.next        = new_next;
+
+                bytes_so_far += node_size;
+                if (bytes_so_far >= bytes_needed)
+                    return i;
+            }
+        }
+        // not enough continuous space
+        return {nullptr, nullptr, nullptr, nullptr};
+    }
+
+    // similar to list_search_array()
+    // begin/end are proxy nodes
+    interval xor_list_search_array(char* begin, char* end, std::size_t bytes_needed,
+                                   std::size_t node_size) noexcept
+    {
+        interval i;
+        i.prev  = begin;
+        i.first = xor_list_get_other(begin, nullptr);
+        // i.last/next are used as iterator for the end of the interval
+        i.last = i.first;
+        i.next = xor_list_get_other(i.last, i.prev);
+
+        auto bytes_so_far = node_size;
+        while (i.next != end)
+        {
+            if (i.last + node_size != i.next) // not continous
+            {
+                // restart at i.next
+                i.prev  = i.last;
+                i.first = i.next;
+                i.last  = i.next;
+                i.next  = xor_list_get_other(i.first, i.prev);
+
+                bytes_so_far = node_size;
+            }
+            else
+            {
+                // extend interval
+                auto new_next = xor_list_get_other(i.next, i.last);
+                i.last        = i.next;
+                i.next        = new_next;
+
+                bytes_so_far += node_size;
+                if (bytes_so_far >= bytes_needed)
+                    return i;
+            }
+        }
+        // not enough continuous space
+        return {nullptr, nullptr, nullptr, nullptr};
+    }
+} // namespace
+
+constexpr std::size_t free_memory_list::min_element_size;
+constexpr std::size_t free_memory_list::min_element_alignment;
+
+free_memory_list::free_memory_list(std::size_t node_size) noexcept
+: first_(nullptr),
+  node_size_(node_size > min_element_size ? node_size : min_element_size),
+  capacity_(0u)
+{
+}
+
+free_memory_list::free_memory_list(std::size_t node_size, void* mem, std::size_t size) noexcept
+: free_memory_list(node_size)
+{
+    insert(mem, size);
+}
+
+free_memory_list::free_memory_list(free_memory_list&& other) noexcept
+: first_(other.first_), node_size_(other.node_size_), capacity_(other.capacity_)
+{
+    other.first_    = nullptr;
+    other.capacity_ = 0u;
+}
+
+free_memory_list& free_memory_list::operator=(free_memory_list&& other) noexcept
+{
+    free_memory_list tmp(detail::move(other));
+    swap(*this, tmp);
+    return *this;
+}
+
+void wpi::memory::detail::swap(free_memory_list& a, free_memory_list& b) noexcept
+{
+    detail::adl_swap(a.first_, b.first_);
+    detail::adl_swap(a.node_size_, b.node_size_);
+    detail::adl_swap(a.capacity_, b.capacity_);
+}
+
+void free_memory_list::insert(void* mem, std::size_t size) noexcept
+{
+    WPI_MEMORY_ASSERT(mem);
+    WPI_MEMORY_ASSERT(is_aligned(mem, alignment()));
+    detail::debug_fill_internal(mem, size, false);
+
+    insert_impl(mem, size);
+}
+
+void* free_memory_list::allocate() noexcept
+{
+    WPI_MEMORY_ASSERT(!empty());
+    --capacity_;
+
+    auto mem = first_;
+    first_   = list_get_next(first_);
+    return detail::debug_fill_new(mem, node_size_, 0);
+}
+
+void* free_memory_list::allocate(std::size_t n) noexcept
+{
+    WPI_MEMORY_ASSERT(!empty());
+    if (n <= node_size_)
+        return allocate();
+
+    auto i = list_search_array(first_, n, node_size_);
+    if (i.first == nullptr)
+        return nullptr;
+
+    if (i.prev)
+        list_set_next(i.prev, i.next); // change next from previous to first after
+    else
+        first_ = i.next;
+    capacity_ -= i.size(node_size_);
+
+    return detail::debug_fill_new(i.first, n, 0);
+}
+
+void free_memory_list::deallocate(void* ptr) noexcept
+{
+    ++capacity_;
+
+    auto node = static_cast<char*>(detail::debug_fill_free(ptr, node_size_, 0));
+    list_set_next(node, first_);
+    first_ = node;
+}
+
+void free_memory_list::deallocate(void* ptr, std::size_t n) noexcept
+{
+    if (n <= node_size_)
+        deallocate(ptr);
+    else
+    {
+        auto mem = detail::debug_fill_free(ptr, n, 0);
+        insert_impl(mem, n);
+    }
+}
+
+std::size_t free_memory_list::alignment() const noexcept
+{
+    return alignment_for(node_size_);
+}
+
+void free_memory_list::insert_impl(void* mem, std::size_t size) noexcept
+{
+    auto no_nodes = size / node_size_;
+    WPI_MEMORY_ASSERT(no_nodes > 0);
+
+    auto cur = static_cast<char*>(mem);
+    for (std::size_t i = 0u; i != no_nodes - 1; ++i)
+    {
+        list_set_next(cur, cur + node_size_);
+        cur += node_size_;
+    }
+    list_set_next(cur, first_);
+    first_ = static_cast<char*>(mem);
+
+    capacity_ += no_nodes;
+}
+
+namespace
+{
+    // converts a block into a linked list
+    void xor_link_block(void* memory, std::size_t node_size, std::size_t no_nodes, char* prev,
+                        char* next) noexcept
+    {
+        auto cur = static_cast<char*>(memory);
+        xor_list_change(prev, next, cur); // change next pointer of prev
+
+        auto last_cur = prev;
+        for (std::size_t i = 0u; i != no_nodes - 1; ++i)
+        {
+            xor_list_set(cur, last_cur,
+                         cur + node_size); // cur gets last_cur and next node in continous memory
+            last_cur = cur;
+            cur += node_size;
+        }
+        xor_list_set(cur, last_cur, next); // last memory node gets next as next
+        xor_list_change(next, prev, cur);  // change prev pointer of next
+    }
+
+    struct pos
+    {
+        char *prev, *next;
+    };
+
+    // finds position to insert memory to keep list ordered
+    // first_prev -> first -> ... (memory somewhere here) ... -> last -> last_next
+    pos find_pos_interval(const allocator_info& info, char* memory, char* first_prev, char* first,
+                          char* last, char* last_next) noexcept
+    {
+        // note: first_prev/last_next can be the proxy nodes, then first_prev isn't necessarily less than first!
+        WPI_MEMORY_ASSERT(less(first, memory) && less(memory, last));
+
+        // need to insert somewhere in the middle
+        // search through the entire list
+        // search from both ends at once
+        auto cur_forward  = first;
+        auto prev_forward = first_prev;
+
+        auto cur_backward  = last;
+        auto prev_backward = last_next;
+
+        do
+        {
+            if (greater(cur_forward, memory))
+                return {prev_forward, cur_forward};
+            else if (less(cur_backward, memory))
+                // the next position is the previous backwards pointer
+                return {cur_backward, prev_backward};
+            debug_check_double_dealloc([&]
+                                       { return cur_forward != memory && cur_backward != memory; },
+                                       info, memory);
+            xor_list_iter_next(cur_forward, prev_forward);
+            xor_list_iter_next(cur_backward, prev_backward);
+        } while (less(prev_forward, prev_backward));
+
+        // ran outside of list
+        debug_check_double_dealloc([] { return false; }, info, memory);
+        return {nullptr, nullptr};
+    }
+
+    // finds the position in the entire list
+    pos find_pos(const allocator_info& info, char* memory, char* begin_node, char* end_node,
+                 char* last_dealloc, char* last_dealloc_prev) noexcept
+    {
+        auto first = xor_list_get_other(begin_node, nullptr);
+        auto last  = xor_list_get_other(end_node, nullptr);
+
+        if (greater(first, memory))
+            // insert at front
+            return {begin_node, first};
+        else if (less(last, memory))
+            // insert at the end
+            return {last, end_node};
+        else if (less(last_dealloc_prev, memory) && less(memory, last_dealloc))
+            // insert before last_dealloc
+            return {last_dealloc_prev, last_dealloc};
+        else if (less(memory, last_dealloc))
+            // insert into [first, last_dealloc_prev]
+            return find_pos_interval(info, memory, begin_node, first, last_dealloc_prev,
+                                     last_dealloc);
+        else if (greater(memory, last_dealloc))
+            // insert into (last_dealloc, last]
+            return find_pos_interval(info, memory, last_dealloc_prev, last_dealloc, last, end_node);
+
+        WPI_MEMORY_UNREACHABLE("memory must be in some half or outside");
+        return {nullptr, nullptr};
+    }
+} // namespace
+
+constexpr std::size_t ordered_free_memory_list::min_element_size;
+constexpr std::size_t ordered_free_memory_list::min_element_alignment;
+
+ordered_free_memory_list::ordered_free_memory_list(std::size_t node_size) noexcept
+: node_size_(node_size > min_element_size ? node_size : min_element_size),
+  capacity_(0u),
+  last_dealloc_(end_node()),
+  last_dealloc_prev_(begin_node())
+{
+    xor_list_set(begin_node(), nullptr, end_node());
+    xor_list_set(end_node(), begin_node(), nullptr);
+}
+
+ordered_free_memory_list::ordered_free_memory_list(ordered_free_memory_list&& other) noexcept
+: node_size_(other.node_size_), capacity_(other.capacity_)
+{
+    if (!other.empty())
+    {
+        auto first = xor_list_get_other(other.begin_node(), nullptr);
+        auto last  = xor_list_get_other(other.end_node(), nullptr);
+
+        xor_list_set(begin_node(), nullptr, first);
+        xor_list_change(first, other.begin_node(), begin_node());
+        xor_list_change(last, other.end_node(), end_node());
+        xor_list_set(end_node(), last, nullptr);
+
+        other.capacity_ = 0u;
+        xor_list_set(other.begin_node(), nullptr, other.end_node());
+        xor_list_set(other.end_node(), other.begin_node(), nullptr);
+    }
+    else
+    {
+        xor_list_set(begin_node(), nullptr, end_node());
+        xor_list_set(end_node(), begin_node(), nullptr);
+    }
+
+    // for programming convenience, last_dealloc is reset
+    last_dealloc_prev_ = begin_node();
+    last_dealloc_      = xor_list_get_other(last_dealloc_prev_, nullptr);
+}
+
+void wpi::memory::detail::swap(ordered_free_memory_list& a,
+                                     ordered_free_memory_list& b) noexcept
+{
+    auto a_first = xor_list_get_other(a.begin_node(), nullptr);
+    auto a_last  = xor_list_get_other(a.end_node(), nullptr);
+
+    auto b_first = xor_list_get_other(b.begin_node(), nullptr);
+    auto b_last  = xor_list_get_other(b.end_node(), nullptr);
+
+    if (!a.empty())
+    {
+        xor_list_set(b.begin_node(), nullptr, a_first);
+        xor_list_change(a_first, a.begin_node(), b.begin_node());
+        xor_list_change(a_last, a.end_node(), b.end_node());
+        xor_list_set(b.end_node(), a_last, nullptr);
+    }
+    else
+    {
+        xor_list_set(b.begin_node(), nullptr, b.end_node());
+        xor_list_set(b.end_node(), b.begin_node(), nullptr);
+    }
+
+    if (!b.empty())
+    {
+        xor_list_set(a.begin_node(), nullptr, b_first);
+        xor_list_change(b_first, b.begin_node(), a.begin_node());
+        xor_list_change(b_last, b.end_node(), a.end_node());
+        xor_list_set(a.end_node(), b_last, nullptr);
+    }
+    else
+    {
+        xor_list_set(a.begin_node(), nullptr, a.end_node());
+        xor_list_set(a.end_node(), a.begin_node(), nullptr);
+    }
+
+    detail::adl_swap(a.node_size_, b.node_size_);
+    detail::adl_swap(a.capacity_, b.capacity_);
+
+    // for programming convenience, last_dealloc is reset
+    a.last_dealloc_prev_ = a.begin_node();
+    a.last_dealloc_      = xor_list_get_other(a.last_dealloc_prev_, nullptr);
+
+    b.last_dealloc_prev_ = b.begin_node();
+    b.last_dealloc_      = xor_list_get_other(b.last_dealloc_prev_, nullptr);
+}
+
+void ordered_free_memory_list::insert(void* mem, std::size_t size) noexcept
+{
+    WPI_MEMORY_ASSERT(mem);
+    WPI_MEMORY_ASSERT(is_aligned(mem, alignment()));
+    detail::debug_fill_internal(mem, size, false);
+
+    insert_impl(mem, size);
+}
+
+void* ordered_free_memory_list::allocate() noexcept
+{
+    WPI_MEMORY_ASSERT(!empty());
+
+    // remove first node
+    auto prev = begin_node();
+    auto node = xor_list_get_other(prev, nullptr);
+    auto next = xor_list_get_other(node, prev);
+
+    xor_list_set(prev, nullptr, next); // link prev to next
+    xor_list_change(next, node, prev); // change prev of next
+    --capacity_;
+
+    if (node == last_dealloc_)
+    {
+        // move last_dealloc_ one further in
+        last_dealloc_ = next;
+        WPI_MEMORY_ASSERT(last_dealloc_prev_ == prev);
+    }
+    else if (node == last_dealloc_prev_)
+    {
+        // now the previous node is the node before ours
+        last_dealloc_prev_ = prev;
+        WPI_MEMORY_ASSERT(last_dealloc_ == next);
+    }
+
+    return detail::debug_fill_new(node, node_size_, 0);
+}
+
+void* ordered_free_memory_list::allocate(std::size_t n) noexcept
+{
+    WPI_MEMORY_ASSERT(!empty());
+
+    if (n <= node_size_)
+        return allocate();
+
+    auto i = xor_list_search_array(begin_node(), end_node(), n, node_size_);
+    if (i.first == nullptr)
+        return nullptr;
+
+    xor_list_change(i.prev, i.first, i.next); // change next pointer from i.prev to i.next
+    xor_list_change(i.next, i.last, i.prev);  // change prev pointer from i.next to i.prev
+    capacity_ -= i.size(node_size_);
+
+    // if last_dealloc_ points into the array being removed
+    if ((less_equal(i.first, last_dealloc_) && less_equal(last_dealloc_, i.last)))
+    {
+        // move last_dealloc just outside range
+        last_dealloc_      = i.next;
+        last_dealloc_prev_ = i.prev;
+    }
+    // if the previous deallocation is the last element of the array
+    else if (last_dealloc_prev_ == i.last)
+    {
+        // it is now the last element before the array
+        WPI_MEMORY_ASSERT(last_dealloc_ == i.next);
+        last_dealloc_prev_ = i.prev;
+    }
+
+    return detail::debug_fill_new(i.first, n, 0);
+}
+
+void ordered_free_memory_list::deallocate(void* ptr) noexcept
+{
+    auto node = static_cast<char*>(debug_fill_free(ptr, node_size_, 0));
+
+    auto p =
+        find_pos(allocator_info(WPI_MEMORY_LOG_PREFIX "::detail::ordered_free_memory_list",
+                                this),
+                 node, begin_node(), end_node(), last_dealloc_, last_dealloc_prev_);
+
+    xor_list_insert(node, p.prev, p.next);
+    ++capacity_;
+
+    last_dealloc_      = node;
+    last_dealloc_prev_ = p.prev;
+}
+
+void ordered_free_memory_list::deallocate(void* ptr, std::size_t n) noexcept
+{
+    if (n <= node_size_)
+        deallocate(ptr);
+    else
+    {
+        auto mem  = detail::debug_fill_free(ptr, n, 0);
+        auto prev = insert_impl(mem, n);
+
+        last_dealloc_      = static_cast<char*>(mem);
+        last_dealloc_prev_ = prev;
+    }
+}
+
+std::size_t ordered_free_memory_list::alignment() const noexcept
+{
+    return alignment_for(node_size_);
+}
+
+char* ordered_free_memory_list::insert_impl(void* mem, std::size_t size) noexcept
+{
+    auto no_nodes = size / node_size_;
+    WPI_MEMORY_ASSERT(no_nodes > 0);
+
+    auto p =
+        find_pos(allocator_info(WPI_MEMORY_LOG_PREFIX "::detail::ordered_free_memory_list",
+                                this),
+                 static_cast<char*>(mem), begin_node(), end_node(), last_dealloc_,
+                 last_dealloc_prev_);
+
+    xor_link_block(mem, node_size_, no_nodes, p.prev, p.next);
+    capacity_ += no_nodes;
+
+    if (p.prev == last_dealloc_prev_)
+    {
+        last_dealloc_ = static_cast<char*>(mem);
+    }
+
+    return p.prev;
+}
+
+char* ordered_free_memory_list::begin_node() noexcept
+{
+    void* mem = &begin_proxy_;
+    return static_cast<char*>(mem);
+}
+
+char* ordered_free_memory_list::end_node() noexcept
+{
+    void* mem = &end_proxy_;
+    return static_cast<char*>(mem);
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list_array.cpp b/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list_array.cpp
new file mode 100644
index 0000000..f4658da
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list_array.cpp
@@ -0,0 +1,22 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/detail/free_list_array.hpp"
+
+#include "wpi/memory/detail/assert.hpp"
+#include "wpi/memory/detail/ilog2.hpp"
+
+using namespace wpi::memory;
+using namespace detail;
+
+std::size_t log2_access_policy::index_from_size(std::size_t size) noexcept
+{
+    WPI_MEMORY_ASSERT_MSG(size, "size must not be zero");
+    return ilog2_ceil(size);
+}
+
+std::size_t log2_access_policy::size_from_index(std::size_t index) noexcept
+{
+    return std::size_t(1) << index;
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list_utils.hpp b/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list_utils.hpp
new file mode 100644
index 0000000..a752837
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/detail/free_list_utils.hpp
@@ -0,0 +1,149 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#ifndef WPI_MEMORY_SRC_DETAIL_FREE_LIST_UTILS_HPP_INCLUDED
+#define WPI_MEMORY_SRC_DETAIL_FREE_LIST_UTILS_HPP_INCLUDED
+
+#include <cstdint>
+
+#include "wpi/memory/config.hpp"
+#include "wpi/memory/detail/align.hpp"
+#include "wpi/memory/detail/assert.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <cstring>
+#include <functional>
+#endif
+
+namespace wpi
+{
+    namespace memory
+    {
+        namespace detail
+        {
+            //=== storage ===///
+            // reads stored integer value
+            inline std::uintptr_t get_int(void* address) noexcept
+            {
+                WPI_MEMORY_ASSERT(address);
+                std::uintptr_t res;
+#if WPI_HOSTED_IMPLEMENTATION
+                std::memcpy(&res, address, sizeof(std::uintptr_t));
+#else
+                auto mem = static_cast<char*>(static_cast<void*>(&res));
+                for (auto i = 0u; i != sizeof(std::uintptr_t); ++i)
+                    mem[i] = static_cast<char*>(address)[i];
+#endif
+                return res;
+            }
+
+            // sets stored integer value
+            inline void set_int(void* address, std::uintptr_t i) noexcept
+            {
+                WPI_MEMORY_ASSERT(address);
+#if WPI_HOSTED_IMPLEMENTATION
+                std::memcpy(address, &i, sizeof(std::uintptr_t));
+#else
+                auto mem = static_cast<char*>(static_cast<void*>(&i));
+                for (auto i = 0u; i != sizeof(std::uintptr_t); ++i)
+                    static_cast<char*>(address)[i] = mem[i];
+#endif
+            }
+
+            // pointer to integer
+            inline std::uintptr_t to_int(char* ptr) noexcept
+            {
+                return reinterpret_cast<std::uintptr_t>(ptr);
+            }
+
+            // integer to pointer
+            inline char* from_int(std::uintptr_t i) noexcept
+            {
+                return reinterpret_cast<char*>(i);
+            }
+
+            //=== intrusive linked list ===//
+            // reads a stored pointer value
+            inline char* list_get_next(void* address) noexcept
+            {
+                return from_int(get_int(address));
+            }
+
+            // stores a pointer value
+            inline void list_set_next(void* address, char* ptr) noexcept
+            {
+                set_int(address, to_int(ptr));
+            }
+
+            //=== intrusive xor linked list ===//
+            // returns the other pointer given one pointer
+            inline char* xor_list_get_other(void* address, char* prev_or_next) noexcept
+            {
+                return from_int(get_int(address) ^ to_int(prev_or_next));
+            }
+
+            // sets the next and previous pointer (order actually does not matter)
+            inline void xor_list_set(void* address, char* prev, char* next) noexcept
+            {
+                set_int(address, to_int(prev) ^ to_int(next));
+            }
+
+            // changes other pointer given one pointer
+            inline void xor_list_change(void* address, char* old_ptr, char* new_ptr) noexcept
+            {
+                WPI_MEMORY_ASSERT(address);
+                auto other = xor_list_get_other(address, old_ptr);
+                xor_list_set(address, other, new_ptr);
+            }
+
+            // advances a pointer pair forward/backward
+            inline void xor_list_iter_next(char*& cur, char*& prev) noexcept
+            {
+                auto next = xor_list_get_other(cur, prev);
+                prev      = cur;
+                cur       = next;
+            }
+
+            // links new node between prev and next
+            inline void xor_list_insert(char* new_node, char* prev, char* next) noexcept
+            {
+                xor_list_set(new_node, prev, next);
+                xor_list_change(prev, next, new_node); // change prev's next to new_node
+                xor_list_change(next, prev, new_node); // change next's prev to new_node
+            }
+
+            //=== sorted list utils ===//
+            // if std::less/std::greater not available compare integer representation and hope it works
+            inline bool less(void* a, void* b) noexcept
+            {
+#if WPI_HOSTED_IMPLEMENTATION
+                return std::less<void*>()(a, b);
+#else
+                return to_int(a) < to_int(b);
+#endif
+            }
+
+            inline bool less_equal(void* a, void* b) noexcept
+            {
+                return a == b || less(a, b);
+            }
+
+            inline bool greater(void* a, void* b) noexcept
+            {
+#if WPI_HOSTED_IMPLEMENTATION
+                return std::greater<void*>()(a, b);
+#else
+                return to_int(a) < to_int(b);
+#endif
+            }
+
+            inline bool greater_equal(void* a, void* b) noexcept
+            {
+                return a == b || greater(a, b);
+            }
+        } // namespace detail
+    }     // namespace memory
+} // namespace wpi
+
+#endif // WPI_MEMORY_SRC_DETAIL_FREE_LIST_UTILS_HPP_INCLUDED
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/detail/small_free_list.cpp b/wpiutil/src/main/native/thirdparty/memory/src/detail/small_free_list.cpp
new file mode 100644
index 0000000..3508daa
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/detail/small_free_list.cpp
@@ -0,0 +1,395 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/detail/small_free_list.hpp"
+
+#include <new>
+
+#include "wpi/memory/detail/debug_helpers.hpp"
+#include "wpi/memory/detail/assert.hpp"
+#include "wpi/memory/error.hpp"
+
+#include "free_list_utils.hpp"
+
+using namespace wpi::memory;
+using namespace detail;
+
+struct wpi::memory::detail::chunk : chunk_base
+{
+    // gives it the size of the memory block it is created in and the size of a node
+    chunk(std::size_t total_memory, std::size_t node_size) noexcept
+    : chunk_base(static_cast<unsigned char>((total_memory - chunk_memory_offset) / node_size))
+    {
+        static_assert(sizeof(chunk) == sizeof(chunk_base), "chunk must not have members");
+        WPI_MEMORY_ASSERT((total_memory - chunk_memory_offset) / node_size
+                                <= chunk_max_nodes);
+        WPI_MEMORY_ASSERT(capacity > 0);
+        auto p = list_memory();
+        for (unsigned char i = 0u; i != no_nodes; p += node_size)
+            *p = ++i;
+    }
+
+    // returns memory of the free list
+    unsigned char* list_memory() noexcept
+    {
+        auto mem = static_cast<void*>(this);
+        return static_cast<unsigned char*>(mem) + chunk_memory_offset;
+    }
+
+    // returns the nth node
+    unsigned char* node_memory(unsigned char i, std::size_t node_size) noexcept
+    {
+        WPI_MEMORY_ASSERT(i < no_nodes);
+        return list_memory() + i * node_size;
+    }
+
+    // checks whether a node came from this chunk
+    bool from(unsigned char* node, std::size_t node_size) noexcept
+    {
+        auto begin = list_memory();
+        auto end   = list_memory() + no_nodes * node_size;
+        return (begin <= node) & (node < end);
+    }
+
+    // checks whether a node is already in this chunk
+    bool contains(unsigned char* node, std::size_t node_size) noexcept
+    {
+        auto cur_index = first_free;
+        while (cur_index != no_nodes)
+        {
+            auto cur_mem = node_memory(cur_index, node_size);
+            if (cur_mem == node)
+                return true;
+            cur_index = *cur_mem;
+        }
+        return false;
+    }
+
+    // allocates a single node
+    // chunk most not be empty
+    unsigned char* allocate(std::size_t node_size) noexcept
+    {
+        --capacity;
+
+        auto node  = node_memory(first_free, node_size);
+        first_free = *node;
+        return node;
+    }
+
+    // deallocates a single node given its address and index
+    // it must be from this chunk
+    void deallocate(unsigned char* node, unsigned char node_index) noexcept
+    {
+        ++capacity;
+
+        *node      = first_free;
+        first_free = node_index;
+    }
+};
+
+namespace
+{
+    // converts a chunk_base to a chunk (if it is one)
+    chunk* make_chunk(chunk_base* c) noexcept
+    {
+        return static_cast<chunk*>(c);
+    }
+
+    // same as above but also requires a certain size
+    chunk* make_chunk(chunk_base* c, std::size_t size_needed) noexcept
+    {
+        WPI_MEMORY_ASSERT(size_needed <= chunk_max_nodes);
+        return c->capacity >= size_needed ? make_chunk(c) : nullptr;
+    }
+
+    // checks if memory was from a chunk, assumes chunk isn't proxy
+    chunk* from_chunk(chunk_base* c, unsigned char* node, std::size_t node_size) noexcept
+    {
+        auto res = make_chunk(c);
+        return res->from(node, node_size) ? res : nullptr;
+    }
+
+    // inserts already interconnected chunks into the list
+    // list will be kept ordered
+    void insert_chunks(chunk_base* list, chunk_base* begin, chunk_base* end) noexcept
+    {
+        WPI_MEMORY_ASSERT(begin && end);
+
+        if (list->next == list) // empty
+        {
+            begin->prev = list;
+            end->next   = list->next;
+            list->next  = begin;
+            list->prev  = end;
+        }
+        else if (less(list->prev, begin)) // insert at end
+        {
+            list->prev->next = begin;
+            begin->prev      = list->prev;
+            end->next        = list;
+            list->prev       = end;
+        }
+        else
+        {
+            auto prev = list;
+            auto cur  = list->next;
+            while (less(cur, begin))
+            {
+                prev = cur;
+                cur  = cur->next;
+            }
+            WPI_MEMORY_ASSERT(greater(cur, end));
+            WPI_MEMORY_ASSERT(prev == list || less(prev, begin));
+            prev->next  = begin;
+            begin->prev = prev;
+            end->next   = cur;
+            cur->prev   = end;
+        }
+    }
+} // namespace
+
+constexpr std::size_t small_free_memory_list::min_element_size;
+constexpr std::size_t small_free_memory_list::min_element_alignment;
+
+small_free_memory_list::small_free_memory_list(std::size_t node_size) noexcept
+: node_size_(node_size), capacity_(0u), alloc_chunk_(&base_), dealloc_chunk_(&base_)
+{
+}
+
+small_free_memory_list::small_free_memory_list(std::size_t node_size, void* mem,
+                                               std::size_t size) noexcept
+: small_free_memory_list(node_size)
+{
+    insert(mem, size);
+}
+
+small_free_memory_list::small_free_memory_list(small_free_memory_list&& other) noexcept
+: node_size_(other.node_size_),
+  capacity_(other.capacity_),
+  // reset markers for simplicity
+  alloc_chunk_(&base_),
+  dealloc_chunk_(&base_)
+{
+    if (!other.empty())
+    {
+        base_.next             = other.base_.next;
+        base_.prev             = other.base_.prev;
+        other.base_.next->prev = &base_;
+        other.base_.prev->next = &base_;
+
+        other.base_.next = &other.base_;
+        other.base_.prev = &other.base_;
+        other.capacity_  = 0u;
+    }
+    else
+    {
+        base_.next = &base_;
+        base_.prev = &base_;
+    }
+}
+
+void wpi::memory::detail::swap(small_free_memory_list& a, small_free_memory_list& b) noexcept
+{
+    auto b_next = b.base_.next;
+    auto b_prev = b.base_.prev;
+
+    if (!a.empty())
+    {
+        b.base_.next       = a.base_.next;
+        b.base_.prev       = a.base_.prev;
+        b.base_.next->prev = &b.base_;
+        b.base_.prev->next = &b.base_;
+    }
+    else
+    {
+        b.base_.next = &b.base_;
+        b.base_.prev = &b.base_;
+    }
+
+    if (!b.empty())
+    {
+        a.base_.next       = b_next;
+        a.base_.prev       = b_prev;
+        a.base_.next->prev = &a.base_;
+        a.base_.prev->next = &a.base_;
+    }
+    else
+    {
+        a.base_.next = &a.base_;
+        a.base_.prev = &a.base_;
+    }
+
+    detail::adl_swap(a.node_size_, b.node_size_);
+    detail::adl_swap(a.capacity_, b.capacity_);
+
+    // reset markers for simplicity
+    a.alloc_chunk_ = a.dealloc_chunk_ = &a.base_;
+    b.alloc_chunk_ = b.dealloc_chunk_ = &b.base_;
+}
+
+void small_free_memory_list::insert(void* mem, std::size_t size) noexcept
+{
+    WPI_MEMORY_ASSERT(mem);
+    WPI_MEMORY_ASSERT(is_aligned(mem, max_alignment));
+    debug_fill_internal(mem, size, false);
+
+    auto total_chunk_size = chunk_memory_offset + node_size_ * chunk_max_nodes;
+    auto align_buffer     = align_offset(total_chunk_size, alignof(chunk));
+
+    auto no_chunks = size / (total_chunk_size + align_buffer);
+    auto remainder = size % (total_chunk_size + align_buffer);
+
+    auto memory          = static_cast<char*>(mem);
+    auto construct_chunk = [&](std::size_t total_memory, std::size_t node_size)
+    {
+        WPI_MEMORY_ASSERT(align_offset(memory, alignof(chunk)) == 0);
+        return ::new (static_cast<void*>(memory)) chunk(total_memory, node_size);
+    };
+
+    auto prev = static_cast<chunk_base*>(nullptr);
+    for (auto i = std::size_t(0); i != no_chunks; ++i)
+    {
+        auto c = construct_chunk(total_chunk_size, node_size_);
+
+        c->prev = prev;
+        if (prev)
+            prev->next = c;
+        prev = c;
+
+        memory += total_chunk_size;
+        memory += align_buffer;
+    }
+
+    auto new_nodes = no_chunks * chunk_max_nodes;
+    if (remainder >= chunk_memory_offset + node_size_) // at least one node
+    {
+        auto c = construct_chunk(remainder, node_size_);
+
+        c->prev = prev;
+        if (prev)
+            prev->next = c;
+        prev = c;
+
+        new_nodes += c->no_nodes;
+    }
+
+    WPI_MEMORY_ASSERT_MSG(new_nodes > 0, "memory block too small");
+    insert_chunks(&base_, static_cast<chunk_base*>(mem), prev);
+    capacity_ += new_nodes;
+}
+
+std::size_t small_free_memory_list::usable_size(std::size_t size) const noexcept
+{
+    auto total_chunk_size = chunk_memory_offset + node_size_ * chunk_max_nodes;
+    auto no_chunks        = size / total_chunk_size;
+    auto remainder        = size % total_chunk_size;
+
+    return no_chunks * chunk_max_nodes * node_size_
+           + (remainder > chunk_memory_offset ? remainder - chunk_memory_offset : 0u);
+}
+
+void* small_free_memory_list::allocate() noexcept
+{
+    auto chunk   = find_chunk_impl(1);
+    alloc_chunk_ = chunk;
+    WPI_MEMORY_ASSERT(chunk && chunk->capacity >= 1);
+
+    --capacity_;
+
+    auto mem = chunk->allocate(node_size_);
+    WPI_MEMORY_ASSERT(mem);
+    return detail::debug_fill_new(mem, node_size_, 0);
+}
+
+void small_free_memory_list::deallocate(void* mem) noexcept
+{
+    auto info =
+        allocator_info(WPI_MEMORY_LOG_PREFIX "::detail::small_free_memory_list", this);
+
+    auto node = static_cast<unsigned char*>(detail::debug_fill_free(mem, node_size_, 0));
+
+    auto chunk     = find_chunk_impl(node);
+    dealloc_chunk_ = chunk;
+    // memory was never allocated from list
+    detail::debug_check_pointer([&] { return chunk != nullptr; }, info, mem);
+
+    auto offset = static_cast<std::size_t>(node - chunk->list_memory());
+    // memory is not at the right position
+    debug_check_pointer([&] { return offset % node_size_ == 0u; }, info, mem);
+    // double-free
+    debug_check_double_dealloc([&] { return !chunk->contains(node, node_size_); }, info, mem);
+
+    auto index = offset / node_size_;
+    WPI_MEMORY_ASSERT(index < chunk->no_nodes);
+    chunk->deallocate(node, static_cast<unsigned char>(index));
+
+    ++capacity_;
+}
+
+std::size_t small_free_memory_list::alignment() const noexcept
+{
+    return alignment_for(node_size_);
+}
+
+chunk* small_free_memory_list::find_chunk_impl(std::size_t n) noexcept
+{
+    if (auto c = make_chunk(alloc_chunk_, n))
+        return c;
+    else if ((c = make_chunk(dealloc_chunk_, n)) != nullptr)
+        return c;
+
+    auto cur_forward  = alloc_chunk_->next;
+    auto cur_backward = alloc_chunk_->prev;
+
+    do
+    {
+        if (auto c = make_chunk(cur_forward, n))
+            return c;
+        else if ((c = make_chunk(cur_backward, n)) != nullptr)
+            return c;
+
+        cur_forward  = cur_forward->next;
+        cur_backward = cur_backward->prev;
+        WPI_MEMORY_ASSERT(cur_forward != alloc_chunk_);
+        WPI_MEMORY_ASSERT(cur_backward != alloc_chunk_);
+    } while (true);
+    WPI_MEMORY_UNREACHABLE("there is memory available somewhere...");
+    return nullptr;
+}
+
+chunk* small_free_memory_list::find_chunk_impl(unsigned char* node, chunk_base* first,
+                                               chunk_base* last) noexcept
+{
+    do
+    {
+        if (auto c = from_chunk(first, node, node_size_))
+            return c;
+        else if ((c = from_chunk(last, node, node_size_)) != nullptr)
+            return c;
+
+        first = first->next;
+        last  = last->prev;
+    } while (!greater(first, last));
+    return nullptr;
+}
+
+chunk* small_free_memory_list::find_chunk_impl(unsigned char* node) noexcept
+{
+    if (auto c = from_chunk(dealloc_chunk_, node, node_size_))
+        return c;
+    else if ((c = from_chunk(alloc_chunk_, node, node_size_)) != nullptr)
+        return c;
+    else if (less(dealloc_chunk_, node))
+    {
+        // node is in (dealloc_chunk_, base_.prev]
+        return find_chunk_impl(node, dealloc_chunk_->next, base_.prev);
+    }
+    else if (greater(dealloc_chunk_, node))
+    {
+        // node is in [base.next, dealloc_chunk_)
+        return find_chunk_impl(node, base_.next, dealloc_chunk_->prev);
+    }
+    WPI_MEMORY_UNREACHABLE("must be in one half");
+    return nullptr;
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/error.cpp b/wpiutil/src/main/native/thirdparty/memory/src/error.cpp
new file mode 100644
index 0000000..6261819
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/error.cpp
@@ -0,0 +1,106 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/error.hpp"
+
+#include <atomic>
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <cstdio>
+#endif
+
+using namespace wpi::memory;
+
+namespace
+{
+    void default_out_of_memory_handler(const allocator_info& info, std::size_t amount) noexcept
+    {
+#if WPI_HOSTED_IMPLEMENTATION
+        std::fprintf(stderr,
+                     "[%s] Allocator %s (at %p) ran out of memory trying to allocate %zu bytes.\n",
+                     WPI_MEMORY_LOG_PREFIX, info.name, info.allocator, amount);
+#endif
+    }
+
+    std::atomic<out_of_memory::handler> out_of_memory_h(default_out_of_memory_handler);
+} // namespace
+
+out_of_memory::handler out_of_memory::set_handler(out_of_memory::handler h)
+{
+    return out_of_memory_h.exchange(h ? h : default_out_of_memory_handler);
+}
+
+out_of_memory::handler out_of_memory::get_handler()
+{
+    return out_of_memory_h;
+}
+
+out_of_memory::out_of_memory(const allocator_info& info, std::size_t amount)
+: info_(info), amount_(amount)
+{
+    out_of_memory_h.load()(info, amount);
+}
+
+const char* out_of_memory::what() const noexcept
+{
+    return "low-level allocator is out of memory";
+}
+
+const char* out_of_fixed_memory::what() const noexcept
+{
+    return "fixed size allocator is out of memory";
+}
+
+namespace
+{
+    void default_bad_alloc_size_handler(const allocator_info& info, std::size_t passed,
+                                        std::size_t supported) noexcept
+    {
+#if WPI_HOSTED_IMPLEMENTATION
+        std::fprintf(stderr,
+                     "[%s] Allocator %s (at %p) received invalid size/alignment %zu, "
+                     "max supported is %zu\n",
+                     WPI_MEMORY_LOG_PREFIX, info.name, info.allocator, passed, supported);
+#endif
+    }
+
+    std::atomic<bad_allocation_size::handler> bad_alloc_size_h(default_bad_alloc_size_handler);
+} // namespace
+
+bad_allocation_size::handler bad_allocation_size::set_handler(bad_allocation_size::handler h)
+{
+    return bad_alloc_size_h.exchange(h ? h : default_bad_alloc_size_handler);
+}
+
+bad_allocation_size::handler bad_allocation_size::get_handler()
+{
+    return bad_alloc_size_h;
+}
+
+bad_allocation_size::bad_allocation_size(const allocator_info& info, std::size_t passed,
+                                         std::size_t supported)
+: info_(info), passed_(passed), supported_(supported)
+{
+    bad_alloc_size_h.load()(info_, passed_, supported_);
+}
+
+const char* bad_allocation_size::what() const noexcept
+{
+    return "allocation node size exceeds supported maximum of allocator";
+}
+
+const char* bad_node_size::what() const noexcept
+{
+    return "allocation node size exceeds supported maximum of allocator";
+}
+
+const char* bad_array_size::what() const noexcept
+{
+    return "allocation array size exceeds supported maximum of allocator";
+}
+
+const char* bad_alignment::what() const noexcept
+{
+    return "allocation alignment exceeds supported maximum of allocator";
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/heap_allocator.cpp b/wpiutil/src/main/native/thirdparty/memory/src/heap_allocator.cpp
new file mode 100644
index 0000000..0f559bd
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/heap_allocator.cpp
@@ -0,0 +1,85 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/heap_allocator.hpp"
+
+#include "wpi/memory/error.hpp"
+
+using namespace wpi::memory;
+
+#ifdef _WIN32
+#include <malloc.h>
+#include <windows.h>
+
+namespace
+{
+    HANDLE get_process_heap() noexcept
+    {
+        static auto heap = GetProcessHeap();
+        return heap;
+    }
+
+    std::size_t max_size() noexcept
+    {
+        return _HEAP_MAXREQ;
+    }
+} // namespace
+
+void* wpi::memory::heap_alloc(std::size_t size) noexcept
+{
+    return HeapAlloc(get_process_heap(), 0, size);
+}
+
+void wpi::memory::heap_dealloc(void* ptr, std::size_t) noexcept
+{
+    HeapFree(get_process_heap(), 0, ptr);
+}
+
+#elif WPI_HOSTED_IMPLEMENTATION
+#include <cstdlib>
+#include <memory>
+
+void* wpi::memory::heap_alloc(std::size_t size) noexcept
+{
+    return std::malloc(size);
+}
+
+void wpi::memory::heap_dealloc(void* ptr, std::size_t) noexcept
+{
+    std::free(ptr);
+}
+
+namespace
+{
+    std::size_t max_size() noexcept
+    {
+        return std::allocator_traits<std::allocator<char>>::max_size({});
+    }
+} // namespace
+#else
+// no implementation for heap_alloc/heap_dealloc
+
+namespace
+{
+    std::size_t max_size() noexcept
+    {
+        return std::size_t(-1);
+    }
+} // namespace
+#endif
+
+allocator_info detail::heap_allocator_impl::info() noexcept
+{
+    return {WPI_MEMORY_LOG_PREFIX "::heap_allocator", nullptr};
+}
+
+std::size_t detail::heap_allocator_impl::max_node_size() noexcept
+{
+    return max_size();
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class detail::lowlevel_allocator<detail::heap_allocator_impl>;
+template class wpi::memory::allocator_traits<heap_allocator>;
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/iteration_allocator.cpp b/wpiutil/src/main/native/thirdparty/memory/src/iteration_allocator.cpp
new file mode 100644
index 0000000..c174c13
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/iteration_allocator.cpp
@@ -0,0 +1,13 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/iteration_allocator.hpp"
+
+using namespace wpi::memory;
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class wpi::memory::iteration_allocator<2>;
+template class wpi::memory::allocator_traits<iteration_allocator<2>>;
+template class wpi::memory::composable_allocator_traits<iteration_allocator<2>>;
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/malloc_allocator.cpp b/wpiutil/src/main/native/thirdparty/memory/src/malloc_allocator.cpp
new file mode 100644
index 0000000..f54817a
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/malloc_allocator.cpp
@@ -0,0 +1,24 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/config.hpp"
+#if WPI_HOSTED_IMPLEMENTATION
+
+#include "wpi/memory/malloc_allocator.hpp"
+
+#include "wpi/memory/error.hpp"
+
+using namespace wpi::memory;
+
+allocator_info detail::malloc_allocator_impl::info() noexcept
+{
+    return {WPI_MEMORY_LOG_PREFIX "::malloc_allocator", nullptr};
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class detail::lowlevel_allocator<detail::malloc_allocator_impl>;
+template class wpi::memory::allocator_traits<malloc_allocator>;
+#endif
+
+#endif // WPI_HOSTED_IMPLEMENTATION
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/memory_arena.cpp b/wpiutil/src/main/native/thirdparty/memory/src/memory_arena.cpp
new file mode 100644
index 0000000..d8454be
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/memory_arena.cpp
@@ -0,0 +1,73 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/memory_arena.hpp"
+
+#include <new>
+
+#include "wpi/memory/detail/align.hpp"
+
+using namespace wpi::memory;
+using namespace detail;
+
+void memory_block_stack::push(allocated_mb block) noexcept
+{
+    WPI_MEMORY_ASSERT(block.size >= sizeof(node));
+    WPI_MEMORY_ASSERT(is_aligned(block.memory, max_alignment));
+    auto next = ::new (block.memory) node(head_, block.size - implementation_offset());
+    head_     = next;
+}
+
+memory_block_stack::allocated_mb memory_block_stack::pop() noexcept
+{
+    WPI_MEMORY_ASSERT(head_);
+    auto to_pop = head_;
+    head_       = head_->prev;
+    return {to_pop, to_pop->usable_size + implementation_offset()};
+}
+
+void memory_block_stack::steal_top(memory_block_stack& other) noexcept
+{
+    WPI_MEMORY_ASSERT(other.head_);
+    auto to_steal = other.head_;
+    other.head_   = other.head_->prev;
+
+    to_steal->prev = head_;
+    head_          = to_steal;
+}
+
+bool memory_block_stack::owns(const void* ptr) const noexcept
+{
+    auto address = static_cast<const char*>(ptr);
+    for (auto cur = head_; cur; cur = cur->prev)
+    {
+        auto mem = static_cast<char*>(static_cast<void*>(cur));
+        if (address >= mem && address < mem + cur->usable_size)
+            return true;
+    }
+    return false;
+}
+
+std::size_t memory_block_stack::size() const noexcept
+{
+    std::size_t res = 0u;
+    for (auto cur = head_; cur; cur = cur->prev)
+        ++res;
+    return res;
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class wpi::memory::memory_arena<static_block_allocator, true>;
+template class wpi::memory::memory_arena<static_block_allocator, false>;
+template class wpi::memory::memory_arena<virtual_block_allocator, true>;
+template class wpi::memory::memory_arena<virtual_block_allocator, false>;
+
+template class wpi::memory::growing_block_allocator<>;
+template class wpi::memory::memory_arena<growing_block_allocator<>, true>;
+template class wpi::memory::memory_arena<growing_block_allocator<>, false>;
+
+template class wpi::memory::fixed_block_allocator<>;
+template class wpi::memory::memory_arena<fixed_block_allocator<>, true>;
+template class wpi::memory::memory_arena<fixed_block_allocator<>, false>;
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/memory_pool.cpp b/wpiutil/src/main/native/thirdparty/memory/src/memory_pool.cpp
new file mode 100644
index 0000000..5a5e5ab
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/memory_pool.cpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/memory_pool.hpp"
+
+#include "wpi/memory/debugging.hpp"
+
+using namespace wpi::memory;
+
+void detail::memory_pool_leak_handler::operator()(std::ptrdiff_t amount)
+{
+    get_leak_handler()({WPI_MEMORY_LOG_PREFIX "::memory_pool", this}, amount);
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class wpi::memory::memory_pool<node_pool>;
+template class wpi::memory::memory_pool<array_pool>;
+template class wpi::memory::memory_pool<small_node_pool>;
+
+template class wpi::memory::allocator_traits<memory_pool<node_pool>>;
+template class wpi::memory::allocator_traits<memory_pool<array_pool>>;
+template class wpi::memory::allocator_traits<memory_pool<small_node_pool>>;
+
+template class wpi::memory::composable_allocator_traits<memory_pool<node_pool>>;
+template class wpi::memory::composable_allocator_traits<memory_pool<array_pool>>;
+template class wpi::memory::composable_allocator_traits<memory_pool<small_node_pool>>;
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/memory_pool_collection.cpp b/wpiutil/src/main/native/thirdparty/memory/src/memory_pool_collection.cpp
new file mode 100644
index 0000000..6366811
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/memory_pool_collection.cpp
@@ -0,0 +1,51 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/memory_pool_collection.hpp"
+
+#include "wpi/memory/debugging.hpp"
+
+using namespace wpi::memory;
+
+void detail::memory_pool_collection_leak_handler::operator()(std::ptrdiff_t amount)
+{
+    get_leak_handler()({WPI_MEMORY_LOG_PREFIX "::memory_pool_collection", this}, amount);
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class wpi::memory::memory_pool_collection<node_pool, identity_buckets>;
+template class wpi::memory::memory_pool_collection<array_pool, identity_buckets>;
+template class wpi::memory::memory_pool_collection<small_node_pool, identity_buckets>;
+
+template class wpi::memory::memory_pool_collection<node_pool, log2_buckets>;
+template class wpi::memory::memory_pool_collection<array_pool, log2_buckets>;
+template class wpi::memory::memory_pool_collection<small_node_pool, log2_buckets>;
+
+template class wpi::memory::allocator_traits<
+    memory_pool_collection<node_pool, identity_buckets>>;
+template class wpi::memory::allocator_traits<
+    memory_pool_collection<array_pool, identity_buckets>>;
+template class wpi::memory::allocator_traits<
+    memory_pool_collection<small_node_pool, identity_buckets>>;
+
+template class wpi::memory::allocator_traits<memory_pool_collection<node_pool, log2_buckets>>;
+template class wpi::memory::allocator_traits<
+    memory_pool_collection<array_pool, log2_buckets>>;
+template class wpi::memory::allocator_traits<
+    memory_pool_collection<small_node_pool, log2_buckets>>;
+
+template class wpi::memory::composable_allocator_traits<
+    memory_pool_collection<node_pool, identity_buckets>>;
+template class wpi::memory::composable_allocator_traits<
+    memory_pool_collection<array_pool, identity_buckets>>;
+template class wpi::memory::composable_allocator_traits<
+    memory_pool_collection<small_node_pool, identity_buckets>>;
+
+template class wpi::memory::composable_allocator_traits<
+    memory_pool_collection<node_pool, log2_buckets>>;
+template class wpi::memory::composable_allocator_traits<
+    memory_pool_collection<array_pool, log2_buckets>>;
+template class wpi::memory::composable_allocator_traits<
+    memory_pool_collection<small_node_pool, log2_buckets>>;
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/memory_stack.cpp b/wpiutil/src/main/native/thirdparty/memory/src/memory_stack.cpp
new file mode 100644
index 0000000..8db5728
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/memory_stack.cpp
@@ -0,0 +1,21 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/memory_stack.hpp"
+
+#include "wpi/memory/debugging.hpp"
+
+using namespace wpi::memory;
+
+void detail::memory_stack_leak_handler::operator()(std::ptrdiff_t amount)
+{
+    get_leak_handler()({WPI_MEMORY_LOG_PREFIX "::memory_stack", this}, amount);
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class wpi::memory::memory_stack<>;
+template class wpi::memory::memory_stack_raii_unwind<memory_stack<>>;
+template class wpi::memory::allocator_traits<memory_stack<>>;
+template class wpi::memory::composable_allocator_traits<memory_stack<>>;
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/new_allocator.cpp b/wpiutil/src/main/native/thirdparty/memory/src/new_allocator.cpp
new file mode 100644
index 0000000..2791182
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/new_allocator.cpp
@@ -0,0 +1,72 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/new_allocator.hpp"
+
+#if WPI_HOSTED_IMPLEMENTATION
+#include <memory>
+#endif
+
+#include <new>
+
+#include "wpi/memory/error.hpp"
+
+using namespace wpi::memory;
+
+allocator_info detail::new_allocator_impl::info() noexcept
+{
+    return {WPI_MEMORY_LOG_PREFIX "::new_allocator", nullptr};
+}
+
+void* detail::new_allocator_impl::allocate(std::size_t size, size_t) noexcept
+{
+    void* memory = nullptr;
+    while (true)
+    {
+        memory = ::operator new(size, std::nothrow);
+        if (memory)
+            break;
+
+        auto handler = std::get_new_handler();
+        if (handler)
+        {
+#if WPI_HAS_EXCEPTION_SUPPORT
+            try
+            {
+                handler();
+            }
+            catch (...)
+            {
+                return nullptr;
+            }
+#else
+            handler();
+#endif
+        }
+        else
+        {
+            return nullptr;
+        }
+    }
+    return memory;
+}
+
+void detail::new_allocator_impl::deallocate(void* ptr, std::size_t, size_t) noexcept
+{
+    ::operator delete(ptr);
+}
+
+std::size_t detail::new_allocator_impl::max_node_size() noexcept
+{
+#if WPI_HOSTED_IMPLEMENTATION
+    return std::allocator_traits<std::allocator<char>>::max_size({});
+#else
+    return std::size_t(-1);
+#endif
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class detail::lowlevel_allocator<detail::new_allocator_impl>;
+template class wpi::memory::allocator_traits<new_allocator>;
+#endif
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/static_allocator.cpp b/wpiutil/src/main/native/thirdparty/memory/src/static_allocator.cpp
new file mode 100644
index 0000000..15a88bf
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/static_allocator.cpp
@@ -0,0 +1,50 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/static_allocator.hpp"
+
+#include "wpi/memory/detail/debug_helpers.hpp"
+#include "wpi/memory/error.hpp"
+#include "wpi/memory/memory_arena.hpp"
+
+using namespace wpi::memory;
+
+void* static_allocator::allocate_node(std::size_t size, std::size_t alignment)
+{
+    auto mem = stack_.allocate(end_, size, alignment);
+    if (!mem)
+        WPI_THROW(out_of_fixed_memory(info(), size));
+    return mem;
+}
+
+allocator_info static_allocator::info() const noexcept
+{
+    return {WPI_MEMORY_LOG_PREFIX "::static_allocator", this};
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class wpi::memory::allocator_traits<static_allocator>;
+#endif
+
+memory_block static_block_allocator::allocate_block()
+{
+    if (cur_ + block_size_ > end_)
+        WPI_THROW(out_of_fixed_memory(info(), block_size_));
+    auto mem = cur_;
+    cur_ += block_size_;
+    return {mem, block_size_};
+}
+
+void static_block_allocator::deallocate_block(memory_block block) noexcept
+{
+    detail::
+        debug_check_pointer([&] { return static_cast<char*>(block.memory) + block.size == cur_; },
+                            info(), block.memory);
+    cur_ -= block_size_;
+}
+
+allocator_info static_block_allocator::info() const noexcept
+{
+    return {WPI_MEMORY_LOG_PREFIX "::static_block_allocator", this};
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/temporary_allocator.cpp b/wpiutil/src/main/native/thirdparty/memory/src/temporary_allocator.cpp
new file mode 100644
index 0000000..fa85e99
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/temporary_allocator.cpp
@@ -0,0 +1,322 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/temporary_allocator.hpp"
+
+#include <new>
+#include <type_traits>
+
+#include "wpi/memory/detail/assert.hpp"
+#include "wpi/memory/default_allocator.hpp"
+#include "wpi/memory/error.hpp"
+
+using namespace wpi::memory;
+
+namespace
+{
+    void default_growth_tracker(std::size_t) noexcept {}
+
+    using temporary_impl_allocator        = default_allocator;
+    using temporary_impl_allocator_traits = allocator_traits<temporary_impl_allocator>;
+} // namespace
+
+detail::temporary_block_allocator::temporary_block_allocator(std::size_t block_size) noexcept
+: tracker_(default_growth_tracker), block_size_(block_size)
+{
+}
+
+detail::temporary_block_allocator::growth_tracker detail::temporary_block_allocator::
+    set_growth_tracker(growth_tracker t) noexcept
+{
+    auto old = tracker_;
+    tracker_ = t;
+    return old;
+}
+
+detail::temporary_block_allocator::growth_tracker detail::temporary_block_allocator::
+    get_growth_tracker() noexcept
+{
+    return tracker_;
+}
+
+memory_block detail::temporary_block_allocator::allocate_block()
+{
+    auto alloc  = temporary_impl_allocator();
+    auto memory = temporary_impl_allocator_traits::allocate_array(alloc, block_size_, 1,
+                                                                  detail::max_alignment);
+    auto block  = memory_block(memory, block_size_);
+    block_size_ = growing_block_allocator<temporary_impl_allocator>::grow_block_size(block_size_);
+    return block;
+}
+
+void detail::temporary_block_allocator::deallocate_block(memory_block block)
+{
+    auto alloc = temporary_impl_allocator();
+    temporary_impl_allocator_traits::deallocate_array(alloc, block.memory, block.size, 1,
+                                                      detail::max_alignment);
+}
+
+#if WPI_MEMORY_TEMPORARY_STACK_MODE >= 2
+// lifetime managment through the nifty counter and the list
+// note: I could have used a simple `thread_local` variable for the temporary stack
+// but this could lead to issues with destruction order
+// and more importantly I have to support platforms that can't handle non-trivial thread local's
+// hence I need to dynamically allocate the stack's and store them in a container
+// on program exit the container is iterated and all stack's are properly destroyed
+// if a thread exit can be detected, the dynamic memory of the stack is already released,
+// but not the stack itself destroyed
+
+#if !defined(__MINGW64__)
+
+// only use the thread exit detector if we have thread local and are not running on MinGW due to a bug
+// see: https://sourceforge.net/p/mingw-w64/bugs/527/
+#define WPI_MEMORY_THREAD_EXIT_DETECTOR 1
+
+#else
+#define WPI_MEMORY_THREAD_EXIT_DETECTOR 0
+
+#if defined(_MSC_VER)
+#pragma message(                                                                                   \
+    "thread_local doesn't support destructors, need to use the temporary_stack_initializer to ensure proper cleanup of the temporary memory")
+#else
+#warning                                                                                           \
+    "thread_local doesn't support destructors, need to use the temporary_stack_initializer to ensure proper cleanup of the temporary memory"
+#endif
+
+#endif
+
+static class detail::temporary_stack_list
+{
+public:
+    std::atomic<temporary_stack_list_node*> first;
+
+    temporary_stack* create_new(std::size_t size)
+    {
+        auto storage =
+            default_allocator().allocate_node(sizeof(temporary_stack), alignof(temporary_stack));
+        return ::new (storage) temporary_stack(0, size);
+    }
+
+    temporary_stack* find_unused()
+    {
+        for (auto ptr = first.load(); ptr; ptr = ptr->next_)
+        {
+            auto value = false;
+            if (ptr->in_use_.compare_exchange_strong(value, true))
+                return static_cast<temporary_stack*>(ptr);
+        }
+
+        return nullptr;
+    }
+
+    temporary_stack* create(std::size_t size)
+    {
+        if (auto ptr = find_unused())
+        {
+            WPI_MEMORY_ASSERT(ptr->in_use_);
+            ptr->stack_ = detail::temporary_stack_impl(size);
+            return ptr;
+        }
+        return create_new(size);
+    }
+
+    void clear(temporary_stack& stack)
+    {
+        // stack should be empty now, so shrink_to_fit() clears all memory
+        stack.stack_.shrink_to_fit();
+        stack.in_use_ = false; // mark as free
+    }
+
+    void destroy()
+    {
+        for (auto ptr = first.exchange(nullptr); ptr;)
+        {
+            auto stack = static_cast<temporary_stack*>(ptr);
+            auto next  = ptr->next_;
+
+            stack->~temporary_stack();
+            default_allocator().deallocate_node(stack, sizeof(temporary_stack),
+                                                alignof(temporary_stack));
+
+            ptr = next;
+        }
+
+        WPI_MEMORY_ASSERT_MSG(!first.load(),
+                                    "destroy() called while other threads are still running");
+    }
+} temporary_stack_list_obj;
+
+namespace
+{
+    thread_local std::size_t      nifty_counter;
+    thread_local temporary_stack* temp_stack = nullptr;
+
+#if WPI_MEMORY_THREAD_EXIT_DETECTOR
+    // don't use this on a bug
+    thread_local struct thread_exit_detector_t
+    {
+        ~thread_exit_detector_t() noexcept
+        {
+            if (temp_stack)
+                // clear automatically on thread exit, as the initializer's destructor does
+                // note: if another's thread_local variable destructor is called after this one
+                // and that destructor uses the temporary allocator
+                // the stack needs to grow again
+                // but who does temporary allocation in a destructor?!
+                temporary_stack_list_obj.clear(*temp_stack);
+        }
+    } thread_exit_detector;
+#endif
+} // namespace
+
+detail::temporary_stack_list_node::temporary_stack_list_node(int) noexcept : in_use_(true)
+{
+    next_ = temporary_stack_list_obj.first.load();
+    while (!temporary_stack_list_obj.first.compare_exchange_weak(next_, this))
+        ;
+#if WPI_MEMORY_THREAD_EXIT_DETECTOR
+    (void)&thread_exit_detector; // ODR-use it, so it will be created
+#endif
+}
+
+detail::temporary_allocator_dtor_t::temporary_allocator_dtor_t() noexcept
+{
+    ++nifty_counter;
+}
+
+detail::temporary_allocator_dtor_t::~temporary_allocator_dtor_t() noexcept
+{
+    if (--nifty_counter == 0u && temp_stack)
+        temporary_stack_list_obj.destroy();
+}
+
+temporary_stack_initializer::temporary_stack_initializer(std::size_t initial_size)
+{
+    if (!temp_stack)
+        temp_stack = temporary_stack_list_obj.create(initial_size);
+}
+
+temporary_stack_initializer::~temporary_stack_initializer() noexcept
+{
+    // don't destroy, nifty counter does that
+    // but can get rid of all the memory
+    if (temp_stack)
+        temporary_stack_list_obj.clear(*temp_stack);
+}
+
+temporary_stack& wpi::memory::get_temporary_stack(std::size_t initial_size)
+{
+    if (!temp_stack)
+        temp_stack = temporary_stack_list_obj.create(initial_size);
+    return *temp_stack;
+}
+
+#elif WPI_MEMORY_TEMPORARY_STACK_MODE == 1
+
+namespace
+{
+    WPI_THREAD_LOCAL alignas(
+        temporary_stack) char temporary_stack_storage[sizeof(temporary_stack)];
+    WPI_THREAD_LOCAL bool is_created = false;
+
+    temporary_stack& get() noexcept
+    {
+        WPI_MEMORY_ASSERT(is_created);
+        return *static_cast<temporary_stack*>(static_cast<void*>(&temporary_stack_storage));
+    }
+
+    void create(std::size_t initial_size)
+    {
+        if (!is_created)
+        {
+            ::new (static_cast<void*>(&temporary_stack_storage)) temporary_stack(initial_size);
+            is_created = true;
+        }
+    }
+} // namespace
+
+// explicit lifetime managment
+temporary_stack_initializer::temporary_stack_initializer(std::size_t initial_size)
+{
+    create(initial_size);
+}
+
+temporary_stack_initializer::~temporary_stack_initializer()
+{
+    if (is_created)
+        get().~temporary_stack();
+}
+
+temporary_stack& wpi::memory::get_temporary_stack(std::size_t initial_size)
+{
+    create(initial_size);
+    return get();
+}
+
+#else
+
+// no lifetime managment
+
+temporary_stack_initializer::temporary_stack_initializer(std::size_t initial_size)
+{
+    if (initial_size != 0u)
+        WPI_MEMORY_WARNING("temporary_stack_initializer() has no effect if "
+                                 "WPI_MEMORY_TEMPORARY_STACK == 0 (pass an initial size of 0 "
+                                 "to disable this message)");
+}
+
+temporary_stack_initializer::~temporary_stack_initializer() {}
+
+temporary_stack& wpi::memory::get_temporary_stack(std::size_t)
+{
+    WPI_MEMORY_UNREACHABLE("get_temporary_stack() called but stack is disabled by "
+                                 "WPI_MEMORY_TEMPORARY_STACK == 0");
+    std::abort();
+}
+
+#endif
+
+const temporary_stack_initializer::defer_create_t temporary_stack_initializer::defer_create;
+
+temporary_allocator::temporary_allocator() : temporary_allocator(get_temporary_stack()) {}
+
+temporary_allocator::temporary_allocator(temporary_stack& stack)
+: unwind_(stack), prev_(stack.top_), shrink_to_fit_(false)
+{
+    WPI_MEMORY_ASSERT(!prev_ || prev_->is_active());
+    stack.top_ = this;
+}
+
+temporary_allocator::~temporary_allocator() noexcept
+{
+    if (is_active())
+    {
+        auto& stack = unwind_.get_stack();
+        stack.top_  = prev_;
+        unwind_.unwind(); // manually call it now...
+        if (shrink_to_fit_)
+            // to call shrink_to_fit() afterwards
+            stack.stack_.shrink_to_fit();
+    }
+}
+
+void* temporary_allocator::allocate(std::size_t size, std::size_t alignment)
+{
+    WPI_MEMORY_ASSERT_MSG(is_active(), "object isn't the active allocator");
+    return unwind_.get_stack().stack_.allocate(size, alignment);
+}
+
+void temporary_allocator::shrink_to_fit() noexcept
+{
+    shrink_to_fit_ = true;
+}
+
+bool temporary_allocator::is_active() const noexcept
+{
+    WPI_MEMORY_ASSERT(unwind_.will_unwind());
+    auto res = unwind_.get_stack().top_ == this;
+    // check that prev is actually before this
+    WPI_MEMORY_ASSERT(!res || !prev_ || prev_->unwind_.get_marker() <= unwind_.get_marker());
+    return res;
+}
diff --git a/wpiutil/src/main/native/thirdparty/memory/src/virtual_memory.cpp b/wpiutil/src/main/native/thirdparty/memory/src/virtual_memory.cpp
new file mode 100644
index 0000000..fd7960f
--- /dev/null
+++ b/wpiutil/src/main/native/thirdparty/memory/src/virtual_memory.cpp
@@ -0,0 +1,240 @@
+// Copyright (C) 2015-2021 Müller <jonathanmueller.dev@gmail.com>
+// This file is subject to the license terms in the LICENSE file
+// found in the top-level directory of this distribution.
+
+#include "wpi/memory/virtual_memory.hpp"
+
+#include "wpi/memory/detail/debug_helpers.hpp"
+#include "wpi/memory/error.hpp"
+#include "wpi/memory/memory_arena.hpp"
+
+using namespace wpi::memory;
+
+void detail::virtual_memory_allocator_leak_handler::operator()(std::ptrdiff_t amount)
+{
+    detail::debug_handle_memory_leak({WPI_MEMORY_LOG_PREFIX "::virtual_memory_allocator",
+                                      nullptr},
+                                     amount);
+}
+
+#if defined(_WIN32)
+#include <windows.h>
+
+namespace
+{
+    std::size_t get_page_size() noexcept
+    {
+        static_assert(sizeof(std::size_t) >= sizeof(DWORD), "possible loss of data");
+
+        SYSTEM_INFO info;
+        GetSystemInfo(&info);
+        return std::size_t(info.dwPageSize);
+    }
+} // namespace
+
+const std::size_t wpi::memory::virtual_memory_page_size = get_page_size();
+
+void* wpi::memory::virtual_memory_reserve(std::size_t no_pages) noexcept
+{
+    auto pages =
+#if (_MSC_VER <= 1900) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+        VirtualAlloc(nullptr, no_pages * virtual_memory_page_size, MEM_RESERVE, PAGE_READWRITE);
+#else
+        VirtualAllocFromApp(nullptr, no_pages * virtual_memory_page_size, MEM_RESERVE,
+                            PAGE_READWRITE);
+#endif
+    return pages;
+}
+
+void wpi::memory::virtual_memory_release(void* pages, std::size_t) noexcept
+{
+    auto result = VirtualFree(pages, 0u, MEM_RELEASE);
+    WPI_MEMORY_ASSERT_MSG(result, "cannot release pages");
+}
+
+void* wpi::memory::virtual_memory_commit(void* memory, std::size_t no_pages) noexcept
+{
+    auto region =
+#if (_MSC_VER <= 1900) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+        VirtualAlloc(memory, no_pages * virtual_memory_page_size, MEM_COMMIT, PAGE_READWRITE);
+#else
+        VirtualAllocFromApp(memory, no_pages * virtual_memory_page_size, MEM_COMMIT,
+                            PAGE_READWRITE);
+#endif
+    if (!region)
+        return nullptr;
+    WPI_MEMORY_ASSERT(region == memory);
+    return region;
+}
+
+void wpi::memory::virtual_memory_decommit(void* memory, std::size_t no_pages) noexcept
+{
+    auto result = VirtualFree(memory, no_pages * virtual_memory_page_size, MEM_DECOMMIT);
+    WPI_MEMORY_ASSERT_MSG(result, "cannot decommit memory");
+}
+#elif defined(__unix__) || defined(__APPLE__) || defined(__VXWORKS__)                              \
+    || defined(__QNXNTO__) // POSIX systems
+#include <sys/mman.h>
+#include <unistd.h>
+
+#if defined(PAGESIZE)
+const std::size_t wpi::memory::virtual_memory_page_size = PAGESIZE;
+#elif defined(PAGE_SIZE)
+const std::size_t wpi::memory::virtual_memory_page_size = PAGE_SIZE;
+#else
+const std::size_t wpi::memory::virtual_memory_page_size =
+    static_cast<std::size_t>(sysconf(_SC_PAGESIZE));
+#endif
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+void* wpi::memory::virtual_memory_reserve(std::size_t no_pages) noexcept
+{
+    auto pages = mmap(nullptr, no_pages * virtual_memory_page_size, PROT_NONE,
+                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    return pages == MAP_FAILED ? nullptr : pages;
+}
+
+void wpi::memory::virtual_memory_release(void* pages, std::size_t no_pages) noexcept
+{
+    auto result = munmap(pages, no_pages * virtual_memory_page_size);
+    WPI_MEMORY_ASSERT_MSG(result == 0, "cannot release pages");
+    (void)result;
+}
+
+void* wpi::memory::virtual_memory_commit(void* memory, std::size_t no_pages) noexcept
+{
+    auto size   = no_pages * virtual_memory_page_size;
+    auto result = mprotect(memory, size, PROT_WRITE | PROT_READ);
+    if (result != 0)
+        return nullptr;
+
+// advise that the memory will be needed
+#if defined(MADV_WILLNEED)
+    madvise(memory, size, MADV_WILLNEED);
+#elif defined(POSIX_MADV_WILLNEED)
+    posix_madvise(memory, size, POSIX_MADV_WILLNEED);
+#endif
+
+    return memory;
+}
+
+void wpi::memory::virtual_memory_decommit(void* memory, std::size_t no_pages) noexcept
+{
+    auto size = no_pages * virtual_memory_page_size;
+// advise that the memory won't be needed anymore
+#if defined(MADV_FREE)
+    madvise(memory, size, MADV_FREE);
+#elif defined(MADV_DONTNEED)
+    madvise(memory, size, MADV_DONTNEED);
+#elif defined(POSIX_MADV_DONTNEED)
+    posix_madvise(memory, size, POSIX_MADV_DONTNEED);
+#endif
+
+    auto result = mprotect(memory, size, PROT_NONE);
+    WPI_MEMORY_ASSERT_MSG(result == 0, "cannot decommit memory");
+    (void)result;
+}
+#else
+#warning "virtual memory functions not available on your platform, define your own"
+#endif
+
+std::size_t wpi::memory::get_virtual_memory_page_size() noexcept
+{
+    return virtual_memory_page_size;
+}
+
+namespace
+{
+    std::size_t calc_no_pages(std::size_t size) noexcept
+    {
+        auto div  = size / virtual_memory_page_size;
+        auto rest = size % virtual_memory_page_size;
+
+        return div + (rest != 0u) + (detail::debug_fence_size ? 2u : 1u);
+    }
+} // namespace
+
+void* virtual_memory_allocator::allocate_node(std::size_t size, std::size_t)
+{
+    auto no_pages = calc_no_pages(size);
+    auto pages    = virtual_memory_reserve(no_pages);
+    if (!pages || !virtual_memory_commit(pages, no_pages))
+        WPI_THROW(
+            out_of_memory({WPI_MEMORY_LOG_PREFIX "::virtual_memory_allocator", nullptr},
+                          no_pages * virtual_memory_page_size));
+    on_allocate(size);
+
+    return detail::debug_fill_new(pages, size, virtual_memory_page_size);
+}
+
+void virtual_memory_allocator::deallocate_node(void* node, std::size_t size, std::size_t) noexcept
+{
+    auto pages = detail::debug_fill_free(node, size, virtual_memory_page_size);
+
+    on_deallocate(size);
+
+    auto no_pages = calc_no_pages(size);
+    virtual_memory_decommit(pages, no_pages);
+    virtual_memory_release(pages, no_pages);
+}
+
+std::size_t virtual_memory_allocator::max_node_size() const noexcept
+{
+    return std::size_t(-1);
+}
+
+std::size_t virtual_memory_allocator::max_alignment() const noexcept
+{
+    return virtual_memory_page_size;
+}
+
+#if WPI_MEMORY_EXTERN_TEMPLATE
+template class wpi::memory::allocator_traits<virtual_memory_allocator>;
+#endif
+
+virtual_block_allocator::virtual_block_allocator(std::size_t block_size, std::size_t no_blocks)
+: block_size_(block_size)
+{
+    WPI_MEMORY_ASSERT(block_size % virtual_memory_page_size == 0u);
+    WPI_MEMORY_ASSERT(no_blocks > 0);
+    auto total_size = block_size_ * no_blocks;
+    auto no_pages   = total_size / virtual_memory_page_size;
+
+    cur_ = static_cast<char*>(virtual_memory_reserve(no_pages));
+    if (!cur_)
+        WPI_THROW(out_of_memory(info(), total_size));
+    end_ = cur_ + total_size;
+}
+
+virtual_block_allocator::~virtual_block_allocator() noexcept
+{
+    virtual_memory_release(cur_, static_cast<std::size_t>(end_ - cur_) / virtual_memory_page_size);
+}
+
+memory_block virtual_block_allocator::allocate_block()
+{
+    if (std::size_t(end_ - cur_) < block_size_)
+        WPI_THROW(out_of_fixed_memory(info(), block_size_));
+    auto mem = virtual_memory_commit(cur_, block_size_ / virtual_memory_page_size);
+    if (!mem)
+        WPI_THROW(out_of_fixed_memory(info(), block_size_));
+    cur_ += block_size_;
+    return {mem, block_size_};
+}
+
+void virtual_block_allocator::deallocate_block(memory_block block) noexcept
+{
+    detail::debug_check_pointer([&]
+                                { return static_cast<char*>(block.memory) == cur_ - block_size_; },
+                                info(), block.memory);
+    cur_ -= block_size_;
+    virtual_memory_decommit(cur_, block_size_);
+}
+
+allocator_info virtual_block_allocator::info() noexcept
+{
+    return {WPI_MEMORY_LOG_PREFIX "::virtual_block_allocator", this};
+}
diff --git a/wpiutil/src/main/native/include/wpi/mpack.h b/wpiutil/src/main/native/thirdparty/mpack/include/wpi/mpack.h
similarity index 100%
rename from wpiutil/src/main/native/include/wpi/mpack.h
rename to wpiutil/src/main/native/thirdparty/mpack/include/wpi/mpack.h
diff --git a/wpiutil/src/main/native/cpp/mpack.cpp b/wpiutil/src/main/native/thirdparty/mpack/src/mpack.cpp
similarity index 99%
rename from wpiutil/src/main/native/cpp/mpack.cpp
rename to wpiutil/src/main/native/thirdparty/mpack/src/mpack.cpp
index fbcb6a4..af5fbd0 100644
--- a/wpiutil/src/main/native/cpp/mpack.cpp
+++ b/wpiutil/src/main/native/thirdparty/mpack/src/mpack.cpp
@@ -237,6 +237,7 @@
 }
 #endif
 
+}  // namespace mpack
 MPACK_SILENCE_WARNINGS_END
 
 /* mpack/mpack-common.c.c */
@@ -246,6 +247,7 @@
 /* #include "mpack-common.h" */
 
 MPACK_SILENCE_WARNINGS_BEGIN
+namespace mpack {
 
 const char* mpack_error_to_string(mpack_error_t error) {
     #if MPACK_STRINGS
@@ -970,6 +972,7 @@
 }
 #endif
 
+}  // namespace mpack
 MPACK_SILENCE_WARNINGS_END
 
 /* mpack/mpack-writer.c.c */
@@ -979,6 +982,7 @@
 /* #include "mpack-writer.h" */
 
 MPACK_SILENCE_WARNINGS_BEGIN
+namespace mpack {
 
 #if MPACK_WRITER
 
@@ -2727,6 +2731,7 @@
 #endif // MPACK_BUILDER
 #endif // MPACK_WRITER
 
+}  // namespace mpack
 MPACK_SILENCE_WARNINGS_END
 
 /* mpack/mpack-reader.c.c */
@@ -2736,6 +2741,7 @@
 /* #include "mpack-reader.h" */
 
 MPACK_SILENCE_WARNINGS_BEGIN
+namespace mpack {
 
 #if MPACK_READER
 
@@ -3996,6 +4002,7 @@
 
 #endif
 
+}  // namespace mpack
 MPACK_SILENCE_WARNINGS_END
 
 /* mpack/mpack-expect.c.c */
@@ -4005,6 +4012,7 @@
 /* #include "mpack-expect.h" */
 
 MPACK_SILENCE_WARNINGS_BEGIN
+namespace mpack {
 
 #if MPACK_EXPECT
 
@@ -4861,6 +4869,7 @@
 
 #endif
 
+}  // namespace mpack
 MPACK_SILENCE_WARNINGS_END
 
 /* mpack/mpack-node.c.c */
@@ -4870,6 +4879,7 @@
 /* #include "mpack-node.h" */
 
 MPACK_SILENCE_WARNINGS_BEGIN
+namespace mpack {
 
 #if MPACK_NODE
 
@@ -7247,5 +7257,5 @@
 
 #endif
 
-}  // namespace wpi
+}  // namespace mpack
 MPACK_SILENCE_WARNINGS_END
diff --git a/wpiutil/src/main/native/include/wpi/Signal.h b/wpiutil/src/main/native/thirdparty/sigslot/include/wpi/Signal.h
similarity index 100%
rename from wpiutil/src/main/native/include/wpi/Signal.h
rename to wpiutil/src/main/native/thirdparty/sigslot/include/wpi/Signal.h
diff --git a/wpiutil/src/main/native/windows/Demangle.cpp b/wpiutil/src/main/native/windows/Demangle.cpp
index 1b0a8a7..18be371 100644
--- a/wpiutil/src/main/native/windows/Demangle.cpp
+++ b/wpiutil/src/main/native/windows/Demangle.cpp
@@ -22,8 +22,9 @@
   char buffer[256];
   DWORD sz = UnDecorateSymbolName(buf.c_str(), buffer, sizeof(buffer),
                                   UNDNAME_COMPLETE);
-  if (sz == 0)
+  if (sz == 0) {
     return std::string{mangledSymbol};
+  }
   return std::string(buffer, sz);
 }
 
diff --git a/wpiutil/src/main/native/windows/DynamicDns.cpp b/wpiutil/src/main/native/windows/DynamicDns.cpp
deleted file mode 100644
index c59d554..0000000
--- a/wpiutil/src/main/native/windows/DynamicDns.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#include "DynamicDns.h"
-
-using namespace wpi;
-
-DynamicDns& DynamicDns::GetDynamicDns() {
-  static DynamicDns dns;
-  return dns;
-}
-
-DynamicDns::DynamicDns() {
-  HMODULE library = LoadLibraryW(L"dnsapi");
-
-  if (library == nullptr) {
-    return;
-  }
-
-  DnsServiceFreeInstancePtr = (DnsServiceFreeInstanceFunc)GetProcAddress(
-      library, "DnsServiceFreeInstance");
-  DnsServiceConstructInstancePtr =
-      (DnsServiceConstructInstanceFunc)GetProcAddress(
-          library, "DnsServiceConstructInstance");
-  DnsServiceRegisterPtr =
-      (DnsServiceRegisterFunc)GetProcAddress(library, "DnsServiceRegister");
-  DnsServiceDeRegisterPtr =
-      (DnsServiceDeRegisterFunc)GetProcAddress(library, "DnsServiceDeRegister");
-
-  CanDnsAnnounce = DnsServiceFreeInstancePtr &&
-                   DnsServiceConstructInstancePtr && DnsServiceRegisterPtr &&
-                   DnsServiceDeRegisterPtr;
-
-  DnsServiceBrowsePtr =
-      (DnsServiceBrowseFunc)GetProcAddress(library, "DnsServiceBrowse");
-  DnsServiceBrowseCancelPtr = (DnsServiceBrowseCancelFunc)GetProcAddress(
-      library, "DnsServiceBrowseCancel");
-
-  CanDnsResolve = DnsServiceBrowsePtr && DnsServiceBrowseCancelPtr;
-}
diff --git a/wpiutil/src/main/native/windows/DynamicDns.h b/wpiutil/src/main/native/windows/DynamicDns.h
deleted file mode 100644
index c8bee04..0000000
--- a/wpiutil/src/main/native/windows/DynamicDns.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#pragma once
-
-#ifndef UNICODE
-#define UNICODE
-#endif
-
-#include <windows.h>
-
-#include <WinDNS.h>
-
-namespace wpi {
-class DynamicDns {
- public:
-  using DnsServiceFreeInstanceFunc =
-      VOID(WINAPI*)(_In_ PDNS_SERVICE_INSTANCE pInstance);
-
-  using DnsServiceConstructInstanceFunc = PDNS_SERVICE_INSTANCE(WINAPI*)(
-      _In_ PCWSTR pServiceName, _In_ PCWSTR pHostName,
-      _In_opt_ PIP4_ADDRESS pIp4, _In_opt_ PIP6_ADDRESS pIp6, _In_ WORD wPort,
-      _In_ WORD wPriority, _In_ WORD wWeight, _In_ DWORD dwPropertiesCount,
-      _In_reads_(dwPropertiesCount) PCWSTR* keys,
-      _In_reads_(dwPropertiesCount) PCWSTR* values);
-
-  using DnsServiceRegisterFunc =
-      DWORD(WINAPI*)(_In_ PDNS_SERVICE_REGISTER_REQUEST pRequest,
-                     _Inout_opt_ PDNS_SERVICE_CANCEL pCancel);
-
-  using DnsServiceDeRegisterFunc =
-      DWORD(WINAPI*)(_In_ PDNS_SERVICE_REGISTER_REQUEST pRequest,
-                     _Inout_opt_ PDNS_SERVICE_CANCEL pCancel);
-
-  using DnsServiceBrowseFunc =
-      DNS_STATUS(WINAPI*)(_In_ PDNS_SERVICE_BROWSE_REQUEST pRequest,
-                          _Inout_ PDNS_SERVICE_CANCEL pCancel);
-
-  using DnsServiceBrowseCancelFunc =
-      DNS_STATUS(WINAPI*)(_In_ PDNS_SERVICE_CANCEL pCancelHandle);
-
-  DnsServiceBrowseFunc DnsServiceBrowsePtr{nullptr};
-  DnsServiceBrowseCancelFunc DnsServiceBrowseCancelPtr{nullptr};
-
-  DnsServiceFreeInstanceFunc DnsServiceFreeInstancePtr{nullptr};
-  DnsServiceConstructInstanceFunc DnsServiceConstructInstancePtr{nullptr};
-  DnsServiceRegisterFunc DnsServiceRegisterPtr{nullptr};
-  DnsServiceDeRegisterFunc DnsServiceDeRegisterPtr{nullptr};
-
-  bool CanDnsAnnounce{false};
-  bool CanDnsResolve{false};
-
-  static DynamicDns& GetDynamicDns();
-
- private:
-  DynamicDns();
-};
-}  // namespace wpi
diff --git a/wpiutil/src/main/native/windows/MulticastServiceAnnouncer.cpp b/wpiutil/src/main/native/windows/MulticastServiceAnnouncer.cpp
deleted file mode 100644
index 2327b8b..0000000
--- a/wpiutil/src/main/native/windows/MulticastServiceAnnouncer.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef UNICODE
-#define UNICODE
-#endif
-
-#include "wpi/MulticastServiceAnnouncer.h"
-
-#include <string>
-#include <vector>
-
-#include "DynamicDns.h"
-#include "wpi/ConvertUTF.h"
-#include "wpi/SmallString.h"
-#include "wpi/SmallVector.h"
-#include "wpi/StringExtras.h"
-#include "wpi/hostname.h"
-
-using namespace wpi;
-
-struct ImplBase {
-  wpi::DynamicDns& dynamicDns = wpi::DynamicDns::GetDynamicDns();
-  PDNS_SERVICE_INSTANCE serviceInstance = nullptr;
-  HANDLE event = nullptr;
-};
-
-struct MulticastServiceAnnouncer::Impl : ImplBase {
-  std::wstring serviceType;
-  std::wstring serviceInstanceName;
-  std::wstring hostName;
-  int port;
-  std::vector<std::wstring> keys;
-  std::vector<PCWSTR> keyPtrs;
-  std::vector<std::wstring> values;
-  std::vector<PCWSTR> valuePtrs;
-
-  template <typename T>
-  Impl(std::string_view serviceName, std::string_view serviceType, int port,
-       wpi::span<const std::pair<T, T>> txt);
-};
-
-template <typename T>
-MulticastServiceAnnouncer::Impl::Impl(std::string_view serviceName,
-                                      std::string_view serviceType, int port,
-                                      wpi::span<const std::pair<T, T>> txt) {
-  if (!dynamicDns.CanDnsAnnounce) {
-    return;
-  }
-
-  this->port = port;
-
-  wpi::SmallVector<wchar_t, 128> wideStorage;
-  std::string hostName = wpi::GetHostname() + ".local";
-
-  for (auto&& i : txt) {
-    wideStorage.clear();
-    wpi::sys::windows::UTF8ToUTF16(i.first, wideStorage);
-    this->keys.emplace_back(
-        std::wstring{wideStorage.data(), wideStorage.size()});
-    wideStorage.clear();
-    wpi::sys::windows::UTF8ToUTF16(i.second, wideStorage);
-    this->values.emplace_back(
-        std::wstring{wideStorage.data(), wideStorage.size()});
-  }
-
-  for (size_t i = 0; i < this->keys.size(); i++) {
-    this->keyPtrs.emplace_back(this->keys[i].c_str());
-    this->valuePtrs.emplace_back(this->values[i].c_str());
-  }
-
-  wpi::SmallString<128> storage;
-
-  wideStorage.clear();
-  wpi::sys::windows::UTF8ToUTF16(hostName, wideStorage);
-
-  this->hostName = std::wstring{wideStorage.data(), wideStorage.size()};
-
-  wideStorage.clear();
-  if (wpi::ends_with_lower(serviceType, ".local")) {
-    wpi::sys::windows::UTF8ToUTF16(serviceType, wideStorage);
-  } else {
-    storage.clear();
-    storage.append(serviceType);
-    storage.append(".local");
-    wpi::sys::windows::UTF8ToUTF16(storage.str(), wideStorage);
-  }
-  this->serviceType = std::wstring{wideStorage.data(), wideStorage.size()};
-
-  wideStorage.clear();
-  storage.clear();
-  storage.append(serviceName);
-  storage.append(".");
-  storage.append(serviceType);
-  if (!wpi::ends_with_lower(serviceType, ".local")) {
-    storage.append(".local");
-  }
-
-  wpi::sys::windows::UTF8ToUTF16(storage.str(), wideStorage);
-  this->serviceInstanceName =
-      std::wstring{wideStorage.data(), wideStorage.size()};
-}
-
-MulticastServiceAnnouncer::MulticastServiceAnnouncer(
-    std::string_view serviceName, std::string_view serviceType, int port,
-    wpi::span<const std::pair<std::string, std::string>> txt) {
-  pImpl = std::make_unique<Impl>(serviceName, serviceType, port, txt);
-}
-
-MulticastServiceAnnouncer::MulticastServiceAnnouncer(
-    std::string_view serviceName, std::string_view serviceType, int port,
-    wpi::span<const std::pair<std::string_view, std::string_view>> txt) {
-  pImpl = std::make_unique<Impl>(serviceName, serviceType, port, txt);
-}
-
-MulticastServiceAnnouncer::~MulticastServiceAnnouncer() noexcept {
-  Stop();
-}
-
-bool MulticastServiceAnnouncer::HasImplementation() const {
-  return pImpl->dynamicDns.CanDnsAnnounce;
-}
-
-static void WINAPI DnsServiceRegisterCallback(DWORD /*Status*/,
-                                              PVOID pQueryContext,
-                                              PDNS_SERVICE_INSTANCE pInstance) {
-  ImplBase* impl = reinterpret_cast<ImplBase*>(pQueryContext);
-
-  impl->serviceInstance = pInstance;
-
-  SetEvent(impl->event);
-}
-
-void MulticastServiceAnnouncer::Start() {
-  if (pImpl->serviceInstance) {
-    return;
-  }
-
-  if (!pImpl->dynamicDns.CanDnsAnnounce) {
-    return;
-  }
-
-  PDNS_SERVICE_INSTANCE serviceInst =
-      pImpl->dynamicDns.DnsServiceConstructInstancePtr(
-          pImpl->serviceInstanceName.c_str(), pImpl->hostName.c_str(), nullptr,
-          nullptr, pImpl->port, 0, 0, static_cast<DWORD>(pImpl->keyPtrs.size()),
-          pImpl->keyPtrs.data(), pImpl->valuePtrs.data());
-  if (serviceInst == nullptr) {
-    return;
-  }
-
-  DNS_SERVICE_REGISTER_REQUEST registerRequest = {};
-  registerRequest.pQueryContext = static_cast<ImplBase*>(pImpl.get());
-  registerRequest.pRegisterCompletionCallback = DnsServiceRegisterCallback;
-  registerRequest.Version = DNS_QUERY_REQUEST_VERSION1;
-  registerRequest.unicastEnabled = false;
-  registerRequest.pServiceInstance = serviceInst;
-  registerRequest.InterfaceIndex = 0;
-
-  pImpl->event = CreateEvent(NULL, true, false, NULL);
-
-  if (pImpl->dynamicDns.DnsServiceRegisterPtr(&registerRequest, nullptr) ==
-      DNS_REQUEST_PENDING) {
-    WaitForSingleObject(pImpl->event, INFINITE);
-  }
-
-  pImpl->dynamicDns.DnsServiceFreeInstancePtr(serviceInst);
-  CloseHandle(pImpl->event);
-  pImpl->event = nullptr;
-}
-
-static void WINAPI DnsServiceDeRegisterCallback(
-    DWORD /*Status*/, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) {
-  ImplBase* impl = reinterpret_cast<ImplBase*>(pQueryContext);
-
-  if (pInstance != nullptr) {
-    impl->dynamicDns.DnsServiceFreeInstancePtr(pInstance);
-    pInstance = nullptr;
-  }
-
-  SetEvent(impl->event);
-}
-
-void MulticastServiceAnnouncer::Stop() {
-  if (!pImpl->dynamicDns.CanDnsAnnounce) {
-    return;
-  }
-
-  if (pImpl->serviceInstance == nullptr) {
-    return;
-  }
-
-  pImpl->event = CreateEvent(NULL, true, false, NULL);
-  DNS_SERVICE_REGISTER_REQUEST registerRequest = {};
-  registerRequest.pQueryContext = static_cast<ImplBase*>(pImpl.get());
-  registerRequest.pRegisterCompletionCallback = DnsServiceDeRegisterCallback;
-  registerRequest.Version = DNS_QUERY_REQUEST_VERSION1;
-  registerRequest.unicastEnabled = false;
-  registerRequest.pServiceInstance = pImpl->serviceInstance;
-  registerRequest.InterfaceIndex = 0;
-
-  if (pImpl->dynamicDns.DnsServiceDeRegisterPtr(&registerRequest, nullptr) ==
-      DNS_REQUEST_PENDING) {
-    WaitForSingleObject(pImpl->event, INFINITE);
-  }
-
-  pImpl->dynamicDns.DnsServiceFreeInstancePtr(pImpl->serviceInstance);
-  pImpl->serviceInstance = nullptr;
-  CloseHandle(pImpl->event);
-  pImpl->event = nullptr;
-}
diff --git a/wpiutil/src/main/native/windows/MulticastServiceResolver.cpp b/wpiutil/src/main/native/windows/MulticastServiceResolver.cpp
deleted file mode 100644
index 115b43f..0000000
--- a/wpiutil/src/main/native/windows/MulticastServiceResolver.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright (c) FIRST and other WPILib contributors.
-// Open Source Software; you can modify and/or share it under the terms of
-// the WPILib BSD license file in the root directory of this project.
-
-#ifndef UNICODE
-#define UNICODE
-#endif
-
-#include "wpi/MulticastServiceResolver.h"
-
-#include <string>
-
-#include "DynamicDns.h"
-#include "wpi/ConvertUTF.h"
-#include "wpi/SmallString.h"
-#include "wpi/SmallVector.h"
-#include "wpi/StringExtras.h"
-
-#pragma comment(lib, "dnsapi")
-
-using namespace wpi;
-
-struct MulticastServiceResolver::Impl {
-  wpi::DynamicDns& dynamicDns = wpi::DynamicDns::GetDynamicDns();
-  std::wstring serviceType;
-  DNS_SERVICE_CANCEL serviceCancel{nullptr};
-
-  MulticastServiceResolver* resolver;
-
-  void onFound(ServiceData&& data) {
-    resolver->PushData(std::forward<ServiceData>(data));
-  }
-};
-
-MulticastServiceResolver::MulticastServiceResolver(
-    std::string_view serviceType) {
-  pImpl = std::make_unique<Impl>();
-  pImpl->resolver = this;
-
-  if (!pImpl->dynamicDns.CanDnsResolve) {
-    return;
-  }
-
-  wpi::SmallVector<wchar_t, 128> wideStorage;
-
-  if (wpi::ends_with_lower(serviceType, ".local")) {
-    wpi::sys::windows::UTF8ToUTF16(serviceType, wideStorage);
-  } else {
-    wpi::SmallString<128> storage;
-    storage.append(serviceType);
-    storage.append(".local");
-    wpi::sys::windows::UTF8ToUTF16(storage.str(), wideStorage);
-  }
-  pImpl->serviceType = std::wstring{wideStorage.data(), wideStorage.size()};
-}
-
-MulticastServiceResolver::~MulticastServiceResolver() noexcept {
-  Stop();
-}
-
-bool MulticastServiceResolver::HasImplementation() const {
-  return pImpl->dynamicDns.CanDnsResolve;
-}
-
-static _Function_class_(DNS_QUERY_COMPLETION_ROUTINE) VOID WINAPI
-    DnsCompletion(_In_ PVOID pQueryContext,
-                  _Inout_ PDNS_QUERY_RESULT pQueryResults) {
-  MulticastServiceResolver::Impl* impl =
-      reinterpret_cast<MulticastServiceResolver::Impl*>(pQueryContext);
-
-  wpi::SmallVector<DNS_RECORDW*, 4> PtrRecords;
-  wpi::SmallVector<DNS_RECORDW*, 4> SrvRecords;
-  wpi::SmallVector<DNS_RECORDW*, 4> TxtRecords;
-  wpi::SmallVector<DNS_RECORDW*, 4> ARecords;
-
-  {
-    DNS_RECORDW* current = pQueryResults->pQueryRecords;
-    while (current != nullptr) {
-      switch (current->wType) {
-        case DNS_TYPE_PTR:
-          PtrRecords.push_back(current);
-          break;
-        case DNS_TYPE_SRV:
-          SrvRecords.push_back(current);
-          break;
-        case DNS_TYPE_TEXT:
-          TxtRecords.push_back(current);
-          break;
-        case DNS_TYPE_A:
-          ARecords.push_back(current);
-          break;
-      }
-      current = current->pNext;
-    }
-  }
-
-  for (DNS_RECORDW* Ptr : PtrRecords) {
-    if (std::wstring_view{Ptr->pName} != impl->serviceType) {
-      continue;
-    }
-
-    std::wstring_view nameHost = Ptr->Data.Ptr.pNameHost;
-    DNS_RECORDW* foundSrv = nullptr;
-    for (DNS_RECORDW* Srv : SrvRecords) {
-      if (std::wstring_view{Srv->pName} == nameHost) {
-        foundSrv = Srv;
-        break;
-      }
-    }
-
-    if (!foundSrv) {
-      continue;
-    }
-
-    for (DNS_RECORDW* A : ARecords) {
-      if (std::wstring_view{A->pName} ==
-          std::wstring_view{foundSrv->Data.Srv.pNameTarget}) {
-        MulticastServiceResolver::ServiceData data;
-        wpi::SmallString<128> storage;
-        for (DNS_RECORDW* Txt : TxtRecords) {
-          if (std::wstring_view{Txt->pName} == nameHost) {
-            for (DWORD i = 0; i < Txt->Data.Txt.dwStringCount; i++) {
-              std::wstring_view wideView = Txt->Data.TXT.pStringArray[i];
-              size_t splitIndex = wideView.find(L'=');
-              if (splitIndex == wideView.npos) {
-                // Todo make this just do key
-                continue;
-              }
-              storage.clear();
-              wpi::span<const wpi::UTF16> wideStr{
-                  reinterpret_cast<const wpi::UTF16*>(wideView.data()),
-                  splitIndex};
-              wpi::convertUTF16ToUTF8String(wideStr, storage);
-              auto& pair = data.txt.emplace_back(
-                  std::pair<std::string, std::string>{storage.string(), {}});
-              storage.clear();
-              wideStr = wpi::span<const wpi::UTF16>{
-                  reinterpret_cast<const wpi::UTF16*>(wideView.data() +
-                                                      splitIndex + 1),
-                  wideView.size() - splitIndex - 1};
-              wpi::convertUTF16ToUTF8String(wideStr, storage);
-              pair.second = storage.string();
-            }
-          }
-        }
-
-        storage.clear();
-        wpi::span<const wpi::UTF16> wideHostName{
-            reinterpret_cast<const wpi::UTF16*>(A->pName), wcslen(A->pName)};
-        wpi::convertUTF16ToUTF8String(wideHostName, storage);
-        storage.append(".");
-
-        data.hostName = storage.string();
-        storage.clear();
-
-        int len = nameHost.find(impl->serviceType.c_str());
-        wpi::span<const wpi::UTF16> wideServiceName{
-            reinterpret_cast<const wpi::UTF16*>(nameHost.data()),
-            nameHost.size()};
-        if (len != nameHost.npos) {
-          wideServiceName = wideServiceName.subspan(0, len - 1);
-        }
-        wpi::convertUTF16ToUTF8String(wideServiceName, storage);
-
-        data.serviceName = storage.string();
-        data.port = foundSrv->Data.Srv.wPort;
-        data.ipv4Address = A->Data.A.IpAddress;
-
-        impl->onFound(std::move(data));
-      }
-    }
-  }
-  DnsFree(pQueryResults->pQueryRecords, DNS_FREE_TYPE::DnsFreeRecordList);
-}
-
-void MulticastServiceResolver::Start() {
-  if (pImpl->serviceCancel.reserved != nullptr) {
-    return;
-  }
-
-  if (!pImpl->dynamicDns.CanDnsResolve) {
-    return;
-  }
-
-  DNS_SERVICE_BROWSE_REQUEST request = {};
-  request.InterfaceIndex = 0;
-  request.pQueryContext = pImpl.get();
-  request.QueryName = pImpl->serviceType.c_str();
-  request.Version = 2;
-  request.pBrowseCallbackV2 = DnsCompletion;
-  pImpl->dynamicDns.DnsServiceBrowsePtr(&request, &pImpl->serviceCancel);
-}
-
-void MulticastServiceResolver::Stop() {
-  if (!pImpl->dynamicDns.CanDnsResolve) {
-    return;
-  }
-
-  if (pImpl->serviceCancel.reserved == nullptr) {
-    return;
-  }
-
-  pImpl->dynamicDns.DnsServiceBrowseCancelPtr(&pImpl->serviceCancel);
-  pImpl->serviceCancel.reserved = nullptr;
-}
diff --git a/wpiutil/src/main/native/windows/StackTrace.cpp b/wpiutil/src/main/native/windows/StackTrace.cpp
index bab5f83..de31b2a 100644
--- a/wpiutil/src/main/native/windows/StackTrace.cpp
+++ b/wpiutil/src/main/native/windows/StackTrace.cpp
@@ -8,6 +8,8 @@
 #include "wpi/ConvertUTF.h"
 #include "wpi/SmallString.h"
 
+#if defined(_MSC_VER)
+
 namespace {
 class StackTraceWalker : public StackWalker {
  public:
@@ -40,3 +42,5 @@
 }
 
 }  // namespace wpi
+
+#endif  // defined(_MSC_VER)
diff --git a/wpiutil/src/main/native/windows/StackWalker.cpp b/wpiutil/src/main/native/windows/StackWalker.cpp
index 237360a..6f0fbf2 100644
--- a/wpiutil/src/main/native/windows/StackWalker.cpp
+++ b/wpiutil/src/main/native/windows/StackWalker.cpp
@@ -1,4 +1,4 @@
-/**********************************************************************
+/**********************************************************************
  *
  * StackWalker.cpp
  * https://github.com/JochenKalmbach/StackWalker
@@ -485,8 +485,8 @@
       if (hToolhelp == NULL)
         continue;
       createToolhelp32Snapshot = (tCT32S)GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot");
-      module32First = (tM32F)GetProcAddress(hToolhelp, strModule32First);
-      module32Next = (tM32N)GetProcAddress(hToolhelp, strModule32Next);
+      module32First = (tM32F)GetProcAddress(hToolhelp, strModule32First);  
+      module32Next = (tM32N)GetProcAddress(hToolhelp, strModule32Next); 
       if ((createToolhelp32Snapshot != NULL) && (module32First != NULL) && (module32Next != NULL))
         break; // found the functions!
       FreeLibrary(hToolhelp);
diff --git a/wpiutil/src/main/native/windows/StackWalker.h b/wpiutil/src/main/native/windows/StackWalker.h
index 750de96..89be951 100644
--- a/wpiutil/src/main/native/windows/StackWalker.h
+++ b/wpiutil/src/main/native/windows/StackWalker.h
@@ -1,3 +1,8 @@
+#ifndef __STACKWALKER_H__
+#define __STACKWALKER_H__
+
+#if defined(_MSC_VER)
+
 /**********************************************************************
  *
  * StackWalker.h
@@ -32,6 +37,8 @@
  *   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * **********************************************************************/
+// #pragma once is supported starting with _MSC_VER 1000,
+// so we need not to check the version (because we only support _MSC_VER >= 1100)!
 #pragma once
 
 #include <windows.h>
@@ -105,7 +112,11 @@
 
   BOOL ShowObject(LPVOID pObject);
 
+#if _MSC_VER >= 1300
+  // due to some reasons, the "STACKWALK_MAX_NAMELEN" must be declared as "public"
+  // in older compilers in order to use it... starting with VC7 we can declare it as "protected"
 protected:
+#endif
   enum
   {
     STACKWALK_MAX_NAMELEN = 1024
@@ -176,3 +187,7 @@
     c.ContextFlags = contextFlags;                                \
     RtlCaptureContext(&c);                                        \
   } while (0);
+
+#endif //defined(_MSC_VER)
+
+#endif // __STACKWALKER_H__