Add typing_extensions.Buffer (#125)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d330a0f..d4bc032 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# Unreleased
+
+- Add `typing_extensions.Buffer`, a marker class for buffer types, as proposed
+  by PEP 688. Equivalent to `collections.abc.Buffer` in Python 3.12. Patch by
+  Jelle Zijlstra.
+
 # Release 4.5.0 (February 14, 2023)
 
 - Runtime support for PEP 702, adding `typing_extensions.deprecated`. Patch
diff --git a/README.md b/README.md
index 6da36c3..b29378b 100644
--- a/README.md
+++ b/README.md
@@ -35,11 +35,15 @@
 
 - Experimental features
 
-  - `override` (see [PEP 698](https://peps.python.org/pep-0698/))
   - The `default=` argument to `TypeVar`, `ParamSpec`, and `TypeVarTuple` (see [PEP 696](https://peps.python.org/pep-0696/))
   - The `infer_variance=` argument to `TypeVar` (see [PEP 695](https://peps.python.org/pep-0695/))
   - The `@deprecated` decorator (see [PEP 702](https://peps.python.org/pep-0702/))
 
+- In the standard library since Python 3.12
+
+  - `override` (equivalent to `typing.override`; see [PEP 698](https://peps.python.org/pep-0698/))
+  - `Buffer` (equivalent to `collections.abc.Buffer`; see [PEP 688](https://peps.python.org/pep-0688/))
+
 - In `typing` since Python 3.11
 
   - `assert_never`
@@ -159,4 +163,4 @@
 ## Running tests
 
 To run tests, navigate into the appropriate source directory and run
-`test_typing_extensions.py`.
\ No newline at end of file
+`test_typing_extensions.py`.
diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py
index 7f9e59a..b4e21d6 100644
--- a/src/test_typing_extensions.py
+++ b/src/test_typing_extensions.py
@@ -29,7 +29,7 @@
 from typing_extensions import assert_type, get_type_hints, get_origin, get_args
 from typing_extensions import clear_overloads, get_overloads, overload
 from typing_extensions import NamedTuple
-from typing_extensions import override, deprecated
+from typing_extensions import override, deprecated, Buffer
 from _typed_dict_test_helper import Foo, FooGeneric
 import warnings
 
@@ -3677,5 +3677,35 @@
                 self.assertEqual(z.__infer_variance__, typevar.__infer_variance__)
 
 
+class BufferTests(BaseTestCase):
+    def test(self):
+        self.assertIsInstance(memoryview(b''), Buffer)
+        self.assertIsInstance(bytearray(), Buffer)
+        self.assertIsInstance(b"x", Buffer)
+        self.assertNotIsInstance(1, Buffer)
+
+        self.assertIsSubclass(bytearray, Buffer)
+        self.assertIsSubclass(memoryview, Buffer)
+        self.assertIsSubclass(bytes, Buffer)
+        self.assertNotIsSubclass(int, Buffer)
+
+        class MyRegisteredBuffer:
+            def __buffer__(self, flags: int) -> memoryview:
+                return memoryview(b'')
+
+        self.assertNotIsInstance(MyRegisteredBuffer(), Buffer)
+        self.assertNotIsSubclass(MyRegisteredBuffer, Buffer)
+        Buffer.register(MyRegisteredBuffer)
+        self.assertIsInstance(MyRegisteredBuffer(), Buffer)
+        self.assertIsSubclass(MyRegisteredBuffer, Buffer)
+
+        class MySubclassedBuffer(Buffer):
+            def __buffer__(self, flags: int) -> memoryview:
+                return memoryview(b'')
+
+        self.assertIsInstance(MySubclassedBuffer(), Buffer)
+        self.assertIsSubclass(MySubclassedBuffer, Buffer)
+
+
 if __name__ == '__main__':
     main()
diff --git a/src/typing_extensions.py b/src/typing_extensions.py
index 71d2a7a..b29e37c 100644
--- a/src/typing_extensions.py
+++ b/src/typing_extensions.py
@@ -33,6 +33,7 @@
     'Coroutine',
     'AsyncGenerator',
     'AsyncContextManager',
+    'Buffer',
     'ChainMap',
 
     # Concrete collection types.
@@ -2318,3 +2319,32 @@
         return (_NamedTuple,)
 
     NamedTuple.__mro_entries__ = _namedtuple_mro_entries
+
+
+if hasattr(collections.abc, "Buffer"):
+    Buffer = collections.abc.Buffer
+else:
+    class Buffer(abc.ABC):
+        """Base class for classes that implement the buffer protocol.
+
+        The buffer protocol allows Python objects to expose a low-level
+        memory buffer interface. Before Python 3.12, it is not possible
+        to implement the buffer protocol in pure Python code, or even
+        to check whether a class implements the buffer protocol. In
+        Python 3.12 and higher, the ``__buffer__`` method allows access
+        to the buffer protocol from Python code, and the
+        ``collections.abc.Buffer`` ABC allows checking whether a class
+        implements the buffer protocol.
+
+        To indicate support for the buffer protocol in earlier versions,
+        inherit from this ABC, either in a stub file or at runtime,
+        or use ABC registration. This ABC provides no methods, because
+        there is no Python-accessible methods shared by pre-3.12 buffer
+        classes. It is useful primarily for static checks.
+
+        """
+
+    # As a courtesy, register the most common stdlib buffer classes.
+    Buffer.register(memoryview)
+    Buffer.register(bytearray)
+    Buffer.register(bytes)