aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-10-07 00:46:05 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-10-07 00:46:05 -0700
commitb5a36f676b1fd69f195d9f1eb6e35f3eb2f15946 (patch)
tree92ce1ffa64bc2d32d5ef73dce66daf3c8e893ee6 /lib
parentd6d05fc84d33c71434a1f8bae51ca5956e08cdf0 (diff)
parentf2d374e8465042fa5cb6bf2be7b9b086948f3a94 (diff)
downloadzig-b5a36f676b1fd69f195d9f1eb6e35f3eb2f15946.tar.gz
zig-b5a36f676b1fd69f195d9f1eb6e35f3eb2f15946.zip
Merge remote-tracking branch 'origin/master' into llvm11
Conflicts: cmake/Findllvm.cmake The llvm11 branch changed 10's to 11's and master branch added the "using LLVM_CONFIG_EXE" help message, so the resolution was to merge these changes together. I also added a check to make sure LLVM is built with AVR enabled, which is no longer an experimental target.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/mingw/lib32/user32.def998
-rw-r--r--lib/std/array_list.zig574
-rw-r--r--lib/std/build.zig116
-rw-r--r--lib/std/builtin.zig13
-rw-r--r--lib/std/c.zig3
-rw-r--r--lib/std/c/darwin.zig2
-rw-r--r--lib/std/c/linux.zig2
-rw-r--r--lib/std/child_process.zig4
-rw-r--r--lib/std/crypto.zig88
-rw-r--r--lib/std/crypto/25519/field.zig14
-rw-r--r--lib/std/crypto/aes_gcm.zig161
-rw-r--r--lib/std/crypto/benchmark.zig3
-rw-r--r--lib/std/crypto/ghash.zig317
-rw-r--r--lib/std/crypto/hkdf.zig66
-rw-r--r--lib/std/crypto/poly1305.zig26
-rw-r--r--lib/std/event/loop.zig55
-rw-r--r--lib/std/fmt.zig10
-rw-r--r--lib/std/fs.zig18
-rw-r--r--lib/std/fs/file.zig16
-rw-r--r--lib/std/macho.zig44
-rw-r--r--lib/std/math/big/int.zig124
-rw-r--r--lib/std/math/big/int_test.zig52
-rw-r--r--lib/std/meta.zig2
-rw-r--r--lib/std/meta/trailer_flags.zig1
-rw-r--r--lib/std/os.zig32
-rw-r--r--lib/std/os/bits/linux.zig76
-rw-r--r--lib/std/os/linux.zig20
-rw-r--r--lib/std/os/test.zig10
-rw-r--r--lib/std/packed_int_array.zig15
-rw-r--r--lib/std/zig/system.zig2
30 files changed, 2570 insertions, 294 deletions
diff --git a/lib/libc/mingw/lib32/user32.def b/lib/libc/mingw/lib32/user32.def
new file mode 100644
index 0000000000..c20d16835a
--- /dev/null
+++ b/lib/libc/mingw/lib32/user32.def
@@ -0,0 +1,998 @@
+LIBRARY USER32.dll
+EXPORTS
+;ord_1500@16 @1500
+;ord_1501@4 @1501
+;ord_1502@12 @1502
+ActivateKeyboardLayout@8
+AddClipboardFormatListener@4
+AdjustWindowRect@12
+AdjustWindowRectEx@16
+AlignRects@16
+AllowForegroundActivation@0
+AllowSetForegroundWindow@4
+AnimateWindow@12
+AnyPopup@0
+AppendMenuA@16
+AppendMenuW@16
+ArrangeIconicWindows@4
+AttachThreadInput@12
+BeginDeferWindowPos@4
+BeginPaint@8
+BlockInput@4
+BringWindowToTop@4
+BroadcastSystemMessage@20
+BroadcastSystemMessageA@20
+BroadcastSystemMessageExA@24
+BroadcastSystemMessageExW@24
+BroadcastSystemMessageW@20
+BuildReasonArray@12
+CalcChildScroll@8
+CalcMenuBar@20
+CalculatePopupWindowPosition@20
+CallMsgFilter@8
+CallMsgFilterA@8
+CallMsgFilterW@8
+CallNextHookEx@16
+CallWindowProcA@20
+CallWindowProcW@20
+CancelShutdown@0
+CascadeChildWindows@8
+CascadeWindows@20
+ChangeClipboardChain@8
+ChangeDisplaySettingsA@8
+ChangeDisplaySettingsExA@20
+ChangeDisplaySettingsExW@20
+ChangeDisplaySettingsW@8
+ChangeMenuA@20
+ChangeMenuW@20
+ChangeWindowMessageFilter@8
+ChangeWindowMessageFilterEx@16
+CharLowerA@4
+CharLowerBuffA@8
+CharLowerBuffW@8
+CharLowerW@4
+CharNextA@4
+;ord_1550@12 @1550
+;ord_1551@8 @1551
+;ord_1552@8 @1552
+;ord_1553@12 @1553
+;ord_1554@8 @1554
+;ord_1555@16 @1555
+;ord_1556@4 @1556
+CharNextExA@12
+CharNextW@4
+CharPrevA@8
+CharPrevExA@16
+CharPrevW@8
+CharToOemA@8
+CharToOemBuffA@12
+CharToOemBuffW@12
+CharToOemW@8
+CharUpperA@4
+CharUpperBuffA@8
+CharUpperBuffW@8
+CharUpperW@4
+CheckDesktopByThreadId@4
+CheckDBCSEnabledExt@0
+CheckDlgButton@12
+CheckMenuItem@12
+CheckMenuRadioItem@20
+CheckProcessForClipboardAccess@8
+CheckProcessSession@4
+CheckRadioButton@16
+CheckWindowThreadDesktop@8
+ChildWindowFromPoint@12
+ChildWindowFromPointEx@16
+CliImmSetHotKey@16
+ClientThreadSetup@0
+ClientToScreen@8
+ClipCursor@4
+CloseClipboard@0
+CloseDesktop@4
+CloseGestureInfoHandle@4
+CloseTouchInputHandle@4
+CloseWindow@4
+CloseWindowStation@4
+ConsoleControl@12
+ControlMagnification@8
+CopyAcceleratorTableA@12
+CopyAcceleratorTableW@12
+CopyIcon@4
+CopyImage@20
+CopyRect@8
+CountClipboardFormats@0
+CreateAcceleratorTableA@8
+CreateAcceleratorTableW@8
+CreateCaret@16
+CreateCursor@28
+CreateDCompositionHwndTarget@12
+CreateDesktopA@24
+CreateDesktopExA@32
+CreateDesktopExW@32
+CreateDesktopW@24
+CreateDialogIndirectParamA@20
+CreateDialogIndirectParamAorW@24
+CreateDialogIndirectParamW@20
+CreateDialogParamA@20
+CreateDialogParamW@20
+CreateIcon@28
+CreateIconFromResource@16
+CreateIconFromResourceEx@28
+CreateIconIndirect@4
+CreateMDIWindowA@40
+CreateMDIWindowW@40
+CreateMenu@0
+CreatePopupMenu@0
+CreateSystemThreads@16 ; ReactOS has the @8 variant
+CreateWindowExA@48
+CreateWindowExW@48
+CreateWindowInBand@52
+CreateWindowIndirect@4
+CreateWindowStationA@16
+CreateWindowStationW@16
+CsrBroadcastSystemMessageExW@24
+CtxInitUser32@0
+DdeAbandonTransaction@12
+DdeAccessData@8
+DdeAddData@16
+DdeClientTransaction@32
+DdeCmpStringHandles@8
+DdeConnect@16
+DdeConnectList@20
+DdeCreateDataHandle@28
+DdeCreateStringHandleA@12
+DdeCreateStringHandleW@12
+DdeDisconnect@4
+DdeDisconnectList@4
+DdeEnableCallback@12
+DdeFreeDataHandle@4
+DdeFreeStringHandle@8
+DdeGetData@16
+DdeGetLastError@4
+DdeGetQualityOfService@12
+DdeImpersonateClient@4
+DdeInitializeA@16
+DdeInitializeW@16
+DdeKeepStringHandle@8
+DdeNameService@16
+DdePostAdvise@12
+DdeQueryConvInfo@12
+DdeQueryNextServer@8
+DdeQueryStringA@20
+DdeQueryStringW@20
+DdeReconnect@4
+DdeSetQualityOfService@12
+DdeSetUserHandle@12
+DdeUnaccessData@4
+DdeUninitialize@4
+DefDlgProcA@16
+DefDlgProcW@16
+DefFrameProcA@20
+DefFrameProcW@20
+DefMDIChildProcA@16
+DefMDIChildProcW@16
+DefRawInputProc@12
+DefWindowProcA@16
+DefWindowProcW@16
+DeferWindowPos@32
+DeferWindowPosAndBand@36
+DeleteMenu@12
+DeregisterShellHookWindow@4
+DestroyAcceleratorTable@4
+DestroyCaret@0
+DestroyCursor@4
+DestroyDCompositionHwndTarget@8
+DestroyIcon@4
+DestroyMenu@4
+DestroyReasons@4
+DestroyWindow@4
+DeviceEventWorker@24 ; No documentation whatsoever, ReactOS has a stub with @20 - https://www.reactos.org/archives/public/ros-diffs/2011-February/040308.html
+DialogBoxIndirectParamA@20
+DialogBoxIndirectParamAorW@24
+DialogBoxIndirectParamW@20
+DialogBoxParamA@20
+DialogBoxParamW@20
+DisableProcessWindowsGhosting@0
+DispatchMessageA@4
+DispatchMessageW@4
+DisplayConfigGetDeviceInfo@4
+DisplayConfigSetDeviceInfo@4
+DisplayExitWindowsWarnings@4
+DlgDirListA@20
+DlgDirListComboBoxA@20
+DlgDirListComboBoxW@20
+DlgDirListW@20
+DlgDirSelectComboBoxExA@16
+DlgDirSelectComboBoxExW@16
+DlgDirSelectExA@16
+DlgDirSelectExW@16
+DoSoundConnect@0
+DoSoundDisconnect@0
+DragDetect@12
+DragObject@20
+DrawAnimatedRects@16
+DrawCaption@16
+DrawCaptionTempA@28
+DrawCaptionTempW@28
+DrawEdge@16
+DrawFocusRect@8
+DrawFrame@16
+DrawFrameControl@16
+DrawIcon@16
+DrawIconEx@36
+DrawMenuBar@4
+DrawMenuBarTemp@20
+DrawStateA@40
+DrawStateW@40
+DrawTextA@20
+DrawTextExA@24
+DrawTextExW@24
+DrawTextW@20
+DwmGetDxSharedSurface@24
+DwmGetRemoteSessionOcclusionEvent@0
+DwmGetRemoteSessionOcclusionState@0
+DwmLockScreenUpdates@4
+DwmStartRedirection@8 ; Mentioned on http://habrahabr.ru/post/145174/ , enables GDI virtualization (for security purposes)
+DwmStopRedirection@0
+DwmValidateWindow@8
+EditWndProc@16
+EmptyClipboard@0
+EnableMenuItem@12
+EnableMouseInPointer@4
+EnableScrollBar@12
+EnableSessionForMMCSS@4
+EnableWindow@8
+EndDeferWindowPos@4
+EndDeferWindowPosEx@8
+EndDialog@8
+EndMenu@0
+EndPaint@8
+EndTask@12
+EnterReaderModeHelper@4
+EnumChildWindows@12
+EnumClipboardFormats@4
+EnumDesktopWindows@12
+EnumDesktopsA@12
+EnumDesktopsW@12
+EnumDisplayDevicesA@16
+EnumDisplayDevicesW@16
+EnumDisplayMonitors@16
+EnumDisplaySettingsA@12
+EnumDisplaySettingsExA@16
+EnumDisplaySettingsExW@16
+EnumDisplaySettingsW@12
+EnumPropsA@8
+EnumPropsExA@12
+EnumPropsExW@12
+EnumPropsW@8
+EnumThreadWindows@12
+EnumWindowStationsA@8
+EnumWindowStationsW@8
+EnumWindows@8
+EqualRect@8
+EvaluateProximityToPolygon@16
+EvaluateProximityToRect@12
+ExcludeUpdateRgn@8
+ExitWindowsEx@8
+FillRect@12
+FindWindowA@8
+FindWindowExA@16
+FindWindowExW@16
+FindWindowW@8
+FlashWindow@8
+FlashWindowEx@4
+FrameRect@12
+FreeDDElParam@8
+FrostCrashedWindow@8
+GetActiveWindow@0
+GetAltTabInfo@20
+GetAltTabInfoA@20
+GetAltTabInfoW@20
+GetAncestor@8
+GetAppCompatFlags2@4
+GetAppCompatFlags@8 ; ReactOS has @4 version http://doxygen.reactos.org/d9/d71/undocuser_8h_a9b76cdc68c523a061c86a40367049ed2.html
+GetAsyncKeyState@4
+GetAutoRotationState@4
+GetCIMSSM@4
+GetCapture@0
+GetCaretBlinkTime@0
+GetCaretPos@4
+GetClassInfoA@12
+GetClassInfoExA@12
+GetClassInfoExW@12
+GetClassInfoW@12
+GetClassLongA@8
+GetClassLongW@8
+GetClassNameA@12
+GetClassNameW@12
+GetClassWord@8
+GetClientRect@8
+GetClipCursor@4
+GetClipboardAccessToken@8
+GetClipboardData@4
+GetClipboardFormatNameA@12
+GetClipboardFormatNameW@12
+GetClipboardOwner@0
+GetClipboardSequenceNumber@0
+GetClipboardViewer@0
+GetComboBoxInfo@8
+GetCurrentInputMessageSource@4
+GetCursor@0
+GetCursorFrameInfo@20
+GetCursorInfo@4
+GetCursorPos@4
+GetDC@4
+GetDCEx@12
+GetDesktopID@8
+GetDesktopWindow@0
+GetDialogBaseUnits@0
+GetDisplayAutoRotationPreferences@4
+GetDisplayConfigBufferSizes@12
+GetDlgCtrlID@4
+GetDlgItem@8
+GetDlgItemInt@16
+GetDlgItemTextA@16
+GetDlgItemTextW@16
+GetDoubleClickTime@0
+GetDpiForMonitorInternal@16
+GetFocus@0
+GetForegroundWindow@0
+GetGUIThreadInfo@8
+GetGestureConfig@24
+GetGestureExtraArgs@12
+GetGestureInfo@8
+GetGuiResources@8
+GetIconInfo@8
+GetIconInfoExA@8
+GetIconInfoExW@8
+GetInputDesktop@0
+GetInputLocaleInfo@8
+GetInputState@0
+GetInternalWindowPos@12
+GetKBCodePage@0
+GetKeyNameTextA@12
+GetKeyNameTextW@12
+GetKeyState@4
+GetKeyboardLayout@4
+GetKeyboardLayoutList@8
+GetKeyboardLayoutNameA@4
+GetKeyboardLayoutNameW@4
+GetKeyboardState@4
+GetKeyboardType@4
+GetLastActivePopup@4
+GetLastInputInfo@4
+GetLayeredWindowAttributes@16
+GetListBoxInfo@4
+GetMagnificationDesktopColorEffect@4
+GetMagnificationDesktopMagnification@12
+GetMagnificationLensCtxInformation@16
+GetMenu@4
+GetMenuBarInfo@16
+GetMenuCheckMarkDimensions@0
+GetMenuContextHelpId@4
+GetMenuDefaultItem@12
+GetMenuInfo@8
+GetMenuItemCount@4
+GetMenuItemID@8
+GetMenuItemInfoA@16
+GetMenuItemInfoW@16
+GetMenuItemRect@16
+GetMenuState@12
+GetMenuStringA@20
+GetMenuStringW@20
+GetMessageA@16
+GetMessageExtraInfo@0
+GetMessagePos@0
+GetMessageTime@0
+GetMessageW@16
+GetMonitorInfoA@8
+GetMonitorInfoW@8
+GetMouseMovePointsEx@20
+GetNextDlgGroupItem@12
+GetNextDlgTabItem@12
+GetOpenClipboardWindow@0
+GetParent@4
+GetPhysicalCursorPos@4
+GetPointerCursorId@8
+GetPointerDevice@8
+GetPointerDeviceCursors@12
+GetPointerDeviceProperties@12
+GetPointerDeviceRects@12
+GetPointerDevices@8
+GetPointerFrameInfo@12
+GetPointerFrameInfoHistory@16
+GetPointerFramePenInfo@12
+GetPointerFramePenInfoHistory@16
+GetPointerFrameTouchInfo@12
+GetPointerFrameTouchInfoHistory@16
+GetPointerInfo@8
+GetPointerInfoHistory@12
+GetPointerInputTransform@12
+GetPointerPenInfo@8
+GetPointerPenInfoHistory@12
+GetPointerTouchInfo@8
+GetPointerTouchInfoHistory@12
+GetPointerType@8
+GetPriorityClipboardFormat@8
+GetProcessDefaultLayout@4
+GetProcessDpiAwarenessInternal@8
+GetProcessWindowStation@0
+GetProgmanWindow@0
+GetPropA@8
+GetPropW@8
+GetQueueStatus@4
+GetRawInputBuffer@12
+GetRawInputData@20
+GetRawInputDeviceInfoA@16
+GetRawInputDeviceInfoW@16
+GetRawInputDeviceList@12
+GetRawPointerDeviceData@20
+GetReasonTitleFromReasonCode@12
+GetRegisteredRawInputDevices@12
+GetQueueStatus@4
+GetScrollBarInfo@12
+GetScrollInfo@12
+GetScrollPos@8
+GetScrollRange@16
+GetSendMessageReceiver@4
+GetShellWindow@0
+GetSubMenu@8
+GetSysColor@4
+GetSysColorBrush@4
+GetSystemMenu@8
+GetSystemMetrics@4
+GetTabbedTextExtentA@20
+GetTabbedTextExtentW@20
+GetTaskmanWindow@0
+GetThreadDesktop@4
+GetTitleBarInfo@8
+GetTopLevelWindow@4
+GetTopWindow@4
+GetTouchInputInfo@16
+GetUnpredictedMessagePos@0
+GetUpdateRect@12
+GetUpdateRgn@12
+GetUpdatedClipboardFormats@12
+GetUserObjectInformationA@20
+GetUserObjectInformationW@20
+GetUserObjectSecurity@20
+GetWinStationInfo@4
+GetWindow@8
+GetWindowBand@8
+GetWindowCompositionAttribute@8
+GetWindowCompositionInfo@8
+GetWindowContextHelpId@4
+GetWindowDC@4
+GetWindowDisplayAffinity@8
+GetWindowFeedbackSetting@20
+GetWindowInfo@8
+GetWindowLongA@8
+GetWindowLongW@8
+GetWindowMinimizeRect@8
+GetWindowModuleFileName@12
+GetWindowModuleFileNameA@12
+GetWindowModuleFileNameW@12
+GetWindowPlacement@8
+GetWindowRect@8
+GetWindowRgn@8
+GetWindowRgnBox@8
+GetWindowRgnEx@12
+GetWindowTextA@12
+GetWindowTextLengthA@4
+GetWindowTextLengthW@4
+GetWindowTextW@12
+GetWindowThreadProcessId@8
+GetWindowWord@8
+GhostWindowFromHungWindow@4
+GrayStringA@36
+GrayStringW@36
+HideCaret@4
+HiliteMenuItem@16
+HungWindowFromGhostWindow@4
+IMPGetIMEA@8
+IMPGetIMEW@8
+IMPQueryIMEA@4
+IMPQueryIMEW@4
+IMPSetIMEA@8
+IMPSetIMEW@8
+ImpersonateDdeClientWindow@8
+InSendMessage@0
+InSendMessageEx@4
+InflateRect@12
+InitializeLpkHooks@4
+InitializeWin32EntryTable@4
+InitializeTouchInjection@8
+InjectTouchInput@8
+InsertMenuA@20
+InsertMenuItemA@16
+InsertMenuItemW@16
+InsertMenuW@20
+InternalGetWindowIcon@8
+;ord_2001@4 @2001
+;ord_2002@4 @2002
+InternalGetWindowText@12
+IntersectRect@12
+;ord_2005@4 @2005
+InvalidateRect@12
+InvalidateRgn@12
+InvertRect@8
+IsCharAlphaA@4
+;ord_2010@16 @2010
+IsCharAlphaNumericA@4
+IsCharAlphaNumericW@4
+IsCharAlphaW@4
+IsCharLowerA@4
+IsCharLowerW@4
+IsCharUpperA@4
+IsCharUpperW@4
+IsChild@8
+IsClipboardFormatAvailable@4
+IsDialogMessage@8
+IsDialogMessageA@8
+IsDialogMessageW@8
+IsDlgButtonChecked@8
+IsGUIThread@4
+IsHungAppWindow@4
+IsIconic@4
+IsImmersiveProcess@4
+IsInDesktopWindowBand@4
+IsMenu@4
+IsProcess16Bit@0
+IsMouseInPointerEnabled@0
+IsProcessDPIAware@0
+IsQueueAttached@0
+IsRectEmpty@4
+IsSETEnabled@0
+IsServerSideWindow@4
+IsThreadDesktopComposited@0
+IsTopLevelWindow@4
+IsTouchWindow@8
+IsWinEventHookInstalled@4
+IsWindow@4
+IsWindowEnabled@4
+IsWindowInDestroy@4
+IsWindowRedirectedForPrint@4
+IsWindowUnicode@4
+IsWindowVisible@4
+IsWow64Message@0
+IsZoomed@4
+KillSystemTimer@8
+KillTimer@8
+LoadAcceleratorsA@8
+LoadAcceleratorsW@8
+LoadBitmapA@8
+LoadBitmapW@8
+LoadCursorA@8
+LoadCursorFromFileA@4
+LoadCursorFromFileW@4
+;ord_2000@0 @2000
+;ord_2001@4 @2001
+;ord_2002@4 @2002
+LoadCursorW@8
+LoadIconA@8
+;ord_2005@4 @2005
+LoadIconW@8
+LoadImageA@24
+LoadImageW@24
+LoadKeyboardLayoutA@8
+LoadKeyboardLayoutEx@12
+LoadKeyboardLayoutW@8
+LoadLocalFonts@0
+LoadMenuA@8
+LoadMenuIndirectA@4
+LoadMenuIndirectW@4
+LoadMenuW@8
+LoadRemoteFonts@0
+LoadStringA@16
+LoadStringW@16
+LockSetForegroundWindow@4
+LockWindowStation@4
+LockWindowUpdate@4
+LockWorkStation@0
+LogicalToPhysicalPoint@8
+LogicalToPhysicalPointForPerMonitorDPI@8
+LookupIconIdFromDirectory@8
+LookupIconIdFromDirectoryEx@20
+MBToWCSEx@24
+MBToWCSExt@20
+MB_GetString@4
+MapDialogRect@8
+MapVirtualKeyA@8
+MapVirtualKeyExA@12
+MapVirtualKeyExW@12
+MapVirtualKeyW@8
+MapWindowPoints@16
+MenuItemFromPoint@16
+MenuWindowProcA@20
+MenuWindowProcW@20
+MessageBeep@4
+MessageBoxA@16
+MessageBoxExA@20
+MessageBoxExW@20
+MessageBoxIndirectA@4
+MessageBoxIndirectW@4
+MessageBoxTimeoutA@24
+MessageBoxTimeoutW@24
+MessageBoxW@16
+ModifyMenuA@20
+ModifyMenuW@20
+MonitorFromPoint@12
+MonitorFromRect@8
+MonitorFromWindow@8
+MoveWindow@24
+MsgWaitForMultipleObjects@20
+MsgWaitForMultipleObjectsEx@20
+NotifyOverlayWindow@8
+NotifyWinEvent@16
+OemKeyScan@4
+OemToCharA@8
+OemToCharBuffA@12
+OemToCharBuffW@12
+OemToCharW@8
+OffsetRect@12
+OpenClipboard@4
+OpenDesktopA@16
+OpenDesktopW@16
+OpenIcon@4
+OpenInputDesktop@12
+OpenThreadDesktop@16
+OpenWindowStationA@12
+OpenWindowStationW@12
+PackDDElParam@12
+PackTouchHitTestingProximityEvaluation@8
+PaintDesktop@4
+PaintMenuBar@24
+PaintMonitor@12
+PeekMessageA@20
+PeekMessageW@20
+PhysicalToLogicalPoint@8
+PhysicalToLogicalPointForPerMonitorDPI@8
+PostMessageA@16
+PostMessageW@16
+PostQuitMessage@4
+PostThreadMessageA@16
+PostThreadMessageW@16
+PrintWindow@12
+PrivateExtractIconExA@20
+PrivateExtractIconExW@20
+PrivateExtractIconsA@32
+PrivateExtractIconsW@32
+PrivateSetDbgTag@8
+PrivateSetRipFlags@8
+PrivateRegisterICSProc@4
+PtInRect@12
+QueryBSDRWindow@0
+QueryDisplayConfig@24
+QuerySendMessage@4
+QueryUserCounters@20
+RealChildWindowFromPoint@12
+RealGetWindowClass@12
+RealGetWindowClassA@12
+RealGetWindowClassW@12
+ReasonCodeNeedsBugID@4
+ReasonCodeNeedsComment@4
+RecordShutdownReason@4
+RedrawWindow@16
+RegisterBSDRWindow@8
+RegisterClassA@4
+RegisterClassExA@4
+RegisterClassExW@4
+RegisterClassW@4
+RegisterClipboardFormatA@4
+RegisterClipboardFormatW@4
+RegisterDeviceNotificationA@12
+RegisterDeviceNotificationW@12
+RegisterErrorReportingDialog@8
+RegisterFrostWindow@8
+RegisterGhostWindow@8
+RegisterHotKey@16
+RegisterPowerSettingNotification@12
+RegisterLogonProcess@8
+RegisterMessagePumpHook@4
+RegisterPointerDeviceNotifications@8
+RegisterPointerInputTarget@8
+RegisterPowerSettingNotification@12
+RegisterRawInputDevices@12
+RegisterServicesProcess@4
+RegisterSessionPort@4 ; Undocumented, rumored to be related to ALPC - http://blogs.msdn.com/b/ntdebugging/archive/2007/07/26/lpc-local-procedure-calls-part-1-architecture.aspx
+RegisterShellHookWindow@4
+RegisterSuspendResumeNotification@8
+RegisterSystemThread@8
+RegisterTasklist@4
+RegisterTouchHitTestingWindow@8
+RegisterTouchWindow@8
+RegisterUserApiHook@4 ; Prototype changed in 2003 - https://www.reactos.org/wiki/Techwiki:RegisterUserApiHook
+RegisterWindowMessageA@4
+RegisterWindowMessageW@4
+ReleaseCapture@0
+ReleaseDC@8
+RemoveClipboardFormatListener@4
+RemoveMenu@12
+RemovePropA@8
+RemovePropW@8
+ReplyMessage@4
+ResolveDesktopForWOW@4
+ReuseDDElParam@20
+ScreenToClient@8
+ScrollChildren@12
+ScrollDC@28
+ScrollWindow@20
+ScrollWindowEx@32
+SendDlgItemMessageA@20
+SendDlgItemMessageW@20
+SendIMEMessageExA@8
+SendIMEMessageExW@8
+SendInput@12
+SendMessageA@16
+SendMessageCallbackA@24
+SendMessageCallbackW@24
+SendMessageTimeoutA@28
+SendMessageTimeoutW@28
+SendMessageW@16
+SendNotifyMessageA@16
+SendNotifyMessageW@16
+SetActiveWindow@4
+SetCapture@4
+SetCaretBlinkTime@4
+SetCaretPos@8
+SetClassLongA@12
+SetClassLongW@12
+SetClassWord@12
+SetClipboardData@8
+SetClipboardViewer@4
+SetConsoleReserveKeys@8
+SetCoalescableTimer@20
+SetCursor@4
+SetCursorContents@8
+SetCursorPos@8
+SetDebugErrorLevel@4
+SetDeskWallpaper@4
+SetDisplayAutoRotationPreferences@4
+SetDisplayConfig@20
+SetDlgItemInt@16
+SetDlgItemTextA@12
+SetDlgItemTextW@12
+SetDoubleClickTime@4
+SetFocus@4
+SetForegroundWindow@4
+SetGestureConfig@20
+SetImmersiveBackgroundWindow@4
+SetInternalWindowPos@16
+SetKeyboardState@4
+SetLastErrorEx@8
+SetLayeredWindowAttributes@16
+SetLogonNotifyWindow@4
+SetMagnificationDesktopColorEffect@4
+SetMagnificationDesktopMagnification@16
+SetMagnificationLensCtxInformation@16
+SetMenu@8
+SetMenuContextHelpId@8
+SetMenuDefaultItem@12
+SetMenuInfo@8
+SetMenuItemBitmaps@20
+SetMenuItemInfoA@16
+SetMenuItemInfoW@16
+SetMessageExtraInfo@4
+SetMessageQueue@4
+SetMirrorRendering@8
+SetParent@8
+SetPhysicalCursorPos@8
+SetProcessDPIAware@0
+SetProcessDefaultLayout@4
+SetProcessDpiAwarenessInternal@4
+SetProcessRestrictionExemption@4
+SetProcessWindowStation@4
+SetProgmanWindow@4
+SetPropA@12
+SetPropW@12
+SetRect@20
+SetRectEmpty@4
+SetScrollInfo@16
+SetScrollPos@16
+SetScrollRange@20
+SetShellWindow@4
+SetShellWindowEx@8
+SetSysColors@12
+SetSysColorsTemp@12
+SetSystemCursor@8
+SetSystemMenu@8
+SetSystemTimer@16
+SetTaskmanWindow@4
+SetThreadDesktop@4
+SetThreadInputBlocked@8
+SetTimer@16
+SetUserObjectInformationA@16
+SetUserObjectInformationW@16
+SetUserObjectSecurity@12
+SetWinEventHook@28
+SetWindowBand@12
+SetWindowCompositionAttribute@8
+SetWindowCompositionTransition@28
+SetWindowContextHelpId@8
+SetWindowDisplayAffinity@8
+SetWindowFeedbackSetting@20
+SetWindowLongA@12
+SetWindowLongW@12
+SetWindowPlacement@8
+SetWindowPos@28
+SetWindowRgn@12
+SetWindowRgnEx@12
+SetWindowStationUser@16
+SetWindowTextA@8
+SetWindowTextW@8
+SetWindowWord@12
+SetWindowsHookA@8
+SetWindowsHookExA@16
+SetWindowsHookExW@16
+SetWindowsHookW@8
+SfmDxBindSwapChain@12
+SfmDxGetSwapChainStats@8
+SfmDxOpenSwapChain@16
+SfmDxQuerySwapChainBindingStatus@12
+SfmDxReleaseSwapChain@8
+SfmDxReportPendingBindingsToDwm@0
+SfmDxSetSwapChainBindingStatus@8
+SfmDxSetSwapChainStats@8
+ShowCaret@4
+ShowCursor@4
+ShowOwnedPopups@8
+ShowScrollBar@12
+ShowStartGlass@4
+ShowSystemCursor@4
+ShowWindow@8
+ShowWindowAsync@8
+ShutdownBlockReasonCreate@8
+ShutdownBlockReasonDestroy@4
+ShutdownBlockReasonQuery@12
+SignalRedirectionStartComplete@0
+SkipPointerFrameMessages@4
+SoftModalMessageBox@4
+SoundSentry@0
+SubtractRect@12
+SwapMouseButton@4
+SwitchDesktop@4
+SwitchDesktopWithFade@12 ; Same as SwithDesktop(), only with fade (done at log-in), only usable by winlogon - http://blog.airesoft.co.uk/2010/08/things-microsoft-can-do-that-you-cant/
+SwitchToThisWindow@8
+SystemParametersInfoA@16
+SystemParametersInfoW@16
+TabbedTextOutA@32
+TabbedTextOutW@32
+TileChildWindows@8
+TileWindows@20
+ToAscii@20
+ToAsciiEx@24
+ToUnicode@24
+ToUnicodeEx@28
+TrackMouseEvent@4
+TrackPopupMenu@28
+TrackPopupMenuEx@24
+TranslateAccelerator@12
+TranslateAcceleratorA@12
+TranslateAcceleratorW@12
+TranslateMDISysAccel@8
+TranslateMessage@4
+TranslateMessageEx@8
+UnhookWinEvent@4
+UnhookWindowsHook@8
+UnhookWindowsHookEx@4
+UnionRect@12
+UnloadKeyboardLayout@4
+UnlockWindowStation@4
+UnpackDDElParam@16
+UnregisterClassA@8
+UnregisterClassW@8
+UnregisterDeviceNotification@4
+UnregisterHotKey@8
+UnregisterMessagePumpHook@0
+UnregisterPointerInputTarget@8
+UnregisterPowerSettingNotification@4
+UnregisterSessionPort@0
+UnregisterSuspendResumeNotification@4
+UnregisterTouchWindow@4
+UnregisterUserApiHook@0
+UpdateDefaultDesktopThumbnail@20
+UpdateLayeredWindow@36
+UpdateLayeredWindowIndirect@8
+UpdatePerUserSystemParameters@4 ; Undocumented, seems to apply certain registry settings to desktop, etc. ReactOS has @8 version - http://doxygen.reactos.org/d0/d92/win32ss_2user_2user32_2misc_2misc_8c_a1ff565f0af6bac6dce604f9f4473fe79.html ; @4 is rumored to be without the first DWORD
+UpdateWindow@4
+UpdateWindowInputSinkHints@8
+UpdateWindowTransform@12
+User32InitializeImmEntryTable@4
+UserClientDllInitialize@12
+UserHandleGrantAccess@12
+UserLpkPSMTextOut@24
+UserLpkTabbedTextOut@48
+UserRealizePalette@4
+UserRegisterWowHandlers@8
+VRipOutput@0
+VTagOutput@0
+ValidateRect@8
+ValidateRgn@8
+VkKeyScanA@4
+VkKeyScanExA@8
+VkKeyScanExW@8
+VkKeyScanW@4
+WCSToMBEx@24
+WINNLSEnableIME@8
+WINNLSGetEnableStatus@4
+WINNLSGetIMEHotkey@4
+WaitForInputIdle@8
+WaitForRedirectionStartComplete@0
+WaitMessage@0
+Win32PoolAllocationStats@24
+WinHelpA@16
+WinHelpW@16
+WindowFromDC@4
+WindowFromPhysicalPoint@8
+WindowFromPoint@8
+_UserTestTokenForInteractive@8
+gSharedInfo DATA
+gapfnScSendMessage DATA
+keybd_event@16
+mouse_event@20
+wsprintfA
+wsprintfW
+wvsprintfA@12
+wvsprintfW@12
+;ord_2500@16 @2500
+;ord_2501@12 @2501
+;ord_2502@8 @2502
+;ord_2503@24 @2503
+;ord_2504@8 @2504
+;ord_2505@8 @2505
+;ord_2506@12 @2506
+;ord_2507@4 @2507
+;ord_2508@8 @2508
+;ord_2509@4 @2509
+;ord_2510@12 @2510
+;ord_2511@8 @2511
+;ord_2512@12 @2512
+;ord_2513@4 @2513
+;ord_2514@8 @2514
+;ord_2515@8 @2515
+;ord_2516@12 @2516
+;ord_2517@4 @2517
+;ord_2518@0 @2518
+;ord_2519@4 @2519
+;ord_2520@0 @2520
+;ord_2521@8 @2521
+;ord_2522@4 @2522
+;ord_2523@8 @2523
+;ord_2524@8 @2524
+;ord_2525@12 @2525
+;ord_2526@12 @2526
+;ord_2527@12 @2527
+IsThreadMessageQueueAttached@4
+;ord_2529@4 @2529
+;ord_2530@8 @2530
+;ord_2531@16 @2531
+;ord_2532@8 @2532
+;ord_2533@4 @2533
+;ord_2534@8 @2534
+;ord_2535@0 @2535
+;ord_2536@8 @2536
+;ord_2537@16 @2537
+;ord_2538@4 @2538
+;ord_2539@4 @2539
+;ord_2540@4 @2540
+;ord_2541@0 @2541
+;ord_2544@4 @2544
+;ord_2545@8 @2545
+;ord_2546@4 @2546
+;ord_2547@4 @2547
+;ord_2548@4 @2548
+;ord_2549@4 @2549
+;ord_2550@8 @2550
+;ord_2551@20 @2551
+;ord_2552@8 @2552
+;ord_2553@32 @2553
+;ord_2554@12 @2554
+;ord_2555@16 @2555
+;ord_2556@8 @2556
+;ord_2557@12 @2557
+;ord_2558@12 @2558
+;ord_2559@16 @2559
+;ord_2560@20 @2560
+;ord_2561@0 @2561
+;ord_2562@0 @2562
+;ord_2563@0 @2563
diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig
index f298d14631..9144d2c644 100644
--- a/lib/std/array_list.zig
+++ b/lib/std/array_list.zig
@@ -371,7 +371,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
var self = Self{};
- const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);
+ const new_memory = try allocator.allocAdvanced(T, alignment, num, .at_least);
self.items.ptr = new_memory.ptr;
self.capacity = new_memory.len;
@@ -419,7 +419,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Replace range of elements `list[start..start+len]` with `new_items`
/// grows list if `len < new_items.len`. may allocate
/// shrinks list if `len > new_items.len`
- pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void {
+ pub fn replaceRange(self: *Self, allocator: *Allocator, start: usize, len: usize, new_items: SliceConst) !void {
var managed = self.toManaged(allocator);
try managed.replaceRange(start, len, new_items);
self.* = managed.toUnmanaged();
@@ -617,201 +617,414 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
};
}
-test "std.ArrayList.init" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.init" {
+ {
+ var list = ArrayList(i32).init(testing.allocator);
+ defer list.deinit();
- testing.expect(list.items.len == 0);
- testing.expect(list.capacity == 0);
-}
+ testing.expect(list.items.len == 0);
+ testing.expect(list.capacity == 0);
+ }
-test "std.ArrayList.initCapacity" {
- var list = try ArrayList(i8).initCapacity(testing.allocator, 200);
- defer list.deinit();
- testing.expect(list.items.len == 0);
- testing.expect(list.capacity >= 200);
-}
+ {
+ var list = ArrayListUnmanaged(i32){};
-test "std.ArrayList.basic" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+ testing.expect(list.items.len == 0);
+ testing.expect(list.capacity == 0);
+ }
+}
+test "std.ArrayList/ArrayListUnmanaged.initCapacity" {
+ const a = testing.allocator;
{
- var i: usize = 0;
- while (i < 10) : (i += 1) {
- list.append(@intCast(i32, i + 1)) catch unreachable;
- }
+ var list = try ArrayList(i8).initCapacity(a, 200);
+ defer list.deinit();
+ testing.expect(list.items.len == 0);
+ testing.expect(list.capacity >= 200);
+ }
+ {
+ var list = try ArrayListUnmanaged(i8).initCapacity(a, 200);
+ defer list.deinit(a);
+ testing.expect(list.items.len == 0);
+ testing.expect(list.capacity >= 200);
}
+}
+test "std.ArrayList/ArrayListUnmanaged.basic" {
+ const a = testing.allocator;
{
- var i: usize = 0;
- while (i < 10) : (i += 1) {
- testing.expect(list.items[i] == @intCast(i32, i + 1));
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
+
+ {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ list.append(@intCast(i32, i + 1)) catch unreachable;
+ }
+ }
+
+ {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ testing.expect(list.items[i] == @intCast(i32, i + 1));
+ }
+ }
+
+ for (list.items) |v, i| {
+ testing.expect(v == @intCast(i32, i + 1));
}
- }
- for (list.items) |v, i| {
- testing.expect(v == @intCast(i32, i + 1));
+ testing.expect(list.pop() == 10);
+ testing.expect(list.items.len == 9);
+
+ list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable;
+ testing.expect(list.items.len == 12);
+ testing.expect(list.pop() == 3);
+ testing.expect(list.pop() == 2);
+ testing.expect(list.pop() == 1);
+ testing.expect(list.items.len == 9);
+
+ list.appendSlice(&[_]i32{}) catch unreachable;
+ testing.expect(list.items.len == 9);
+
+ // can only set on indices < self.items.len
+ list.items[7] = 33;
+ list.items[8] = 42;
+
+ testing.expect(list.pop() == 42);
+ testing.expect(list.pop() == 33);
}
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+
+ {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ list.append(a, @intCast(i32, i + 1)) catch unreachable;
+ }
+ }
+
+ {
+ var i: usize = 0;
+ while (i < 10) : (i += 1) {
+ testing.expect(list.items[i] == @intCast(i32, i + 1));
+ }
+ }
+
+ for (list.items) |v, i| {
+ testing.expect(v == @intCast(i32, i + 1));
+ }
- testing.expect(list.pop() == 10);
- testing.expect(list.items.len == 9);
+ testing.expect(list.pop() == 10);
+ testing.expect(list.items.len == 9);
- list.appendSlice(&[_]i32{ 1, 2, 3 }) catch unreachable;
- testing.expect(list.items.len == 12);
- testing.expect(list.pop() == 3);
- testing.expect(list.pop() == 2);
- testing.expect(list.pop() == 1);
- testing.expect(list.items.len == 9);
+ list.appendSlice(a, &[_]i32{ 1, 2, 3 }) catch unreachable;
+ testing.expect(list.items.len == 12);
+ testing.expect(list.pop() == 3);
+ testing.expect(list.pop() == 2);
+ testing.expect(list.pop() == 1);
+ testing.expect(list.items.len == 9);
- list.appendSlice(&[_]i32{}) catch unreachable;
- testing.expect(list.items.len == 9);
+ list.appendSlice(a, &[_]i32{}) catch unreachable;
+ testing.expect(list.items.len == 9);
- // can only set on indices < self.items.len
- list.items[7] = 33;
- list.items[8] = 42;
+ // can only set on indices < self.items.len
+ list.items[7] = 33;
+ list.items[8] = 42;
- testing.expect(list.pop() == 42);
- testing.expect(list.pop() == 33);
+ testing.expect(list.pop() == 42);
+ testing.expect(list.pop() == 33);
+ }
}
-test "std.ArrayList.appendNTimes" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.appendNTimes" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
+
+ try list.appendNTimes(2, 10);
+ testing.expectEqual(@as(usize, 10), list.items.len);
+ for (list.items) |element| {
+ testing.expectEqual(@as(i32, 2), element);
+ }
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
- try list.appendNTimes(2, 10);
- testing.expectEqual(@as(usize, 10), list.items.len);
- for (list.items) |element| {
- testing.expectEqual(@as(i32, 2), element);
+ try list.appendNTimes(a, 2, 10);
+ testing.expectEqual(@as(usize, 10), list.items.len);
+ for (list.items) |element| {
+ testing.expectEqual(@as(i32, 2), element);
+ }
}
}
-test "std.ArrayList.appendNTimes with failing allocator" {
- var list = ArrayList(i32).init(testing.failing_allocator);
- defer list.deinit();
- testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10));
+test "std.ArrayList/ArrayListUnmanaged.appendNTimes with failing allocator" {
+ const a = testing.failing_allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
+ testing.expectError(error.OutOfMemory, list.appendNTimes(2, 10));
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+ testing.expectError(error.OutOfMemory, list.appendNTimes(a, 2, 10));
+ }
}
-test "std.ArrayList.orderedRemove" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.orderedRemove" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
+
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.append(4);
+ try list.append(5);
+ try list.append(6);
+ try list.append(7);
+
+ //remove from middle
+ testing.expectEqual(@as(i32, 4), list.orderedRemove(3));
+ testing.expectEqual(@as(i32, 5), list.items[3]);
+ testing.expectEqual(@as(usize, 6), list.items.len);
+
+ //remove from end
+ testing.expectEqual(@as(i32, 7), list.orderedRemove(5));
+ testing.expectEqual(@as(usize, 5), list.items.len);
+
+ //remove from front
+ testing.expectEqual(@as(i32, 1), list.orderedRemove(0));
+ testing.expectEqual(@as(i32, 2), list.items[0]);
+ testing.expectEqual(@as(usize, 4), list.items.len);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
- try list.append(1);
- try list.append(2);
- try list.append(3);
- try list.append(4);
- try list.append(5);
- try list.append(6);
- try list.append(7);
-
- //remove from middle
- testing.expectEqual(@as(i32, 4), list.orderedRemove(3));
- testing.expectEqual(@as(i32, 5), list.items[3]);
- testing.expectEqual(@as(usize, 6), list.items.len);
-
- //remove from end
- testing.expectEqual(@as(i32, 7), list.orderedRemove(5));
- testing.expectEqual(@as(usize, 5), list.items.len);
-
- //remove from front
- testing.expectEqual(@as(i32, 1), list.orderedRemove(0));
- testing.expectEqual(@as(i32, 2), list.items[0]);
- testing.expectEqual(@as(usize, 4), list.items.len);
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+ try list.append(a, 4);
+ try list.append(a, 5);
+ try list.append(a, 6);
+ try list.append(a, 7);
+
+ //remove from middle
+ testing.expectEqual(@as(i32, 4), list.orderedRemove(3));
+ testing.expectEqual(@as(i32, 5), list.items[3]);
+ testing.expectEqual(@as(usize, 6), list.items.len);
+
+ //remove from end
+ testing.expectEqual(@as(i32, 7), list.orderedRemove(5));
+ testing.expectEqual(@as(usize, 5), list.items.len);
+
+ //remove from front
+ testing.expectEqual(@as(i32, 1), list.orderedRemove(0));
+ testing.expectEqual(@as(i32, 2), list.items[0]);
+ testing.expectEqual(@as(usize, 4), list.items.len);
+ }
}
-test "std.ArrayList.swapRemove" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.swapRemove" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
- try list.append(1);
- try list.append(2);
- try list.append(3);
- try list.append(4);
- try list.append(5);
- try list.append(6);
- try list.append(7);
-
- //remove from middle
- testing.expect(list.swapRemove(3) == 4);
- testing.expect(list.items[3] == 7);
- testing.expect(list.items.len == 6);
-
- //remove from end
- testing.expect(list.swapRemove(5) == 6);
- testing.expect(list.items.len == 5);
-
- //remove from front
- testing.expect(list.swapRemove(0) == 1);
- testing.expect(list.items[0] == 5);
- testing.expect(list.items.len == 4);
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.append(4);
+ try list.append(5);
+ try list.append(6);
+ try list.append(7);
+
+ //remove from middle
+ testing.expect(list.swapRemove(3) == 4);
+ testing.expect(list.items[3] == 7);
+ testing.expect(list.items.len == 6);
+
+ //remove from end
+ testing.expect(list.swapRemove(5) == 6);
+ testing.expect(list.items.len == 5);
+
+ //remove from front
+ testing.expect(list.swapRemove(0) == 1);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items.len == 4);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+ try list.append(a, 4);
+ try list.append(a, 5);
+ try list.append(a, 6);
+ try list.append(a, 7);
+
+ //remove from middle
+ testing.expect(list.swapRemove(3) == 4);
+ testing.expect(list.items[3] == 7);
+ testing.expect(list.items.len == 6);
+
+ //remove from end
+ testing.expect(list.swapRemove(5) == 6);
+ testing.expect(list.items.len == 5);
+
+ //remove from front
+ testing.expect(list.swapRemove(0) == 1);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items.len == 4);
+ }
}
-test "std.ArrayList.insert" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.insert" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
- try list.append(1);
- try list.append(2);
- try list.append(3);
- try list.insert(0, 5);
- testing.expect(list.items[0] == 5);
- testing.expect(list.items[1] == 1);
- testing.expect(list.items[2] == 2);
- testing.expect(list.items[3] == 3);
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.insert(0, 5);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items[1] == 1);
+ testing.expect(list.items[2] == 2);
+ testing.expect(list.items[3] == 3);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+ try list.insert(a, 0, 5);
+ testing.expect(list.items[0] == 5);
+ testing.expect(list.items[1] == 1);
+ testing.expect(list.items[2] == 2);
+ testing.expect(list.items[3] == 3);
+ }
}
-test "std.ArrayList.insertSlice" {
- var list = ArrayList(i32).init(testing.allocator);
- defer list.deinit();
+test "std.ArrayList/ArrayListUnmanaged.insertSlice" {
+ const a = testing.allocator;
+ {
+ var list = ArrayList(i32).init(a);
+ defer list.deinit();
- try list.append(1);
- try list.append(2);
- try list.append(3);
- try list.append(4);
- try list.insertSlice(1, &[_]i32{ 9, 8 });
- testing.expect(list.items[0] == 1);
- testing.expect(list.items[1] == 9);
- testing.expect(list.items[2] == 8);
- testing.expect(list.items[3] == 2);
- testing.expect(list.items[4] == 3);
- testing.expect(list.items[5] == 4);
-
- const items = [_]i32{1};
- try list.insertSlice(0, items[0..0]);
- testing.expect(list.items.len == 6);
- testing.expect(list.items[0] == 1);
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
+ try list.append(4);
+ try list.insertSlice(1, &[_]i32{ 9, 8 });
+ testing.expect(list.items[0] == 1);
+ testing.expect(list.items[1] == 9);
+ testing.expect(list.items[2] == 8);
+ testing.expect(list.items[3] == 2);
+ testing.expect(list.items[4] == 3);
+ testing.expect(list.items[5] == 4);
+
+ const items = [_]i32{1};
+ try list.insertSlice(0, items[0..0]);
+ testing.expect(list.items.len == 6);
+ testing.expect(list.items[0] == 1);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+ defer list.deinit(a);
+
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+ try list.append(a, 4);
+ try list.insertSlice(a, 1, &[_]i32{ 9, 8 });
+ testing.expect(list.items[0] == 1);
+ testing.expect(list.items[1] == 9);
+ testing.expect(list.items[2] == 8);
+ testing.expect(list.items[3] == 2);
+ testing.expect(list.items[4] == 3);
+ testing.expect(list.items[5] == 4);
+
+ const items = [_]i32{1};
+ try list.insertSlice(a, 0, items[0..0]);
+ testing.expect(list.items.len == 6);
+ testing.expect(list.items[0] == 1);
+ }
}
-test "std.ArrayList.replaceRange" {
+test "std.ArrayList/ArrayListUnmanaged.replaceRange" {
var arena = std.heap.ArenaAllocator.init(testing.allocator);
defer arena.deinit();
+ const a = &arena.allocator;
- const alloc = &arena.allocator;
const init = [_]i32{ 1, 2, 3, 4, 5 };
const new = [_]i32{ 0, 0, 0 };
- var list_zero = ArrayList(i32).init(alloc);
- var list_eq = ArrayList(i32).init(alloc);
- var list_lt = ArrayList(i32).init(alloc);
- var list_gt = ArrayList(i32).init(alloc);
+ const result_zero = [_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 };
+ const result_eq = [_]i32{ 1, 0, 0, 0, 5 };
+ const result_le = [_]i32{ 1, 0, 0, 0, 4, 5 };
+ const result_gt = [_]i32{ 1, 0, 0, 0 };
- try list_zero.appendSlice(&init);
- try list_eq.appendSlice(&init);
- try list_lt.appendSlice(&init);
- try list_gt.appendSlice(&init);
-
- try list_zero.replaceRange(1, 0, &new);
- try list_eq.replaceRange(1, 3, &new);
- try list_lt.replaceRange(1, 2, &new);
-
- // after_range > new_items.len in function body
- testing.expect(1 + 4 > new.len);
- try list_gt.replaceRange(1, 4, &new);
-
- testing.expectEqualSlices(i32, list_zero.items, &[_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 });
- testing.expectEqualSlices(i32, list_eq.items, &[_]i32{ 1, 0, 0, 0, 5 });
- testing.expectEqualSlices(i32, list_lt.items, &[_]i32{ 1, 0, 0, 0, 4, 5 });
- testing.expectEqualSlices(i32, list_gt.items, &[_]i32{ 1, 0, 0, 0 });
+ {
+ var list_zero = ArrayList(i32).init(a);
+ var list_eq = ArrayList(i32).init(a);
+ var list_lt = ArrayList(i32).init(a);
+ var list_gt = ArrayList(i32).init(a);
+
+ try list_zero.appendSlice(&init);
+ try list_eq.appendSlice(&init);
+ try list_lt.appendSlice(&init);
+ try list_gt.appendSlice(&init);
+
+ try list_zero.replaceRange(1, 0, &new);
+ try list_eq.replaceRange(1, 3, &new);
+ try list_lt.replaceRange(1, 2, &new);
+
+ // after_range > new_items.len in function body
+ testing.expect(1 + 4 > new.len);
+ try list_gt.replaceRange(1, 4, &new);
+
+ testing.expectEqualSlices(i32, list_zero.items, &result_zero);
+ testing.expectEqualSlices(i32, list_eq.items, &result_eq);
+ testing.expectEqualSlices(i32, list_lt.items, &result_le);
+ testing.expectEqualSlices(i32, list_gt.items, &result_gt);
+ }
+ {
+ var list_zero = ArrayListUnmanaged(i32){};
+ var list_eq = ArrayListUnmanaged(i32){};
+ var list_lt = ArrayListUnmanaged(i32){};
+ var list_gt = ArrayListUnmanaged(i32){};
+
+ try list_zero.appendSlice(a, &init);
+ try list_eq.appendSlice(a, &init);
+ try list_lt.appendSlice(a, &init);
+ try list_gt.appendSlice(a, &init);
+
+ try list_zero.replaceRange(a, 1, 0, &new);
+ try list_eq.replaceRange(a, 1, 3, &new);
+ try list_lt.replaceRange(a, 1, 2, &new);
+
+ // after_range > new_items.len in function body
+ testing.expect(1 + 4 > new.len);
+ try list_gt.replaceRange(a, 1, 4, &new);
+
+ testing.expectEqualSlices(i32, list_zero.items, &result_zero);
+ testing.expectEqualSlices(i32, list_eq.items, &result_eq);
+ testing.expectEqualSlices(i32, list_lt.items, &result_le);
+ testing.expectEqualSlices(i32, list_gt.items, &result_gt);
+ }
}
const Item = struct {
@@ -819,11 +1032,25 @@ const Item = struct {
sub_items: ArrayList(Item),
};
-test "std.ArrayList: ArrayList(T) of struct T" {
- var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(testing.allocator) };
- defer root.sub_items.deinit();
- try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(testing.allocator) });
- testing.expect(root.sub_items.items[0].integer == 42);
+const ItemUnmanaged = struct {
+ integer: i32,
+ sub_items: ArrayListUnmanaged(ItemUnmanaged),
+};
+
+test "std.ArrayList/ArrayListUnmanaged: ArrayList(T) of struct T" {
+ const a = std.testing.allocator;
+ {
+ var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(a) };
+ defer root.sub_items.deinit();
+ try root.sub_items.append(Item{ .integer = 42, .sub_items = ArrayList(Item).init(a) });
+ testing.expect(root.sub_items.items[0].integer == 42);
+ }
+ {
+ var root = ItemUnmanaged{ .integer = 1, .sub_items = ArrayListUnmanaged(ItemUnmanaged){} };
+ defer root.sub_items.deinit(a);
+ try root.sub_items.append(a, ItemUnmanaged{ .integer = 42, .sub_items = ArrayListUnmanaged(ItemUnmanaged){} });
+ testing.expect(root.sub_items.items[0].integer == 42);
+ }
}
test "std.ArrayList(u8) implements outStream" {
@@ -837,19 +1064,32 @@ test "std.ArrayList(u8) implements outStream" {
testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.span());
}
-test "std.ArrayList.shrink still sets length on error.OutOfMemory" {
+test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" {
// use an arena allocator to make sure realloc returns error.OutOfMemory
var arena = std.heap.ArenaAllocator.init(testing.allocator);
defer arena.deinit();
+ const a = &arena.allocator;
- var list = ArrayList(i32).init(&arena.allocator);
+ {
+ var list = ArrayList(i32).init(a);
- try list.append(1);
- try list.append(2);
- try list.append(3);
+ try list.append(1);
+ try list.append(2);
+ try list.append(3);
- list.shrink(1);
- testing.expect(list.items.len == 1);
+ list.shrink(1);
+ testing.expect(list.items.len == 1);
+ }
+ {
+ var list = ArrayListUnmanaged(i32){};
+
+ try list.append(a, 1);
+ try list.append(a, 2);
+ try list.append(a, 3);
+
+ list.shrink(a, 1);
+ testing.expect(list.items.len == 1);
+ }
}
test "std.ArrayList.writer" {
@@ -864,7 +1104,7 @@ test "std.ArrayList.writer" {
testing.expectEqualSlices(u8, list.items, "abcdefg");
}
-test "addManyAsArray" {
+test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
const a = std.testing.allocator;
{
var list = ArrayList(u8).init(a);
diff --git a/lib/std/build.zig b/lib/std/build.zig
index 7e3c75bc78..6575e057e8 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -1232,6 +1232,9 @@ pub const LibExeObjStep = struct {
installed_path: ?[]const u8,
install_step: ?*InstallArtifactStep,
+ /// Base address for an executable image.
+ image_base: ?u64 = null,
+
libc_file: ?[]const u8 = null,
valgrind_support: ?bool = null,
@@ -1239,6 +1242,7 @@ pub const LibExeObjStep = struct {
/// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF
/// file.
link_eh_frame_hdr: bool = false,
+ link_emit_relocs: bool = false,
/// Place every function in its own section so that unused ones may be
/// safely garbage-collected during the linking phase.
@@ -1384,66 +1388,50 @@ pub const LibExeObjStep = struct {
}
fn computeOutFileNames(self: *LibExeObjStep) void {
- // TODO make this call std.zig.binNameAlloc
- switch (self.kind) {
- .Obj => {
- self.out_filename = self.builder.fmt("{}{}", .{ self.name, self.target.oFileExt() });
- },
- .Exe => {
- self.out_filename = self.builder.fmt("{}{}", .{ self.name, self.target.exeFileExt() });
- },
- .Test => {
- self.out_filename = self.builder.fmt("test{}", .{self.target.exeFileExt()});
+ const target_info = std.zig.system.NativeTargetInfo.detect(
+ self.builder.allocator,
+ self.target,
+ ) catch unreachable;
+ const target = target_info.target;
+ self.out_filename = std.zig.binNameAlloc(self.builder.allocator, .{
+ .root_name = self.name,
+ .target = target,
+ .output_mode = switch (self.kind) {
+ .Lib => .Lib,
+ .Obj => .Obj,
+ .Exe, .Test => .Exe,
},
- .Lib => {
- if (!self.is_dynamic) {
- self.out_filename = self.builder.fmt("{}{}{}", .{
- self.target.libPrefix(),
+ .link_mode = if (self.is_dynamic) .Dynamic else .Static,
+ .version = self.version,
+ }) catch unreachable;
+
+ if (self.kind == .Lib) {
+ if (!self.is_dynamic) {
+ self.out_lib_filename = self.out_filename;
+ } else if (self.version) |version| {
+ if (target.isDarwin()) {
+ self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", .{
self.name,
- self.target.staticLibSuffix(),
+ version.major,
});
+ self.name_only_filename = self.builder.fmt("lib{}.dylib", .{self.name});
self.out_lib_filename = self.out_filename;
- } else if (self.version) |version| {
- if (self.target.isDarwin()) {
- self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", .{
- self.name,
- version.major,
- version.minor,
- version.patch,
- });
- self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", .{
- self.name,
- version.major,
- });
- self.name_only_filename = self.builder.fmt("lib{}.dylib", .{self.name});
- self.out_lib_filename = self.out_filename;
- } else if (self.target.isWindows()) {
- self.out_filename = self.builder.fmt("{}.dll", .{self.name});
- self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name});
- } else {
- self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", .{
- self.name,
- version.major,
- version.minor,
- version.patch,
- });
- self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, version.major });
- self.name_only_filename = self.builder.fmt("lib{}.so", .{self.name});
- self.out_lib_filename = self.out_filename;
- }
+ } else if (target.os.tag == .windows) {
+ self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name});
} else {
- if (self.target.isDarwin()) {
- self.out_filename = self.builder.fmt("lib{}.dylib", .{self.name});
- self.out_lib_filename = self.out_filename;
- } else if (self.target.isWindows()) {
- self.out_filename = self.builder.fmt("{}.dll", .{self.name});
- self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name});
- } else {
- self.out_filename = self.builder.fmt("lib{}.so", .{self.name});
- self.out_lib_filename = self.out_filename;
- }
+ self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, version.major });
+ self.name_only_filename = self.builder.fmt("lib{}.so", .{self.name});
+ self.out_lib_filename = self.out_filename;
}
- },
+ } else {
+ if (target.isDarwin()) {
+ self.out_lib_filename = self.out_filename;
+ } else if (target.os.tag == .windows) {
+ self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name});
+ } else {
+ self.out_lib_filename = self.out_filename;
+ }
+ }
}
}
@@ -2040,6 +2028,11 @@ pub const LibExeObjStep = struct {
try zig_args.append("--pkg-end");
}
+ if (self.image_base) |image_base| {
+ try zig_args.append("--image-base");
+ try zig_args.append(builder.fmt("0x{x}", .{image_base}));
+ }
+
if (self.filter) |filter| {
try zig_args.append("--test-filter");
try zig_args.append(filter);
@@ -2075,6 +2068,9 @@ pub const LibExeObjStep = struct {
if (self.link_eh_frame_hdr) {
try zig_args.append("--eh-frame-hdr");
}
+ if (self.link_emit_relocs) {
+ try zig_args.append("--emit-relocs");
+ }
if (self.link_function_sections) {
try zig_args.append("-ffunction-sections");
}
@@ -2168,8 +2164,8 @@ pub const LibExeObjStep = struct {
}
if (self.linker_script) |linker_script| {
- zig_args.append("--linker-script") catch unreachable;
- zig_args.append(builder.pathFromRoot(linker_script)) catch unreachable;
+ try zig_args.append("--script");
+ try zig_args.append(builder.pathFromRoot(linker_script));
}
if (self.version_script) |version_script| {
@@ -2335,6 +2331,14 @@ pub const LibExeObjStep = struct {
var it = src_dir.iterate();
while (try it.next()) |entry| {
+ // The compiler can put these files into the same directory, but we don't
+ // want to copy them over.
+ if (mem.eql(u8, entry.name, "stage1.id") or
+ mem.eql(u8, entry.name, "llvm-ar.id") or
+ mem.eql(u8, entry.name, "libs.txt") or
+ mem.eql(u8, entry.name, "builtin.zig") or
+ mem.eql(u8, entry.name, "lld.id")) continue;
+
_ = try src_dir.updateFile(entry.name, dest_dir, entry.name, .{});
}
} else {
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 52b8f641cd..68bbbe3b2d 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -100,6 +100,16 @@ pub const AtomicOrder = enum {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
+pub const ReduceOp = enum {
+ And,
+ Or,
+ Xor,
+ Min,
+ Max,
+};
+
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
pub const AtomicRmwOp = enum {
Xchg,
Add,
@@ -262,6 +272,7 @@ pub const TypeInfo = union(enum) {
field_type: type,
default_value: anytype,
is_comptime: bool,
+ alignment: comptime_int,
};
/// This data structure is used by the Zig language code generation and
@@ -318,6 +329,7 @@ pub const TypeInfo = union(enum) {
pub const UnionField = struct {
name: []const u8,
field_type: type,
+ alignment: comptime_int,
};
/// This data structure is used by the Zig language code generation and
@@ -341,6 +353,7 @@ pub const TypeInfo = union(enum) {
/// therefore must be kept in sync with the compiler implementation.
pub const Fn = struct {
calling_convention: CallingConvention,
+ alignment: comptime_int,
is_generic: bool,
is_var_args: bool,
return_type: ?type,
diff --git a/lib/std/c.zig b/lib/std/c.zig
index aa50fff90e..7cfc44714f 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -342,3 +342,6 @@ pub extern "c" fn fsync(fd: c_int) c_int;
pub extern "c" fn fdatasync(fd: c_int) c_int;
pub extern "c" fn prctl(option: c_int, ...) c_int;
+
+pub extern "c" fn getrlimit(resource: rlimit_resource, rlim: *rlimit) c_int;
+pub extern "c" fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) c_int;
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig
index ed1ddb7d91..976690d6b7 100644
--- a/lib/std/c/darwin.zig
+++ b/lib/std/c/darwin.zig
@@ -12,7 +12,7 @@ usingnamespace @import("../os/bits.zig");
extern "c" fn __error() *c_int;
pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
-pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
+pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int;
pub extern "c" fn _dyld_image_count() u32;
pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header;
pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;
diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig
index 538fbdfd7d..d48c76c7a6 100644
--- a/lib/std/c/linux.zig
+++ b/lib/std/c/linux.zig
@@ -100,6 +100,8 @@ pub extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_
pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: c_uint) c_int;
+pub extern "c" fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: *const rlimit, old_limit: *rlimit) c_int;
+
pub const pthread_attr_t = extern struct {
__size: [56]u8,
__align: c_long,
diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig
index e706302ebd..52e9ac99ba 100644
--- a/lib/std/child_process.zig
+++ b/lib/std/child_process.zig
@@ -105,8 +105,8 @@ pub const ChildProcess = struct {
.term = null,
.env_map = null,
.cwd = null,
- .uid = if (builtin.os.tag == .windows) {} else null,
- .gid = if (builtin.os.tag == .windows) {} else null,
+ .uid = if (builtin.os.tag == .windows or builtin.os.tag == .wasi) {} else null,
+ .gid = if (builtin.os.tag == .windows or builtin.os.tag == .wasi) {} else null,
.stdin = null,
.stdout = null,
.stderr = null,
diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig
index fa69d51d4d..8c225aa719 100644
--- a/lib/std/crypto.zig
+++ b/lib/std/crypto.zig
@@ -4,6 +4,50 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
+/// Authenticated Encryption with Associated Data
+pub const aead = struct {
+ const chacha20 = @import("crypto/chacha20.zig");
+
+ pub const Gimli = @import("crypto/gimli.zig").Aead;
+ pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;
+ pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;
+ pub const AEGIS128L = @import("crypto/aegis.zig").AEGIS128L;
+ pub const AEGIS256 = @import("crypto/aegis.zig").AEGIS256;
+ pub const AES128GCM = @import("crypto/aes_gcm.zig").AES128GCM;
+ pub const AES256GCM = @import("crypto/aes_gcm.zig").AES256GCM;
+};
+
+/// Authentication (MAC) functions.
+pub const auth = struct {
+ pub const hmac = @import("crypto/hmac.zig");
+ pub const siphash = @import("crypto/siphash.zig");
+};
+
+/// Core functions, that should rarely be used directly by applications.
+pub const core = struct {
+ pub const aes = @import("crypto/aes.zig");
+ pub const Gimli = @import("crypto/gimli.zig").State;
+
+ /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations.
+ ///
+ /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees.
+ ///
+ /// Most applications may want to use AEADs instead.
+ pub const modes = @import("crypto/modes.zig");
+};
+
+/// Diffie-Hellman key exchange functions.
+pub const dh = struct {
+ pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
+};
+
+/// Elliptic-curve arithmetic.
+pub const ecc = struct {
+ pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
+ pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
+ pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
+};
+
/// Hash functions.
pub const hash = struct {
pub const Md5 = @import("crypto/md5.zig").Md5;
@@ -15,26 +59,15 @@ pub const hash = struct {
pub const Gimli = @import("crypto/gimli.zig").Hash;
};
-/// Authentication (MAC) functions.
-pub const auth = struct {
- pub const hmac = @import("crypto/hmac.zig");
- pub const siphash = @import("crypto/siphash.zig");
-};
-
-/// Authenticated Encryption with Associated Data
-pub const aead = struct {
- const chacha20 = @import("crypto/chacha20.zig");
-
- pub const Gimli = @import("crypto/gimli.zig").Aead;
- pub const ChaCha20Poly1305 = chacha20.Chacha20Poly1305;
- pub const XChaCha20Poly1305 = chacha20.XChacha20Poly1305;
- pub const AEGIS128L = @import("crypto/aegis.zig").AEGIS128L;
- pub const AEGIS256 = @import("crypto/aegis.zig").AEGIS256;
+/// Key derivation functions.
+pub const kdf = struct {
+ pub const hkdf = @import("crypto/hkdf.zig");
};
/// MAC functions requiring single-use secret keys.
pub const onetimeauth = struct {
pub const Poly1305 = @import("crypto/poly1305.zig").Poly1305;
+ pub const Ghash = @import("crypto/ghash.zig").Ghash;
};
/// A password hashing function derives a uniform key from low-entropy input material such as passwords.
@@ -57,31 +90,6 @@ pub const pwhash = struct {
pub const pbkdf2 = @import("crypto/pbkdf2.zig").pbkdf2;
};
-/// Core functions, that should rarely be used directly by applications.
-pub const core = struct {
- pub const aes = @import("crypto/aes.zig");
- pub const Gimli = @import("crypto/gimli.zig").State;
-
- /// Modes are generic compositions to construct encryption/decryption functions from block ciphers and permutations.
- ///
- /// These modes are designed to be building blocks for higher-level constructions, and should generally not be used directly by applications, as they may not provide the expected properties and security guarantees.
- ///
- /// Most applications may want to use AEADs instead.
- pub const modes = @import("crypto/modes.zig");
-};
-
-/// Elliptic-curve arithmetic.
-pub const ecc = struct {
- pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
- pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
- pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
-};
-
-/// Diffie-Hellman key exchange functions.
-pub const dh = struct {
- pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
-};
-
/// Digital signature functions.
pub const sign = struct {
pub const Ed25519 = @import("crypto/25519/ed25519.zig").Ed25519;
diff --git a/lib/std/crypto/25519/field.zig b/lib/std/crypto/25519/field.zig
index 61929ba044..0bc0ead5f2 100644
--- a/lib/std/crypto/25519/field.zig
+++ b/lib/std/crypto/25519/field.zig
@@ -307,12 +307,14 @@ pub const Fe = struct {
}
pub fn pow2523(a: Fe) Fe {
- var c = a;
- var i: usize = 0;
- while (i < 249) : (i += 1) {
- c = c.sq().mul(a);
- }
- return c.sq().sq().mul(a);
+ var t0 = a.mul(a.sq());
+ var t1 = t0.mul(t0.sqn(2)).sq().mul(a);
+ t0 = t1.sqn(5).mul(t1);
+ var t2 = t0.sqn(5).mul(t1);
+ t1 = t2.sqn(15).mul(t2);
+ t2 = t1.sqn(30).mul(t1);
+ t1 = t2.sqn(60).mul(t2);
+ return t1.sqn(120).mul(t1).sqn(10).mul(t0).sqn(2).mul(a);
}
pub fn abs(a: Fe) Fe {
diff --git a/lib/std/crypto/aes_gcm.zig b/lib/std/crypto/aes_gcm.zig
new file mode 100644
index 0000000000..c7093a7593
--- /dev/null
+++ b/lib/std/crypto/aes_gcm.zig
@@ -0,0 +1,161 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const builtin = std.builtin;
+const crypto = std.crypto;
+const debug = std.debug;
+const Ghash = std.crypto.onetimeauth.Ghash;
+const mem = std.mem;
+const modes = crypto.core.modes;
+
+pub const AES128GCM = AESGCM(crypto.core.aes.AES128);
+pub const AES256GCM = AESGCM(crypto.core.aes.AES256);
+
+fn AESGCM(comptime AES: anytype) type {
+ debug.assert(AES.block.block_size == 16);
+
+ return struct {
+ pub const tag_length = 16;
+ pub const nonce_length = 12;
+ pub const key_length = AES.key_bits / 8;
+
+ const zeros = [_]u8{0} ** 16;
+
+ pub fn encrypt(c: []u8, tag: *[tag_length]u8, m: []const u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) void {
+ debug.assert(c.len == m.len);
+ debug.assert(m.len <= 16 * ((1 << 32) - 2));
+
+ const aes = AES.initEnc(key);
+ var h: [16]u8 = undefined;
+ aes.encrypt(&h, &zeros);
+
+ var t: [16]u8 = undefined;
+ var j: [16]u8 = undefined;
+ mem.copy(u8, j[0..nonce_length], npub[0..]);
+ mem.writeIntBig(u32, j[nonce_length..][0..4], 1);
+ aes.encrypt(&t, &j);
+
+ var mac = Ghash.init(&h);
+ mac.update(ad);
+ mac.pad();
+
+ mem.writeIntBig(u32, j[nonce_length..][0..4], 2);
+ modes.ctr(@TypeOf(aes), aes, c, m, j, builtin.Endian.Big);
+ mac.update(c[0..m.len][0..]);
+ mac.pad();
+
+ var final_block = h;
+ mem.writeIntBig(u64, final_block[0..8], ad.len * 8);
+ mem.writeIntBig(u64, final_block[8..16], m.len * 8);
+ mac.update(&final_block);
+ mac.final(tag);
+ for (t) |x, i| {
+ tag[i] ^= x;
+ }
+ }
+
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void {
+ assert(c.len == m.len);
+
+ const aes = AES.initEnc(key);
+ var h: [16]u8 = undefined;
+ aes.encrypt(&h, &zeros);
+
+ var t: [16]u8 = undefined;
+ var j: [16]u8 = undefined;
+ mem.copy(u8, j[0..nonce_length], npub[0..]);
+ mem.writeIntBig(u32, j[nonce_length..][0..4], 1);
+ aes.encrypt(&t, &j);
+
+ var mac = Ghash.init(&h);
+ mac.update(ad);
+ mac.pad();
+
+ mac.update(c);
+ mac.pad();
+
+ var final_block = h;
+ mem.writeIntBig(u64, final_block[0..8], ad.len * 8);
+ mem.writeIntBig(u64, final_block[8..16], m.len * 8);
+ mac.update(&final_block);
+ var computed_tag: [Ghash.mac_length]u8 = undefined;
+ mac.final(&computed_tag);
+ for (t) |x, i| {
+ computed_tag[i] ^= x;
+ }
+
+ var acc: u8 = 0;
+ for (computed_tag) |_, p| {
+ acc |= (computed_tag[p] ^ tag[p]);
+ }
+ if (acc != 0) {
+ mem.set(u8, m, 0xaa);
+ return error.AuthenticationFailed;
+ }
+
+ mem.writeIntBig(u32, j[nonce_length..][0..4], 2);
+ modes.ctr(@TypeOf(aes), aes, m, c, j, builtin.Endian.Big);
+ }
+ };
+}
+
+const htest = @import("test.zig");
+const testing = std.testing;
+
+test "AES256GCM - Empty message and no associated data" {
+ const key: [AES256GCM.key_length]u8 = [_]u8{0x69} ** AES256GCM.key_length;
+ const nonce: [AES256GCM.nonce_length]u8 = [_]u8{0x42} ** AES256GCM.nonce_length;
+ const ad = "";
+ const m = "";
+ var c: [m.len]u8 = undefined;
+ var m2: [m.len]u8 = undefined;
+ var tag: [AES256GCM.tag_length]u8 = undefined;
+
+ AES256GCM.encrypt(&c, &tag, m, ad, nonce, key);
+ htest.assertEqual("6b6ff610a16fa4cd59f1fb7903154e92", &tag);
+}
+
+test "AES256GCM - Associated data only" {
+ const key: [AES256GCM.key_length]u8 = [_]u8{0x69} ** AES256GCM.key_length;
+ const nonce: [AES256GCM.nonce_length]u8 = [_]u8{0x42} ** AES256GCM.nonce_length;
+ const m = "";
+ const ad = "Test with associated data";
+ var c: [m.len]u8 = undefined;
+ var tag: [AES256GCM.tag_length]u8 = undefined;
+
+ AES256GCM.encrypt(&c, &tag, m, ad, nonce, key);
+ htest.assertEqual("262ed164c2dfb26e080a9d108dd9dd4c", &tag);
+}
+
+test "AES256GCM - Message only" {
+ const key: [AES256GCM.key_length]u8 = [_]u8{0x69} ** AES256GCM.key_length;
+ const nonce: [AES256GCM.nonce_length]u8 = [_]u8{0x42} ** AES256GCM.nonce_length;
+ const m = "Test with message only";
+ const ad = "";
+ var c: [m.len]u8 = undefined;
+ var m2: [m.len]u8 = undefined;
+ var tag: [AES256GCM.tag_length]u8 = undefined;
+
+ AES256GCM.encrypt(&c, &tag, m, ad, nonce, key);
+ try AES256GCM.decrypt(&m2, &c, tag, ad, nonce, key);
+ testing.expectEqualSlices(u8, m[0..], m2[0..]);
+
+ htest.assertEqual("5ca1642d90009fea33d01f78cf6eefaf01d539472f7c", &c);
+ htest.assertEqual("07cd7fc9103e2f9e9bf2dfaa319caff4", &tag);
+}
+
+test "AES256GCM - Message and associated data" {
+ const key: [AES256GCM.key_length]u8 = [_]u8{0x69} ** AES256GCM.key_length;
+ const nonce: [AES256GCM.nonce_length]u8 = [_]u8{0x42} ** AES256GCM.nonce_length;
+ const m = "Test with message";
+ const ad = "Test with associated data";
+ var c: [m.len]u8 = undefined;
+ var m2: [m.len]u8 = undefined;
+ var tag: [AES256GCM.tag_length]u8 = undefined;
+
+ AES256GCM.encrypt(&c, &tag, m, ad, nonce, key);
+ try AES256GCM.decrypt(&m2, &c, tag, ad, nonce, key);
+ testing.expectEqualSlices(u8, m[0..], m2[0..]);
+
+ htest.assertEqual("5ca1642d90009fea33d01f78cf6eefaf01", &c);
+ htest.assertEqual("64accec679d444e2373bd9f6796c0d2c", &tag);
+}
diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig
index 3c7e3445a2..1db3a1e870 100644
--- a/lib/std/crypto/benchmark.zig
+++ b/lib/std/crypto/benchmark.zig
@@ -57,6 +57,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64
}
const macs = [_]Crypto{
+ Crypto{ .ty = crypto.onetimeauth.Ghash, .name = "ghash" },
Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" },
Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" },
Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" },
@@ -151,6 +152,8 @@ const aeads = [_]Crypto{
Crypto{ .ty = crypto.aead.Gimli, .name = "gimli-aead" },
Crypto{ .ty = crypto.aead.AEGIS128L, .name = "aegis-128l" },
Crypto{ .ty = crypto.aead.AEGIS256, .name = "aegis-256" },
+ Crypto{ .ty = crypto.aead.AES128GCM, .name = "aes128-gcm" },
+ Crypto{ .ty = crypto.aead.AES256GCM, .name = "aes256-gcm" },
};
pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 {
diff --git a/lib/std/crypto/ghash.zig b/lib/std/crypto/ghash.zig
new file mode 100644
index 0000000000..04bc6a8275
--- /dev/null
+++ b/lib/std/crypto/ghash.zig
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2020 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+//
+// Adapted from BearSSL's ctmul64 implementation originally written by Thomas Pornin <pornin@bolet.org>
+
+const std = @import("../std.zig");
+const assert = std.debug.assert;
+const math = std.math;
+const mem = std.mem;
+
+/// GHASH is a universal hash function that features multiplication
+/// by a fixed parameter within a Galois field.
+///
+/// It is not a general purpose hash function - The key must be secret, unpredictable and never reused.
+///
+/// GHASH is typically used to compute the authentication tag in the AES-GCM construction.
+pub const Ghash = struct {
+ pub const block_size: usize = 16;
+ pub const mac_length = 16;
+ pub const minimum_key_length = 16;
+
+ y0: u64 = 0,
+ y1: u64 = 0,
+ h0: u64,
+ h1: u64,
+ h2: u64,
+ h0r: u64,
+ h1r: u64,
+ h2r: u64,
+
+ hh0: u64 = undefined,
+ hh1: u64 = undefined,
+ hh2: u64 = undefined,
+ hh0r: u64 = undefined,
+ hh1r: u64 = undefined,
+ hh2r: u64 = undefined,
+
+ leftover: usize = 0,
+ buf: [block_size]u8 align(16) = undefined,
+
+ pub fn init(key: *const [minimum_key_length]u8) Ghash {
+ const h1 = mem.readIntBig(u64, key[0..8]);
+ const h0 = mem.readIntBig(u64, key[8..16]);
+ const h1r = @bitReverse(u64, h1);
+ const h0r = @bitReverse(u64, h0);
+ const h2 = h0 ^ h1;
+ const h2r = h0r ^ h1r;
+
+ if (std.builtin.mode == .ReleaseSmall) {
+ return Ghash{
+ .h0 = h0,
+ .h1 = h1,
+ .h2 = h2,
+ .h0r = h0r,
+ .h1r = h1r,
+ .h2r = h2r,
+ };
+ } else {
+ // Precompute H^2
+ var hh = Ghash{
+ .h0 = h0,
+ .h1 = h1,
+ .h2 = h2,
+ .h0r = h0r,
+ .h1r = h1r,
+ .h2r = h2r,
+ };
+ hh.update(key);
+ const hh1 = hh.y1;
+ const hh0 = hh.y0;
+ const hh1r = @bitReverse(u64, hh1);
+ const hh0r = @bitReverse(u64, hh0);
+ const hh2 = hh0 ^ hh1;
+ const hh2r = hh0r ^ hh1r;
+
+ return Ghash{
+ .h0 = h0,
+ .h1 = h1,
+ .h2 = h2,
+ .h0r = h0r,
+ .h1r = h1r,
+ .h2r = h2r,
+
+ .hh0 = hh0,
+ .hh1 = hh1,
+ .hh2 = hh2,
+ .hh0r = hh0r,
+ .hh1r = hh1r,
+ .hh2r = hh2r,
+ };
+ }
+ }
+
+ inline fn clmul_pclmul(x: u64, y: u64) u64 {
+ const Vector = std.meta.Vector;
+ const product = asm (
+ \\ vpclmulqdq $0x00, %[x], %[y], %[out]
+ : [out] "=x" (-> Vector(2, u64))
+ : [x] "x" (@bitCast(Vector(2, u64), @as(u128, x))),
+ [y] "x" (@bitCast(Vector(2, u64), @as(u128, y)))
+ );
+ return product[0];
+ }
+
+ fn clmul_soft(x: u64, y: u64) u64 {
+ const x0 = x & 0x1111111111111111;
+ const x1 = x & 0x2222222222222222;
+ const x2 = x & 0x4444444444444444;
+ const x3 = x & 0x8888888888888888;
+ const y0 = y & 0x1111111111111111;
+ const y1 = y & 0x2222222222222222;
+ const y2 = y & 0x4444444444444444;
+ const y3 = y & 0x8888888888888888;
+ var z0 = (x0 *% y0) ^ (x1 *% y3) ^ (x2 *% y2) ^ (x3 *% y1);
+ var z1 = (x0 *% y1) ^ (x1 *% y0) ^ (x2 *% y3) ^ (x3 *% y2);
+ var z2 = (x0 *% y2) ^ (x1 *% y1) ^ (x2 *% y0) ^ (x3 *% y3);
+ var z3 = (x0 *% y3) ^ (x1 *% y2) ^ (x2 *% y1) ^ (x3 *% y0);
+ z0 &= 0x1111111111111111;
+ z1 &= 0x2222222222222222;
+ z2 &= 0x4444444444444444;
+ z3 &= 0x8888888888888888;
+ return z0 | z1 | z2 | z3;
+ }
+
+ const has_pclmul = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .pclmul);
+ const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx);
+ const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) clmul_pclmul else clmul_soft;
+
+ fn blocks(st: *Ghash, msg: []const u8) void {
+ assert(msg.len % 16 == 0); // GHASH blocks() expects full blocks
+ var y1 = st.y1;
+ var y0 = st.y0;
+
+ var i: usize = 0;
+
+ // 2-blocks aggregated reduction
+ if (std.builtin.mode != .ReleaseSmall) {
+ while (i + 32 <= msg.len) : (i += 32) {
+ // B0 * H^2 unreduced
+ y1 ^= mem.readIntBig(u64, msg[i..][0..8]);
+ y0 ^= mem.readIntBig(u64, msg[i..][8..16]);
+
+ const y1r = @bitReverse(u64, y1);
+ const y0r = @bitReverse(u64, y0);
+ const y2 = y0 ^ y1;
+ const y2r = y0r ^ y1r;
+
+ var z0 = clmul(y0, st.hh0);
+ var z1 = clmul(y1, st.hh1);
+ var z2 = clmul(y2, st.hh2) ^ z0 ^ z1;
+ var z0h = clmul(y0r, st.hh0r);
+ var z1h = clmul(y1r, st.hh1r);
+ var z2h = clmul(y2r, st.hh2r) ^ z0h ^ z1h;
+
+ // B1 * H unreduced
+ const sy1 = mem.readIntBig(u64, msg[i..][16..24]);
+ const sy0 = mem.readIntBig(u64, msg[i..][24..32]);
+
+ const sy1r = @bitReverse(u64, sy1);
+ const sy0r = @bitReverse(u64, sy0);
+ const sy2 = sy0 ^ sy1;
+ const sy2r = sy0r ^ sy1r;
+
+ const sz0 = clmul(sy0, st.h0);
+ const sz1 = clmul(sy1, st.h1);
+ const sz2 = clmul(sy2, st.h2) ^ sz0 ^ sz1;
+ const sz0h = clmul(sy0r, st.h0r);
+ const sz1h = clmul(sy1r, st.h1r);
+ const sz2h = clmul(sy2r, st.h2r) ^ sz0h ^ sz1h;
+
+ // ((B0 * H^2) + B1 * H) (mod M)
+ z0 ^= sz0;
+ z1 ^= sz1;
+ z2 ^= sz2;
+ z0h ^= sz0h;
+ z1h ^= sz1h;
+ z2h ^= sz2h;
+ z0h = @bitReverse(u64, z0h) >> 1;
+ z1h = @bitReverse(u64, z1h) >> 1;
+ z2h = @bitReverse(u64, z2h) >> 1;
+
+ var v3 = z1h;
+ var v2 = z1 ^ z2h;
+ var v1 = z0h ^ z2;
+ var v0 = z0;
+
+ v3 = (v3 << 1) | (v2 >> 63);
+ v2 = (v2 << 1) | (v1 >> 63);
+ v1 = (v1 << 1) | (v0 >> 63);
+ v0 = (v0 << 1);
+
+ v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
+ v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
+ y1 = v3 ^ v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
+ y0 = v2 ^ (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
+ }
+ }
+
+ // single block
+ while (i + 16 <= msg.len) : (i += 16) {
+ y1 ^= mem.readIntBig(u64, msg[i..][0..8]);
+ y0 ^= mem.readIntBig(u64, msg[i..][8..16]);
+
+ const y1r = @bitReverse(u64, y1);
+ const y0r = @bitReverse(u64, y0);
+ const y2 = y0 ^ y1;
+ const y2r = y0r ^ y1r;
+
+ const z0 = clmul(y0, st.h0);
+ const z1 = clmul(y1, st.h1);
+ var z2 = clmul(y2, st.h2) ^ z0 ^ z1;
+ var z0h = clmul(y0r, st.h0r);
+ var z1h = clmul(y1r, st.h1r);
+ var z2h = clmul(y2r, st.h2r) ^ z0h ^ z1h;
+ z0h = @bitReverse(u64, z0h) >> 1;
+ z1h = @bitReverse(u64, z1h) >> 1;
+ z2h = @bitReverse(u64, z2h) >> 1;
+
+ // shift & reduce
+ var v3 = z1h;
+ var v2 = z1 ^ z2h;
+ var v1 = z0h ^ z2;
+ var v0 = z0;
+
+ v3 = (v3 << 1) | (v2 >> 63);
+ v2 = (v2 << 1) | (v1 >> 63);
+ v1 = (v1 << 1) | (v0 >> 63);
+ v0 = (v0 << 1);
+
+ v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
+ v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
+ y1 = v3 ^ v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
+ y0 = v2 ^ (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
+ }
+ st.y1 = y1;
+ st.y0 = y0;
+ }
+
+ pub fn update(st: *Ghash, m: []const u8) void {
+ var mb = m;
+
+ if (st.leftover > 0) {
+ const want = math.min(block_size - st.leftover, mb.len);
+ const mc = mb[0..want];
+ for (mc) |x, i| {
+ st.buf[st.leftover + i] = x;
+ }
+ mb = mb[want..];
+ st.leftover += want;
+ if (st.leftover < block_size) {
+ return;
+ }
+ st.blocks(&st.buf);
+ st.leftover = 0;
+ }
+ if (mb.len >= block_size) {
+ const want = mb.len & ~(block_size - 1);
+ st.blocks(mb[0..want]);
+ mb = mb[want..];
+ }
+ if (mb.len > 0) {
+ for (mb) |x, i| {
+ st.buf[st.leftover + i] = x;
+ }
+ st.leftover += mb.len;
+ }
+ }
+
+ /// Zero-pad to align the next input to the first byte of a block
+ pub fn pad(st: *Ghash) void {
+ if (st.leftover == 0) {
+ return;
+ }
+ var i = st.leftover;
+ while (i < block_size) : (i += 1) {
+ st.buf[i] = 0;
+ }
+ st.blocks(&st.buf);
+ st.leftover = 0;
+ }
+
+ pub fn final(st: *Ghash, out: *[mac_length]u8) void {
+ st.pad();
+ mem.writeIntBig(u64, out[0..8], st.y1);
+ mem.writeIntBig(u64, out[8..16], st.y0);
+
+ mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Ghash)]);
+ }
+
+ pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void {
+ var st = Ghash.init(key);
+ st.update(msg);
+ st.final(out);
+ }
+};
+
+const htest = @import("test.zig");
+
+test "ghash" {
+ const key = [_]u8{0x42} ** 16;
+ const m = [_]u8{0x69} ** 256;
+
+ var st = Ghash.init(&key);
+ st.update(&m);
+ var out: [16]u8 = undefined;
+ st.final(&out);
+ htest.assertEqual("889295fa746e8b174bf4ec80a65dea41", &out);
+
+ st = Ghash.init(&key);
+ st.update(m[0..100]);
+ st.update(m[100..]);
+ st.final(&out);
+ htest.assertEqual("889295fa746e8b174bf4ec80a65dea41", &out);
+}
diff --git a/lib/std/crypto/hkdf.zig b/lib/std/crypto/hkdf.zig
new file mode 100644
index 0000000000..7ac3603637
--- /dev/null
+++ b/lib/std/crypto/hkdf.zig
@@ -0,0 +1,66 @@
+const std = @import("../std.zig");
+const assert = std.debug.assert;
+const hmac = std.crypto.auth.hmac;
+const mem = std.mem;
+
+/// HKDF-SHA256
+pub const HkdfSha256 = Hkdf(hmac.sha2.HmacSha256);
+
+/// HKDF-SHA512
+pub const HkdfSha512 = Hkdf(hmac.sha2.HmacSha512);
+
+/// The Hkdf construction takes some source of initial keying material and
+/// derives one or more uniform keys from it.
+pub fn Hkdf(comptime Hmac: type) type {
+ return struct {
+ /// Return a master key from a salt and initial keying material.
+ fn extract(salt: []const u8, ikm: []const u8) [Hmac.mac_length]u8 {
+ var prk: [Hmac.mac_length]u8 = undefined;
+ Hmac.create(&prk, ikm, salt);
+ return prk;
+ }
+
+ /// Derive a subkey from a master key `prk` and a subkey description `ctx`.
+ fn expand(out: []u8, ctx: []const u8, prk: [Hmac.mac_length]u8) void {
+ assert(out.len < Hmac.mac_length * 255); // output size is too large for the Hkdf construction
+ var i: usize = 0;
+ var counter = [1]u8{1};
+ while (i + Hmac.mac_length <= out.len) : (i += Hmac.mac_length) {
+ var st = Hmac.init(&prk);
+ if (i != 0) {
+ st.update(out[i - Hmac.mac_length ..][0..Hmac.mac_length]);
+ }
+ st.update(ctx);
+ st.update(&counter);
+ st.final(out[i..][0..Hmac.mac_length]);
+ counter[0] += 1;
+ }
+ const left = out.len % Hmac.mac_length;
+ if (left > 0) {
+ var st = Hmac.init(&prk);
+ if (i != 0) {
+ st.update(out[i - Hmac.mac_length ..][0..Hmac.mac_length]);
+ }
+ st.update(ctx);
+ st.update(&counter);
+ var tmp: [Hmac.mac_length]u8 = undefined;
+ st.final(tmp[0..Hmac.mac_length]);
+ mem.copy(u8, out[i..][0..left], tmp[0..left]);
+ }
+ }
+ };
+}
+
+const htest = @import("test.zig");
+
+test "Hkdf" {
+ const ikm = [_]u8{0x0b} ** 22;
+ const salt = [_]u8{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c };
+ const context = [_]u8{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 };
+ const kdf = HkdfSha256;
+ const prk = kdf.extract(&salt, &ikm);
+ htest.assertEqual("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", &prk);
+ var out: [42]u8 = undefined;
+ kdf.expand(&out, &context, prk);
+ htest.assertEqual("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", &out);
+}
diff --git a/lib/std/crypto/poly1305.zig b/lib/std/crypto/poly1305.zig
index a95b9d7cb3..c6613f64ba 100644
--- a/lib/std/crypto/poly1305.zig
+++ b/lib/std/crypto/poly1305.zig
@@ -22,8 +22,7 @@ pub const Poly1305 = struct {
// partial block buffer
buf: [block_size]u8 align(16) = undefined,
- pub fn init(key: []const u8) Poly1305 {
- std.debug.assert(key.len >= minimum_key_length);
+ pub fn init(key: *const [minimum_key_length]u8) Poly1305 {
const t0 = mem.readIntLittle(u64, key[0..8]);
const t1 = mem.readIntLittle(u64, key[8..16]);
return Poly1305{
@@ -92,7 +91,7 @@ pub const Poly1305 = struct {
}
mb = mb[want..];
st.leftover += want;
- if (st.leftover > block_size) {
+ if (st.leftover < block_size) {
return;
}
st.blocks(&st.buf, false);
@@ -115,8 +114,20 @@ pub const Poly1305 = struct {
}
}
- pub fn final(st: *Poly1305, out: []u8) void {
- std.debug.assert(out.len >= mac_length);
+ /// Zero-pad to align the next input to the first byte of a block
+ pub fn pad(st: *Poly1305) void {
+ if (st.leftover == 0) {
+ return;
+ }
+ var i = st.leftover;
+ while (i < block_size) : (i += 1) {
+ st.buf[i] = 0;
+ }
+ st.blocks(&st.buf);
+ st.leftover = 0;
+ }
+
+ pub fn final(st: *Poly1305, out: *[mac_length]u8) void {
if (st.leftover > 0) {
var i = st.leftover;
st.buf[i] = 1;
@@ -187,10 +198,7 @@ pub const Poly1305 = struct {
std.mem.secureZero(u8, @ptrCast([*]u8, st)[0..@sizeOf(Poly1305)]);
}
- pub fn create(out: []u8, msg: []const u8, key: []const u8) void {
- std.debug.assert(out.len >= mac_length);
- std.debug.assert(key.len >= minimum_key_length);
-
+ pub fn create(out: *[mac_length]u8, msg: []const u8, key: *const [minimum_key_length]u8) void {
var st = Poly1305.init(key);
st.update(msg);
st.final(out);
diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig
index 2ed9f938d8..226d5f1d52 100644
--- a/lib/std/event/loop.zig
+++ b/lib/std/event/loop.zig
@@ -647,6 +647,31 @@ pub const Loop = struct {
}
}
+ /// Runs the provided function asynchronously. The function's frame is allocated
+ /// with `allocator` and freed when the function returns.
+ /// `func` must return void and it can be an async function.
+ /// Yields to the event loop, running the function on the next tick.
+ pub fn runDetached(self: *Loop, alloc: *mem.Allocator, comptime func: anytype, args: anytype) error{OutOfMemory}!void {
+ if (!std.io.is_async) @compileError("Can't use runDetached in non-async mode!");
+ if (@TypeOf(@call(.{}, func, args)) != void) {
+ @compileError("`func` must not have a return value");
+ }
+
+ const Wrapper = struct {
+ const Args = @TypeOf(args);
+ fn run(func_args: Args, loop: *Loop, allocator: *mem.Allocator) void {
+ loop.yield();
+ const result = @call(.{}, func, func_args);
+ suspend {
+ allocator.destroy(@frame());
+ }
+ }
+ };
+
+ var run_frame = try alloc.create(@Frame(Wrapper.run));
+ run_frame.* = async Wrapper.run(args, self, alloc);
+ }
+
/// Yielding lets the event loop run, starting any unstarted async operations.
/// Note that async operations automatically start when a function yields for any other reason,
/// for example, when async I/O is performed. This function is intended to be used only when
@@ -1493,3 +1518,33 @@ fn testEventLoop2(h: anyframe->i32, did_it: *bool) void {
testing.expect(value == 1234);
did_it.* = true;
}
+
+var testRunDetachedData: usize = 0;
+test "std.event.Loop - runDetached" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+ if (!std.io.is_async) return error.SkipZigTest;
+ if (true) {
+ // https://github.com/ziglang/zig/issues/4922
+ return error.SkipZigTest;
+ }
+
+ var loop: Loop = undefined;
+ try loop.initMultiThreaded();
+ defer loop.deinit();
+
+ // Schedule the execution, won't actually start until we start the
+ // event loop.
+ try loop.runDetached(std.testing.allocator, testRunDetached, .{});
+
+ // Now we can start the event loop. The function will return only
+ // after all tasks have been completed, allowing us to synchonize
+ // with the previous runDetached.
+ loop.run();
+
+ testing.expect(testRunDetachedData == 1);
+}
+
+fn testRunDetached() void {
+ testRunDetachedData += 1;
+}
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index 56a1aba217..ab2cc1577d 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -1181,6 +1181,16 @@ fn bufPrintIntToSlice(buf: []u8, value: anytype, base: u8, uppercase: bool, opti
return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
}
+pub fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args)]u8 {
+ comptime var buf: [count(fmt, args)]u8 = undefined;
+ _ = bufPrint(&buf, fmt, args) catch unreachable;
+ return &buf;
+}
+
+test "comptimePrint" {
+ std.testing.expectEqualSlices(u8, "100", comptime comptimePrint("{}", .{100}));
+}
+
test "parse u64 digit too big" {
_ = parseUnsigned(u64, "123a", 10) catch |err| {
if (err == error.InvalidCharacter) return;
diff --git a/lib/std/fs.zig b/lib/std/fs.zig
index 1890d7e136..22d243612a 100644
--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -1856,7 +1856,7 @@ pub const Dir = struct {
}
};
-/// Returns an handle to the current working directory. It is not opened with iteration capability.
+/// Returns a handle to the current working directory. It is not opened with iteration capability.
/// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.
/// On POSIX targets, this function is comptime-callable.
pub fn cwd() Dir {
@@ -2162,7 +2162,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File {
return openFileAbsoluteZ(buf[0..self_exe_path.len :0].ptr, flags);
}
-pub const SelfExePathError = os.ReadLinkError || os.SysCtlError;
+pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathError;
/// `selfExePath` except allocates the result on the heap.
/// Caller owns returned memory.
@@ -2190,10 +2190,18 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 {
/// TODO make the return type of this a null terminated pointer
pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 {
if (is_darwin) {
- var u32_len: u32 = @intCast(u32, math.min(out_buffer.len, math.maxInt(u32)));
- const rc = std.c._NSGetExecutablePath(out_buffer.ptr, &u32_len);
+ // Note that _NSGetExecutablePath() will return "a path" to
+ // the executable not a "real path" to the executable.
+ var symlink_path_buf: [MAX_PATH_BYTES:0]u8 = undefined;
+ var u32_len: u32 = MAX_PATH_BYTES + 1; // include the sentinel
+ const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len);
if (rc != 0) return error.NameTooLong;
- return mem.spanZ(@ptrCast([*:0]u8, out_buffer));
+
+ var real_path_buf: [MAX_PATH_BYTES]u8 = undefined;
+ const real_path = try std.os.realpathZ(&symlink_path_buf, &real_path_buf);
+ if (real_path.len > out_buffer.len) return error.NameTooLong;
+ std.mem.copy(u8, out_buffer, real_path);
+ return out_buffer[0..real_path.len];
}
switch (builtin.os.tag) {
.linux => return os.readlinkZ("/proc/self/exe", out_buffer),
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index 8d4f5df2e8..bfa6dec3ed 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -615,7 +615,7 @@ pub const File = struct {
}
}
- pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: usize) PWriteError!usize {
+ pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!usize {
if (is_windows) {
// TODO improve this to use WriteFileScatter
if (iovecs.len == 0) return @as(usize, 0);
@@ -632,11 +632,11 @@ pub const File = struct {
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial writes from the underlying OS layer.
- pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: usize) PWriteError!void {
+ pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!void {
if (iovecs.len == 0) return;
var i: usize = 0;
- var off: usize = 0;
+ var off: u64 = 0;
while (true) {
var amt = try self.pwritev(iovecs[i..], offset + off);
off += amt;
@@ -652,14 +652,16 @@ pub const File = struct {
pub const CopyRangeError = os.CopyFileRangeError;
- pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) CopyRangeError!usize {
- return os.copy_file_range(in.handle, in_offset, out.handle, out_offset, len, 0);
+ pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {
+ const adjusted_len = math.cast(usize, len) catch math.maxInt(usize);
+ const result = try os.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0);
+ return result;
}
/// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it
/// means the in file reached the end. Reaching the end of a file is not an error condition.
- pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) CopyRangeError!usize {
- var total_bytes_copied: usize = 0;
+ pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 {
+ var total_bytes_copied: u64 = 0;
var in_off = in_offset;
var out_off = out_offset;
while (total_bytes_copied < len) {
diff --git a/lib/std/macho.zig b/lib/std/macho.zig
index d3296ee171..bb22991d06 100644
--- a/lib/std/macho.zig
+++ b/lib/std/macho.zig
@@ -1257,3 +1257,47 @@ pub const reloc_type_x86_64 = packed enum(u4) {
/// for thread local variables
X86_64_RELOC_TLV,
};
+
+/// This symbol is a reference to an external non-lazy (data) symbol.
+pub const REFERENCE_FLAG_UNDEFINED_NON_LAZY: u16 = 0x0;
+
+/// This symbol is a reference to an external lazy symbol—that is, to a function call.
+pub const REFERENCE_FLAG_UNDEFINED_LAZY: u16 = 0x1;
+
+/// This symbol is defined in this module.
+pub const REFERENCE_FLAG_DEFINED: u16 = 0x2;
+
+/// This symbol is defined in this module and is visible only to modules within this shared library.
+pub const REFERENCE_FLAG_PRIVATE_DEFINED: u16 = 3;
+
+/// This symbol is defined in another module in this file, is a non-lazy (data) symbol, and is visible
+/// only to modules within this shared library.
+pub const REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY: u16 = 4;
+
+/// This symbol is defined in another module in this file, is a lazy (function) symbol, and is visible
+/// only to modules within this shared library.
+pub const REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY: u16 = 5;
+
+/// Must be set for any defined symbol that is referenced by dynamic-loader APIs (such as dlsym and
+/// NSLookupSymbolInImage) and not ordinary undefined symbol references. The strip tool uses this bit
+/// to avoid removing symbols that must exist: If the symbol has this bit set, strip does not strip it.
+pub const REFERENCED_DYNAMICALLY: u16 = 0x10;
+
+/// Used by the dynamic linker at runtime. Do not set this bit.
+pub const N_DESC_DISCARDED: u16 = 0x20;
+
+/// Indicates that this symbol is a weak reference. If the dynamic linker cannot find a definition
+/// for this symbol, it sets the address of this symbol to 0. The static linker sets this symbol given
+/// the appropriate weak-linking flags.
+pub const N_WEAK_REF: u16 = 0x40;
+
+/// Indicates that this symbol is a weak definition. If the static linker or the dynamic linker finds
+/// another (non-weak) definition for this symbol, the weak definition is ignored. Only symbols in a
+/// coalesced section (page 23) can be marked as a weak definition.
+pub const N_WEAK_DEF: u16 = 0x80;
+
+/// The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
+/// that the function is actually a resolver function and should
+/// be called to get the address of the real function to use.
+/// This bit is only available in .o files (MH_OBJECT filetype)
+pub const N_SYMBOL_RESOLVER: u16 = 0x100;
diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig
index 19f6d0809e..54ad2f55d0 100644
--- a/lib/std/math/big/int.zig
+++ b/lib/std/math/big/int.zig
@@ -58,6 +58,11 @@ pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize {
return (string_len + (limb_bits / base - 1)) / (limb_bits / base);
}
+pub fn calcPowLimbsBufferLen(a_bit_count: usize, y: usize) usize {
+ // The 2 accounts for the minimum space requirement for llmulacc
+ return 2 + (a_bit_count * y + (limb_bits - 1)) / limb_bits;
+}
+
/// a + b * c + *carry, sets carry to the overflow bits
pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb {
@setRuntimeSafety(debug_safety);
@@ -597,6 +602,52 @@ pub const Mutable = struct {
return gcdLehmer(rma, x_copy, y_copy, limbs_buffer);
}
+ /// q = a ^ b
+ ///
+ /// r may not alias a.
+ ///
+ /// Asserts that `r` has enough limbs to store the result. Upper bound is
+ /// `calcPowLimbsBufferLen(a.bitCountAbs(), b)`.
+ ///
+ /// `limbs_buffer` is used for temporary storage.
+ /// The amount required is given by `calcPowLimbsBufferLen`.
+ pub fn pow(r: *Mutable, a: Const, b: u32, limbs_buffer: []Limb) !void {
+ assert(r.limbs.ptr != a.limbs.ptr); // illegal aliasing
+
+ // Handle all the trivial cases first
+ switch (b) {
+ 0 => {
+ // a^0 = 1
+ return r.set(1);
+ },
+ 1 => {
+ // a^1 = a
+ return r.copy(a);
+ },
+ else => {},
+ }
+
+ if (a.eqZero()) {
+ // 0^b = 0
+ return r.set(0);
+ } else if (a.limbs.len == 1 and a.limbs[0] == 1) {
+ // 1^b = 1 and -1^b = ±1
+ r.set(1);
+ r.positive = a.positive or (b & 1) == 0;
+ return;
+ }
+
+ // Here a>1 and b>1
+ const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b);
+ assert(r.limbs.len >= needed_limbs);
+ assert(limbs_buffer.len >= needed_limbs);
+
+ llpow(r.limbs, a.limbs, b, limbs_buffer);
+
+ r.normalize(needed_limbs);
+ r.positive = a.positive or (b & 1) == 0;
+ }
+
/// rma may not alias x or y.
/// x and y may alias each other.
/// Asserts that `rma` has enough limbs to store the result. Upper bound is given by `calcGcdNoAliasLimbLen`.
@@ -1775,6 +1826,29 @@ pub const Managed = struct {
try m.gcd(x.toConst(), y.toConst(), &limbs_buffer);
rma.setMetadata(m.positive, m.len);
}
+
+ pub fn pow(rma: *Managed, a: Managed, b: u32) !void {
+ const needed_limbs = calcPowLimbsBufferLen(a.bitCountAbs(), b);
+
+ const limbs_buffer = try rma.allocator.alloc(Limb, needed_limbs);
+ defer rma.allocator.free(limbs_buffer);
+
+ if (rma.limbs.ptr == a.limbs.ptr) {
+ var m = try Managed.initCapacity(rma.allocator, needed_limbs);
+ errdefer m.deinit();
+ var m_mut = m.toMutable();
+ try m_mut.pow(a.toConst(), b, limbs_buffer);
+ m.setMetadata(m_mut.positive, m_mut.len);
+
+ rma.deinit();
+ rma.swap(&m);
+ } else {
+ try rma.ensureCapacity(needed_limbs);
+ var rma_mut = rma.toMutable();
+ try rma_mut.pow(a.toConst(), b, limbs_buffer);
+ rma.setMetadata(rma_mut.positive, rma_mut.len);
+ }
+ }
};
/// Knuth 4.3.1, Algorithm M.
@@ -2129,6 +2203,56 @@ fn llxor(r: []Limb, a: []const Limb, b: []const Limb) void {
}
}
+/// Knuth 4.6.3
+fn llpow(r: []Limb, a: []const Limb, b: u32, tmp_limbs: []Limb) void {
+ var tmp1: []Limb = undefined;
+ var tmp2: []Limb = undefined;
+
+ // Multiplication requires no aliasing between the operand and the result
+ // variable, use the output limbs and another temporary set to overcome this
+ // limitation.
+ // The initial assignment makes the result end in `r` so an extra memory
+ // copy is saved, each 1 flips the index twice so it's a no-op so count the
+ // 0.
+ const b_leading_zeros = @intCast(u5, @clz(u32, b));
+ const exp_zeros = @popCount(u32, ~b) - b_leading_zeros;
+ if (exp_zeros & 1 != 0) {
+ tmp1 = tmp_limbs;
+ tmp2 = r;
+ } else {
+ tmp1 = r;
+ tmp2 = tmp_limbs;
+ }
+
+ const a_norm = a[0..llnormalize(a)];
+
+ mem.copy(Limb, tmp1, a_norm);
+ mem.set(Limb, tmp1[a_norm.len..], 0);
+
+ // Scan the exponent as a binary number, from left to right, dropping the
+ // most significant bit set.
+ const exp_bits = @intCast(u5, 31 - b_leading_zeros);
+ var exp = @bitReverse(u32, b) >> 1 + b_leading_zeros;
+
+ var i: u5 = 0;
+ while (i < exp_bits) : (i += 1) {
+ // Square
+ {
+ mem.set(Limb, tmp2, 0);
+ const op = tmp1[0..llnormalize(tmp1)];
+ llmulacc(null, tmp2, op, op);
+ mem.swap([]Limb, &tmp1, &tmp2);
+ }
+ // Multiply by a
+ if (exp & 1 != 0) {
+ mem.set(Limb, tmp2, 0);
+ llmulacc(null, tmp2, tmp1[0..llnormalize(tmp1)], a_norm);
+ mem.swap([]Limb, &tmp1, &tmp2);
+ }
+ exp >>= 1;
+ }
+}
+
// Storage must live for the lifetime of the returned value
fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable {
assert(storage.len >= 2);
diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig
index 9de93e94ac..5d07bee9b5 100644
--- a/lib/std/math/big/int_test.zig
+++ b/lib/std/math/big/int_test.zig
@@ -1480,3 +1480,55 @@ test "big.int const to managed" {
testing.expect(a.toConst().eq(b.toConst()));
}
+
+test "big.int pow" {
+ {
+ var a = try Managed.initSet(testing.allocator, 10);
+ defer a.deinit();
+
+ try a.pow(a, 8);
+ testing.expectEqual(@as(u32, 100000000), try a.to(u32));
+ }
+ {
+ var a = try Managed.initSet(testing.allocator, 10);
+ defer a.deinit();
+
+ var y = try Managed.init(testing.allocator);
+ defer y.deinit();
+
+ // y and a are not aliased
+ try y.pow(a, 123);
+ // y and a are aliased
+ try a.pow(a, 123);
+
+ testing.expect(a.eq(y));
+
+ const ys = try y.toString(testing.allocator, 16, false);
+ defer testing.allocator.free(ys);
+ testing.expectEqualSlices(
+ u8,
+ "183425a5f872f126e00a5ad62c839075cd6846c6fb0230887c7ad7a9dc530fcb" ++
+ "4933f60e8000000000000000000000000000000",
+ ys,
+ );
+ }
+ // Special cases
+ {
+ var a = try Managed.initSet(testing.allocator, 0);
+ defer a.deinit();
+
+ try a.pow(a, 100);
+ testing.expectEqual(@as(i32, 0), try a.to(i32));
+
+ try a.set(1);
+ try a.pow(a, 0);
+ testing.expectEqual(@as(i32, 1), try a.to(i32));
+ try a.pow(a, 100);
+ testing.expectEqual(@as(i32, 1), try a.to(i32));
+ try a.set(-1);
+ try a.pow(a, 15);
+ testing.expectEqual(@as(i32, -1), try a.to(i32));
+ try a.pow(a, 16);
+ testing.expectEqual(@as(i32, 1), try a.to(i32));
+ }
+}
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 492e497ff4..79b0424e96 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -854,6 +854,7 @@ pub fn ArgsTuple(comptime Function: type) type {
.field_type = arg.arg_type.?,
.default_value = @as(?(arg.arg_type.?), null),
.is_comptime = false,
+ .alignment = @alignOf(arg.arg_type.?),
};
}
@@ -884,6 +885,7 @@ pub fn Tuple(comptime types: []const type) type {
.field_type = T,
.default_value = @as(?T, null),
.is_comptime = false,
+ .alignment = @alignOf(T),
};
}
diff --git a/lib/std/meta/trailer_flags.zig b/lib/std/meta/trailer_flags.zig
index c8c1323686..6cd8dc9357 100644
--- a/lib/std/meta/trailer_flags.zig
+++ b/lib/std/meta/trailer_flags.zig
@@ -47,6 +47,7 @@ pub fn TrailerFlags(comptime Fields: type) type {
@as(?struct_field.field_type, null),
),
.is_comptime = false,
+ .alignment = @alignOf(?struct_field.field_type),
};
}
break :blk @Type(.{
diff --git a/lib/std/os.zig b/lib/std/os.zig
index c06ce4ed00..c89f122c63 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -3993,7 +3993,7 @@ pub const RealPathError = error{
/// Expands all symbolic links and resolves references to `.`, `..`, and
/// extra `/` characters in `pathname`.
/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.
-/// See also `realpathC` and `realpathW`.
+/// See also `realpathZ` and `realpathW`.
pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
if (builtin.os.tag == .windows) {
const pathname_w = try windows.sliceToPrefixedFileW(pathname);
@@ -5410,3 +5410,33 @@ pub fn prctl(option: i32, args: anytype) PrctlError!u31 {
else => |err| return std.os.unexpectedErrno(err),
}
}
+
+pub const GetrlimitError = UnexpectedError;
+
+pub fn getrlimit(resource: rlimit_resource) GetrlimitError!rlimit {
+ // TODO implement for systems other than linux and enable test
+ var limits: rlimit = undefined;
+ const rc = system.getrlimit(resource, &limits);
+ switch (errno(rc)) {
+ 0 => return limits,
+ EFAULT => unreachable, // bogus pointer
+ EINVAL => unreachable,
+ else => |err| return std.os.unexpectedErrno(err),
+ }
+}
+
+pub const SetrlimitError = error{
+ PermissionDenied,
+} || UnexpectedError;
+
+pub fn setrlimit(resource: rlimit_resource, limits: rlimit) SetrlimitError!void {
+ // TODO implement for systems other than linux and enable test
+ const rc = system.setrlimit(resource, &limits);
+ switch (errno(rc)) {
+ 0 => return,
+ EFAULT => unreachable, // bogus pointer
+ EINVAL => unreachable,
+ EPERM => return error.PermissionDenied,
+ else => |err| return std.os.unexpectedErrno(err),
+ }
+}
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig
index df31bc32fd..1ead0c7961 100644
--- a/lib/std/os/bits/linux.zig
+++ b/lib/std/os/bits/linux.zig
@@ -1890,3 +1890,79 @@ pub const ifreq = extern struct {
data: ?[*]u8,
},
};
+
+// doc comments copied from musl
+pub const rlimit_resource = extern enum(c_int) {
+ /// Per-process CPU limit, in seconds.
+ CPU,
+
+ /// Largest file that can be created, in bytes.
+ FSIZE,
+
+ /// Maximum size of data segment, in bytes.
+ DATA,
+
+ /// Maximum size of stack segment, in bytes.
+ STACK,
+
+ /// Largest core file that can be created, in bytes.
+ CORE,
+
+ /// Largest resident set size, in bytes.
+ /// This affects swapping; processes that are exceeding their
+ /// resident set size will be more likely to have physical memory
+ /// taken from them.
+ RSS,
+
+ /// Number of processes.
+ NPROC,
+
+ /// Number of open files.
+ NOFILE,
+
+ /// Locked-in-memory address space.
+ MEMLOCK,
+
+ /// Address space limit.
+ AS,
+
+ /// Maximum number of file locks.
+ LOCKS,
+
+ /// Maximum number of pending signals.
+ SIGPENDING,
+
+ /// Maximum bytes in POSIX message queues.
+ MSGQUEUE,
+
+ /// Maximum nice priority allowed to raise to.
+ /// Nice levels 19 .. -20 correspond to 0 .. 39
+ /// values of this resource limit.
+ NICE,
+
+ /// Maximum realtime priority allowed for non-priviledged
+ /// processes.
+ RTPRIO,
+
+ /// Maximum CPU time in µs that a process scheduled under a real-time
+ /// scheduling policy may consume without making a blocking system
+ /// call before being forcibly descheduled.
+ RTTIME,
+
+ _,
+};
+
+pub const rlim_t = u64;
+
+/// No limit
+pub const RLIM_INFINITY = ~@as(rlim_t, 0);
+
+pub const RLIM_SAVED_MAX = RLIM_INFINITY;
+pub const RLIM_SAVED_CUR = RLIM_INFINITY;
+
+pub const rlimit = extern struct {
+ /// Soft limit
+ cur: rlim_t,
+ /// Hard limit
+ max: rlim_t,
+};
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 50d1e4ae78..e38d9bc10d 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -1263,6 +1263,26 @@ pub fn prctl(option: i32, arg2: usize, arg3: usize, arg4: usize, arg5: usize) us
return syscall5(.prctl, @bitCast(usize, @as(isize, option)), arg2, arg3, arg4, arg5);
}
+pub fn getrlimit(resource: rlimit_resource, rlim: *rlimit) usize {
+ // use prlimit64 to have 64 bit limits on 32 bit platforms
+ return prlimit(0, resource, null, rlim);
+}
+
+pub fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) usize {
+ // use prlimit64 to have 64 bit limits on 32 bit platforms
+ return prlimit(0, resource, rlim, null);
+}
+
+pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit, old_limit: ?*rlimit) usize {
+ return syscall4(
+ .prlimit64,
+ @bitCast(usize, @as(isize, pid)),
+ @bitCast(usize, @as(isize, @enumToInt(resource))),
+ @ptrToInt(new_limit),
+ @ptrToInt(old_limit)
+ );
+}
+
test "" {
if (builtin.os.tag == .linux) {
_ = @import("linux/test.zig");
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig
index 0a453d8b2e..aee1b9549a 100644
--- a/lib/std/os/test.zig
+++ b/lib/std/os/test.zig
@@ -591,3 +591,13 @@ test "fsync" {
try os.fsync(file.handle);
try os.fdatasync(file.handle);
}
+
+test "getrlimit and setrlimit" {
+ // TODO enable for other systems when implemented
+ if(builtin.os.tag != .linux){
+ return error.SkipZigTest;
+ }
+
+ const cpuLimit = try os.getrlimit(.CPU);
+ try os.setrlimit(.CPU, cpuLimit);
+}
diff --git a/lib/std/packed_int_array.zig b/lib/std/packed_int_array.zig
index de99afa303..f25ff0b1b8 100644
--- a/lib/std/packed_int_array.zig
+++ b/lib/std/packed_int_array.zig
@@ -318,9 +318,12 @@ pub fn PackedIntSliceEndian(comptime Int: type, comptime endian: builtin.Endian)
};
}
+const we_are_testing_this_with_stage1_which_leaks_comptime_memory = true;
+
test "PackedIntArray" {
// TODO @setEvalBranchQuota generates panics in wasm32. Investigate.
if (builtin.arch == .wasm32) return error.SkipZigTest;
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
@setEvalBranchQuota(10000);
const max_bits = 256;
@@ -358,6 +361,7 @@ test "PackedIntArray" {
}
test "PackedIntArray init" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
const PackedArray = PackedIntArray(u3, 8);
var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 });
var i = @as(usize, 0);
@@ -367,6 +371,7 @@ test "PackedIntArray init" {
test "PackedIntSlice" {
// TODO @setEvalBranchQuota generates panics in wasm32. Investigate.
if (builtin.arch == .wasm32) return error.SkipZigTest;
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
@setEvalBranchQuota(10000);
const max_bits = 256;
@@ -405,6 +410,7 @@ test "PackedIntSlice" {
}
test "PackedIntSlice of PackedInt(Array/Slice)" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
const max_bits = 16;
const int_count = 19;
@@ -470,6 +476,7 @@ test "PackedIntSlice of PackedInt(Array/Slice)" {
}
test "PackedIntSlice accumulating bit offsets" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
//bit_offset is u3, so standard debugging asserts should catch
// anything
{
@@ -497,6 +504,8 @@ test "PackedIntSlice accumulating bit offsets" {
//@NOTE: As I do not have a big endian system to test this on,
// big endian values were not tested
test "PackedInt(Array/Slice) sliceCast" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
+
const PackedArray = PackedIntArray(u1, 16);
var packed_array = PackedArray.init([_]u1{ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
const packed_slice_cast_2 = packed_array.sliceCast(u2);
@@ -537,6 +546,8 @@ test "PackedInt(Array/Slice) sliceCast" {
}
test "PackedInt(Array/Slice)Endian" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
+
{
const PackedArrayBe = PackedIntArrayEndian(u4, .Big, 8);
var packed_array_be = PackedArrayBe.init([_]u4{ 0, 1, 2, 3, 4, 5, 6, 7 });
@@ -604,6 +615,8 @@ test "PackedInt(Array/Slice)Endian" {
// after this one is not mapped and will cause a segfault if we
// don't account for the bounds.
test "PackedIntArray at end of available memory" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
+
switch (builtin.os.tag) {
.linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
else => return,
@@ -623,6 +636,8 @@ test "PackedIntArray at end of available memory" {
}
test "PackedIntSlice at end of available memory" {
+ if (we_are_testing_this_with_stage1_which_leaks_comptime_memory) return error.SkipZigTest;
+
switch (builtin.os.tag) {
.linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
else => return,
diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig
index d13d0b22ef..b1947058cc 100644
--- a/lib/std/zig/system.zig
+++ b/lib/std/zig/system.zig
@@ -213,6 +213,8 @@ pub const NativeTargetInfo = struct {
// kernel version
const kernel_version = if (mem.indexOfScalar(u8, release, '-')) |pos|
release[0..pos]
+ else if (mem.indexOfScalar(u8, release, '_')) |pos|
+ release[0..pos]
else
release;